Key-Lok II is a dongle based software protection system for developers. For more information please visit www.keylok.com. In this article, we will create a PAM module to authenticate user logins using Key-Lok II dongles.
Key-Lok II is a dongle based software protection system for developers. For more information please visit www.keylok.com. In this article, we will create a PAM module to authenticate user logins using Key-Lok II dongles.
In order to login to the system, each user will need to have a dongle. After connecting the dongle to the machine, the PAM module will validate the dongle and it will login user to the system.
/*
* $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 <cinar(a)zdo.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <pwd.h>
/* declare provided PAM extensions */
#define PAM_SM_AUTH
/* include PAM */
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
/* 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<Counts; i++)
{
HighBit = LocalTarget & 0X8000;
LocalTarget = (LocalTarget << 1) + (HighBit >> 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