/* * $Id: pam_module_for_keylok_ii_parallel_dongle.c,v 1.2 2004/12/07 15:12:38 cinar Exp $ * * pam_keylok.c: is a PAM module demonstrating the user * authentication using Key-Lok II (TM) parallel dongle. * * Copyright (c) 2003 Ali Onur Cinar * * Latest version may be downloaded from http://www.zdo.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. And also please * DO NOT REMOVE my name, and give me CREDIT when you use * whole or a part of this program in an other program. * * To compile using GNU C Compiler: * $ cc -c pam_keylok.c * $ cc -shared -o pam_keylok.so pam_keylok.o kfunc32.o * $ install -c -m 755 pam_keylok.so /lib/security * * Post-Process: * Add the following line to your login program's PAM * configuration file (/etc/pam.d/login): * auth required pam_keylok.so * * Not: * kfunc32.o Key-Lok II library file comes with Key-Lok II SDK * and It does not come with this code. * * Disclaimer: * Key-Lok II (TM) Security System (C)Copyright 1982-1997 - * Microcomputer Applications, Inc - All rights reserved. * url: www.keylok.com * */ #include #include #include #include /* declare provided PAM extensions */ #define PAM_SM_AUTH /* include PAM */ #include #include /* client specific codes */ #define ValidateCode1 .... #define ValidateCode2 .... #define ValidateCode3 .... #define ClientIDCode1 .... #define ClientIDCode2 .... #define ReadCode1 .... #define ReadCode2 .... #define ReadCode3 .... /* codes for Key-Lok device */ #define TERMINATE -1 /* Key-Lok termin */ #define KLCHECK 1 /* Key-Lok check */ #define READAUTH 2 /* Key-Lok readauth*/ #define GETSN 3 /* Key-Lok getser# */ #define GETVARWORD 4 /* Key-Lok getword */ /* constants */ #define LOCAL_LOG_PREFIX "PAM-Key-Lok: " /* external prototypes from kfunc32.o */ extern unsigned long KFUNC(unsigned,unsigned,unsigned,unsigned); extern void RegisterWinDriver(void); /* prototypes */ static void KTASK(unsigned,unsigned,unsigned,unsigned); static unsigned RotateLeft(unsigned,int); static void _pam_log(int err, const char *format, ...); /* globals */ unsigned ReturnValue1, ReturnValue2; /* Key-Lok outputs */ /* RCS */ static char const rcsid[] = "$Id: pam_module_for_keylok_ii_parallel_dongle.c,v 1.2 2004/12/07 15:12:38 cinar Exp $"; PAM_EXTERN int pam_sm_authenticate( pam_handle_t *pamh, int flags, int argc, const char **argv) { /* variables */ struct passwd *pwd; /* passwd entry */ int pw_uid; /* current user_id */ int pw_gid; /* current group_id*/ int key_sn; /* Key-Lok serial# */ int key_uid; /* Key-Lok user_id */ int key_gid; /* Key-Lok group_id*/ int retval; /* dummy returnval */ const char *user; /* keeps username */ /* get username from PAM */ if ( ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) || (user == NULL) || (strlen(user) < 1) ) { _pam_log(LOG_ERR, LOCAL_LOG_PREFIX "No username returned from PAM"); return retval; } /* get user's account */ if ((pwd = getpwnam(user)) == NULL) { _pam_log(LOG_ERR, LOCAL_LOG_PREFIX "Unknown user %s", user); return PAM_SERVICE_ERR; } /* get user_id and group_id */ pw_uid = pwd->pw_uid; pw_gid = pwd->pw_gid; /* check the Key-Lok II device */ RegisterWinDriver(); KTASK((unsigned)(KLCHECK),ValidateCode1,ValidateCode2,ValidateCode3); KTASK(RotateLeft(ReturnValue1,ReturnValue2 & 7) ^ ReadCode3 ^ ReturnValue2,RotateLeft(ReturnValue2,ReturnValue1 & 15), ReturnValue1 ^ ReturnValue2, 0); if ((ReturnValue1 != ClientIDCode1)||(ReturnValue2 != ClientIDCode2)) { /* wrong Key-Lok device */ _pam_log(LOG_ERR, LOCAL_LOG_PREFIX "Wrong Key-Lok device"); /* return the error */ return PAM_SERVICE_ERR; } /* gain read access to Key-Lok */ KTASK(READAUTH, ReadCode1, ReadCode2, ReadCode3); /* get the serial number for logging purposes */ KTASK(GETSN, 0, 0, 0); key_sn = ReturnValue1; /* read the word at address 0 to compare with user_id */ KTASK(GETVARWORD, 0, 0, 0); /* first 0 is the address */ key_uid = ReturnValue1; /* read the word at address 1 to compare with group_id */ KTASK(GETVARWORD, 1, 0, 0); /* first 1 is the address */ key_gid = ReturnValue1; /* terminate the Key-Lok communication */ KTASK((unsigned)TERMINATE, 0, 0, 0); /* compare uid and gid with the values from Key-Lok */ if (pw_uid != key_uid || pw_gid != key_gid) { /* failed to authenticate */ _pam_log(LOG_ERR, LOCAL_LOG_PREFIX "%s failed to authenticate. (key: %d:%d sys: %d:%d sn# %d)", user, key_uid, key_gid, pw_uid, pw_gid, key_sn); return PAM_AUTH_ERR; } /* authenticated */ _pam_log(LOG_ERR, LOCAL_LOG_PREFIX "%s authenticated (sn# %d)", user, key_sn); return PAM_SUCCESS; } PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_SUCCESS; } /* * KTASK makes the security system call. */ static void KTASK(unsigned CommandCode, unsigned Argument2, unsigned Argument3, unsigned Argument4) { unsigned long ReturnValue; ReturnValue = KFUNC(CommandCode, Argument2, Argument3, Argument4); ReturnValue1 = (unsigned) (ReturnValue & 0XFFFF); ReturnValue2 = (unsigned) (ReturnValue >> 16); } /* * RotateLeft function rotates the bits in the Target left the * number of positions identified by the argument Counts */ static unsigned RotateLeft(unsigned Target, int Counts) { int i; static unsigned LocalTarget, HighBit; LocalTarget = Target; for (i=0; i> 15); } LocalTarget = LocalTarget & 0XFFFF; /* For 32 bit integers */ return (LocalTarget); } /* * Logs the event into PAM log file */ static void _pam_log(int err, const char *format, ...) { va_list args; va_start(args, format); vsyslog(LOG_AUTH | err, format, args); va_end(args); } #ifdef PAM_STATIC /* static module data */ struct pam_module _pam_keylok_modstruct = { "pam_keylok", pam_sm_authenticate, pam_sm_setcred, NULL, NULL, NULL, NULL, }; #endif