summaryrefslogtreecommitdiff
path: root/pam_pwdfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'pam_pwdfile.c')
-rw-r--r--pam_pwdfile.c533
1 files changed, 281 insertions, 252 deletions
diff --git a/pam_pwdfile.c b/pam_pwdfile.c
index 5a7f580..09b3fed 100644
--- a/pam_pwdfile.c
+++ b/pam_pwdfile.c
@@ -1,14 +1,14 @@
/* pam_pwdfile.c copyright 1999-2001 by Charl P. Botha <cpbotha@ieee.org>
*
- * $Id: pam_pwdfile.c,v 1.15 2001-07-14 20:50:21 cpbotha Exp $
+ * $Id: pam_pwdfile.c,v 1.16 2002-05-11 14:42:35 cpbotha Exp $
*
* pam authentication module that can be pointed at any username/crypted
* text file so that pam using application can use an alternate set of
* passwords than specified in system password database
*
- * version 0.95
+ * version 0.97
*
- * Copyright (c) Charl P. Botha, 1999-2001. All rights reserved
+ * Copyright (c) Charl P. Botha, 1999-2002. All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -60,8 +60,9 @@
#define PAM_SM_AUTH
#include <security/pam_modules.h>
-/* unistd.h does not declare this as it should */
-extern char *crypt(const char *key, const char *salt);
+#include "md5.h"
+/*extern char *crypt(const char *key, const char *salt);*/
+extern char *bigcrypt(const char *key, const char *salt);
#define PWDF_PARAM "pwdfile"
#define FLOCK_PARAM "flock"
@@ -82,30 +83,30 @@ int _set_auth_tok(pam_handle_t *, int, int, const char **);
/* logging function ripped from pam_listfile.c */
static void _pam_log(int err, const char *format, ...) {
- va_list args;
-
- va_start(args, format);
- openlog("pam_pwdfile", LOG_CONS|LOG_PID, LOG_AUTH);
- vsyslog(err, format, args);
- va_end(args);
- closelog();
+ va_list args;
+
+ va_start(args, format);
+ openlog("pam_pwdfile", LOG_CONS|LOG_PID, LOG_AUTH);
+ vsyslog(err, format, args);
+ va_end(args);
+ closelog();
}
static int lock_fd(int fd) {
- int delay;
-
- for (delay = 5; delay <= 40; delay *= 2) {
- if (flock(fd, LOCK_SH | LOCK_NB) == -1) {
- /* failed */
- if (errno != EWOULDBLOCK) goto failed;
- sleep(delay);
- }else{
- return 0;
- }
- }
- if (flock(fd, LOCK_SH | LOCK_NB) != -1) return 0;
-failed:
- return -1;
+ int delay;
+
+ for (delay = 5; delay <= 40; delay *= 2) {
+ if (flock(fd, LOCK_SH | LOCK_NB) == -1) {
+ /* failed */
+ if (errno != EWOULDBLOCK) goto failed;
+ sleep(delay);
+ }else{
+ return 0;
+ }
+ }
+ if (flock(fd, LOCK_SH | LOCK_NB) != -1) return 0;
+ failed:
+ return -1;
}
/* this function ripped from pam_unix/support.c */
@@ -113,47 +114,47 @@ int converse( pam_handle_t *pamh,
int nargs,
struct pam_message **message,
struct pam_response **response ) {
- int retval;
- struct pam_conv *conv;
-
- retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
- if ( retval == PAM_SUCCESS ) {
+ int retval;
+ struct pam_conv *conv;
+
+ retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
+ if ( retval == PAM_SUCCESS ) {
retval = conv->conv( nargs,
- ( const struct pam_message ** ) message,
- response,
- conv->appdata_ptr );
- }
- return retval;
+ ( const struct pam_message ** ) message,
+ response,
+ conv->appdata_ptr );
+ }
+ return retval;
}
/* this function ripped from pam_unix/support.c */
int _set_auth_tok( pam_handle_t *pamh,
int flags, int argc,
const char **argv ) {
- int retval;
- char *p;
-
- struct pam_message msg[1],*pmsg[1];
- struct pam_response *resp;
-
- /* set up conversation call */
-
- pmsg[0] = &msg[0];
- msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
- msg[0].msg = "Password: ";
- resp = NULL;
-
- if ( ( retval = converse( pamh, 1 , pmsg, &resp ) ) != PAM_SUCCESS )
- return retval;
-
- if ( resp )
- {
+ int retval;
+ char *p;
+
+ struct pam_message msg[1],*pmsg[1];
+ struct pam_response *resp;
+
+ /* set up conversation call */
+
+ pmsg[0] = &msg[0];
+ msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
+ msg[0].msg = "Password: ";
+ resp = NULL;
+
+ if ( ( retval = converse( pamh, 1 , pmsg, &resp ) ) != PAM_SUCCESS )
+ return retval;
+
+ if ( resp )
+ {
if ( ( flags & PAM_DISALLOW_NULL_AUTHTOK ) &&
- resp[0].resp == NULL )
- {
- free( resp );
- return PAM_AUTH_ERR;
- }
+ resp[0].resp == NULL )
+ {
+ free( resp );
+ return PAM_AUTH_ERR;
+ }
p = resp[ 0 ].resp;
@@ -164,13 +165,13 @@ int _set_auth_tok( pam_handle_t *pamh,
resp[ 0 ].resp = NULL;
- }
- else
- return PAM_CONV_ERR;
-
- free( resp );
- pam_set_item( pamh, PAM_AUTHTOK, p );
- return PAM_SUCCESS;
+ }
+ else
+ return PAM_CONV_ERR;
+
+ free( resp );
+ pam_set_item( pamh, PAM_AUTHTOK, p );
+ return PAM_SUCCESS;
}
@@ -179,211 +180,239 @@ int _set_auth_tok( pam_handle_t *pamh,
* if unsucessful, returns 0
*/
static int fgetpwnam(FILE *stream, const char *name, char *password) {
- char tempLine[256], *tpointer, *curname, *curpass, *fgr;
- int loopdone, pwdfound;
- int len;
-
- /* go to beginning of file */
- rewind(stream);
- /* some control variables */
- loopdone = pwdfound = 0;
- /* fgets should do this, but we make sure */
- tempLine[255] = '\0';
- /* iterate through lines in file, until end of file */
- do {
- /* get the current line */
- fgr = fgets(tempLine,255,stream);
- /* if it's valid, go on */
- if ( fgr != NULL) {
- /* first get the username out */
- tpointer = tempLine;
- curname = strsep(&tpointer,":");
- /* check to see if it's the right one */
- if (strcmp(curname,name)==0) {
- /* at least we know our loop is done */
- loopdone = 1;
- /* remove possible trailing newline */
- len = strlen(tpointer);
- if (tpointer[len - 1] == '\n')
- tpointer[len - 1] = '\0';
- /* get the password and put it in its place */
- curpass = strsep(&tpointer,":");
- if (curpass != NULL) {
- /* we use md5 pwd len, as this is just a safe maximum */
- strncpy(password,curpass,CRYPTED_MD5PWD_LEN+1);
- pwdfound = 1;
- } /* if (curpass... */
- } /* if (strcmp(curname... */
- } /* if (tempLine... */
- } while (fgr != NULL);
- return pwdfound;
+ char tempLine[256], *tpointer, *curname, *curpass, *fgr;
+ int loopdone, pwdfound;
+ int len;
+
+ /* go to beginning of file */
+ rewind(stream);
+ /* some control variables */
+ loopdone = pwdfound = 0;
+ /* fgets should do this, but we make sure */
+ tempLine[255] = '\0';
+ /* iterate through lines in file, until end of file */
+ do {
+ /* get the current line */
+ fgr = fgets(tempLine,255,stream);
+ /* if it's valid, go on */
+ if ( fgr != NULL) {
+ /* first get the username out */
+ tpointer = tempLine;
+ curname = strsep(&tpointer,":");
+ /* check to see if it's the right one */
+ if (strcmp(curname,name)==0) {
+ /* at least we know our loop is done */
+ loopdone = 1;
+ /* remove possible trailing newline */
+ len = strlen(tpointer);
+ if (tpointer[len - 1] == '\n')
+ tpointer[len - 1] = '\0';
+ /* get the password and put it in its place */
+ curpass = strsep(&tpointer,":");
+ if (curpass != NULL) {
+ /* we use md5 pwd len, as this is just a safe maximum */
+ strncpy(password,curpass,CRYPTED_MD5PWD_LEN+1);
+ pwdfound = 1;
+ } /* if (curpass... */
+ } /* if (strcmp(curname... */
+ } /* if (tempLine... */
+ } while (fgr != NULL);
+ return pwdfound;
}
/* expected hook for auth service */
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
int argc, const char **argv) {
- int retval, pcnt, pwdfilename_found;
- const char *name;
- char *password;
- char pwdfilename[PWDFN_LEN];
- char salt[12], crypted_password[CRYPTED_MD5PWD_LEN+1];
- FILE *pwdfile;
- int use_flock = 0;
- int use_delay = 1;
-
- /* we require the pwdfile switch and argument to be present, else we don't work */
- /* pcnt is the parameter counter variable for iterating through argv */
- pcnt = pwdfilename_found = 0;
- do {
- /* see if the current parameter looks like "pwdfile" */
- if (strcmp(argv[pcnt],PWDF_PARAM)==0) {
- /* if argv is long enough, grab the subsequent parameter */
- if (pcnt+1 < argc) {
+ int retval, pcnt, pwdfilename_found;
+ const char *name;
+ char *password;
+ char pwdfilename[PWDFN_LEN];
+ char salt[12], stored_crypted_password[CRYPTED_MD5PWD_LEN+1];
+ char *crypted_password;
+ FILE *pwdfile;
+ int use_flock = 0;
+ int use_delay = 1;
+ int temp_result = 0;
+
+ /* we require the pwdfile switch and argument to be present, else we don't work */
+ /* pcnt is the parameter counter variable for iterating through argv */
+ pcnt = pwdfilename_found = 0;
+ do {
+ /* see if the current parameter looks like "pwdfile" */
+ if (strcmp(argv[pcnt],PWDF_PARAM)==0) {
+ /* if argv is long enough, grab the subsequent parameter */
+ if (pcnt+1 < argc) {
+ /* make sure we can't overflow */
+ strncpy(pwdfilename,argv[++pcnt],PWDFN_LEN);
+ /* indicate that we've found it */
+ pwdfilename_found = 1;
+ }
+ /* also check for "pwdfile=blah" */
+ } else if (strncmp(argv[pcnt],PWDF_PARAM "=",sizeof(PWDF_PARAM "=")-1)==0) {
/* make sure we can't overflow */
- strncpy(pwdfilename,argv[++pcnt],PWDFN_LEN);
+ strncpy(pwdfilename,argv[pcnt]+sizeof(PWDF_PARAM),PWDFN_LEN);
/* indicate that we've found it */
pwdfilename_found = 1;
- }
- /* also check for "pwdfile=blah" */
- } else if (strncmp(argv[pcnt],PWDF_PARAM "=",sizeof(PWDF_PARAM "=")-1)==0) {
- /* make sure we can't overflow */
- strncpy(pwdfilename,argv[pcnt]+sizeof(PWDF_PARAM),PWDFN_LEN);
- /* indicate that we've found it */
- pwdfilename_found = 1;
- } else if (strcmp(argv[pcnt],FLOCK_PARAM)==0) {
- /* we have a "flock" parameter */
- use_flock = 1;
- } else if (strcmp(argv[pcnt],"no" FLOCK_PARAM)==0) {
- /* or a "noflock" parameter */
- use_flock = 0;
- } else if (strcmp(argv[pcnt],NODELAY_PARAM)==0) {
- /* no delay on authentication failure */
- use_delay = 0;
- }
-
- } while (++pcnt < argc);
-
+ } else if (strcmp(argv[pcnt],FLOCK_PARAM)==0) {
+ /* we have a "flock" parameter */
+ use_flock = 1;
+ } else if (strcmp(argv[pcnt],"no" FLOCK_PARAM)==0) {
+ /* or a "noflock" parameter */
+ use_flock = 0;
+ } else if (strcmp(argv[pcnt],NODELAY_PARAM)==0) {
+ /* no delay on authentication failure */
+ use_delay = 0;
+ }
+
+ } while (++pcnt < argc);
+
#ifdef HAVE_PAM_FAIL_DELAY
- if (use_delay) {
- D(("setting delay"));
- (void) pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */
- }
+ if (use_delay) {
+ D(("setting delay"));
+ (void) pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */
+ }
#endif
-
- /* for some or other reason, the password file wasn't specified */
- if (!pwdfilename_found) {
- _pam_log(LOG_ERR,"password file name not specified");
- return PAM_AUTHINFO_UNAVAIL;
- }
-
- /* DEBUG */
- D(_pam_log(LOG_ERR, "password filename extracted"));
-
- /* now try to open the password file */
- if ((pwdfile=fopen(pwdfilename,"r"))==NULL) {
- _pam_log(LOG_ERR,"couldn't open password file %s",pwdfilename);
- return PAM_AUTHINFO_UNAVAIL;
- }
-
- /* set a lock on the password file */
- if (use_flock && lock_fd(fileno(pwdfile)) == -1) {
- _pam_log(LOG_ERR,"couldn't lock password file %s",pwdfilename);
- return PAM_AUTHINFO_UNAVAIL;
- }
-
- /* get user name */
- if ((retval = pam_get_user(pamh,&name,"login: ")) != PAM_SUCCESS) {
- _pam_log(LOG_ERR, "username not found");
- fclose(pwdfile);
- return retval;
- }
-
-
- /* DEBUG */
- D(_pam_log(LOG_ERR,"username is %s", name));
-
- /* get password - code from pam_unix_auth.c */
- pam_get_item(pamh, PAM_AUTHTOK, (void *)&password);
- if (!password) {
- retval = _set_auth_tok(pamh, flags, argc, argv);
- if (retval!=PAM_SUCCESS) {
- fclose(pwdfile);
- return retval;
- }
- }
- pam_get_item(pamh, PAM_AUTHTOK, (void *)&password);
-
- if ((retval = pam_get_item(pamh, PAM_AUTHTOK, (void *)&password)) != PAM_SUCCESS) {
- _pam_log(LOG_ERR, "auth token not found");
- fclose(pwdfile);
- return retval;
- }
-
- /* DEBUG */
- D(_pam_log(LOG_ERR,"got password from user", password));
-
- /* now crypt password and compare to the user entry in the password file */
- /* first make sure password is long enough -- may I do this? */
- if (strlen(password)<2 || password==NULL) {
- _pam_log(LOG_ERR,"password too short or NULL");
- fclose(pwdfile);
- return PAM_AUTH_ERR;
- }
-
- /* get the crypted password corresponding to this user */
- if (!fgetpwnam(pwdfile, name, crypted_password)) {
- _pam_log(LOG_ERR,"user not found in password database");
- fclose(pwdfile);
- return PAM_AUTHINFO_UNAVAIL;
- }
-
- /* DEBUG */
- D(_pam_log(LOG_ERR,"got crypted password == '%s'", crypted_password));
-
- /* Extract the salt and set the passwd length, depending on MD5 or DES */
- if (strncmp(crypted_password, "$1$", 3) == 0) {
- strncpy(salt, crypted_password, 11);
- salt[11] = '\0';
- crypted_password[CRYPTED_MD5PWD_LEN] = '\0';
- } else {
- strncpy(salt, crypted_password, 2);
- salt[2] = '\0';
- crypted_password[CRYPTED_DESPWD_LEN] = '\0';
- }
-
- /* DEBUG */
- D(_pam_log(LOG_ERR,"user password crypted is '%s'", crypt(password,salt)));
-
- /* if things don't match up, complain */
- if (strcmp(crypt(password,salt),crypted_password)!=0) {
- _pam_log(LOG_ERR,"wrong password for user %s",name);
- fclose(pwdfile);
- return PAM_AUTH_ERR;
- }
-
- /* DEBUG */
- D(_pam_log(LOG_ERR,"passwords match"));
-
- /* we've gotten here, i.e. authentication was sucessful! */
- fclose(pwdfile);
- return PAM_SUCCESS;
+
+ /* for some or other reason, the password file wasn't specified */
+ if (!pwdfilename_found) {
+ _pam_log(LOG_ERR,"password file name not specified");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ /* DEBUG */
+ D(_pam_log(LOG_ERR, "password filename extracted"));
+
+ /* now try to open the password file */
+ if ((pwdfile=fopen(pwdfilename,"r"))==NULL) {
+ _pam_log(LOG_ERR,"couldn't open password file %s",pwdfilename);
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ /* set a lock on the password file */
+ if (use_flock && lock_fd(fileno(pwdfile)) == -1) {
+ _pam_log(LOG_ERR,"couldn't lock password file %s",pwdfilename);
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ /* get user name */
+ if ((retval = pam_get_user(pamh,&name,"login: ")) != PAM_SUCCESS) {
+ _pam_log(LOG_ERR, "username not found");
+ fclose(pwdfile);
+ return retval;
+ }
+
+
+ /* DEBUG */
+ D(_pam_log(LOG_ERR,"username is %s", name));
+
+ /* get password - code from pam_unix_auth.c */
+ pam_get_item(pamh, PAM_AUTHTOK, (void *)&password);
+ if (!password) {
+ retval = _set_auth_tok(pamh, flags, argc, argv);
+ if (retval!=PAM_SUCCESS) {
+ fclose(pwdfile);
+ return retval;
+ }
+ }
+ pam_get_item(pamh, PAM_AUTHTOK, (void *)&password);
+
+ if ((retval = pam_get_item(pamh, PAM_AUTHTOK, (void *)&password)) != PAM_SUCCESS) {
+ _pam_log(LOG_ERR, "auth token not found");
+ fclose(pwdfile);
+ return retval;
+ }
+
+ /* DEBUG */
+ D(_pam_log(LOG_ERR,"got password from user", password));
+
+ /* now crypt password and compare to the user entry in the password file */
+ /* first make sure password is long enough -- may I do this? */
+ if (strlen(password)<2 || password==NULL) {
+ _pam_log(LOG_ERR,"password too short or NULL");
+ fclose(pwdfile);
+ return PAM_AUTH_ERR;
+ }
+
+ /* get the crypted password corresponding to this user */
+ if (!fgetpwnam(pwdfile, name, stored_crypted_password)) {
+ _pam_log(LOG_ERR,"user not found in password database");
+ fclose(pwdfile);
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ /* DEBUG */
+ D(_pam_log(LOG_ERR,"got crypted password == '%s'", stored_crypted_password));
+
+
+ temp_result = 0;
+
+ /* Extract the salt and set the passwd length, depending on MD5 or DES */
+ if (strncmp(stored_crypted_password, "$1$", 3) == 0) {
+ /* get out the salt into "salt" */
+ strncpy(salt, stored_crypted_password, 11);
+ salt[11] = '\0';
+ stored_crypted_password[CRYPTED_MD5PWD_LEN] = '\0';
+ /* try both md5 crypts */
+ crypted_password = Goodcrypt_md5(password, salt);
+ if (strcmp(crypted_password, stored_crypted_password) == 0)
+ {
+ temp_result = 1;
+ }
+ else
+ {
+ crypted_password = Brokencrypt_md5(password, salt);
+ if (strcmp(crypted_password, stored_crypted_password) == 0)
+ {
+ temp_result = 1;
+ }
+ }
+ } else {
+ /* get the salt out into "salt" */
+ strncpy(salt, stored_crypted_password, 2);
+ salt[2] = '\0';
+ stored_crypted_password[CRYPTED_DESPWD_LEN] = '\0';
+
+ crypted_password = bigcrypt(password, salt);
+ if (strcmp(crypted_password, stored_crypted_password) == 0)
+ {
+ temp_result = 1;
+ }
+ }
+
+ /* DEBUG */
+ D(_pam_log(LOG_ERR,"user password crypted is '%s'", crypted_password));
+
+ /* if things don't match up, complain */
+ if (!temp_result)
+ {
+ _pam_log(LOG_ERR,"wrong password for user %s",name);
+ fclose(pwdfile);
+ return PAM_AUTH_ERR;
+ }
+
+ /* DEBUG */
+ D(_pam_log(LOG_ERR,"passwords match"));
+
+ /* we've gotten here, i.e. authentication was sucessful! */
+ fclose(pwdfile);
+ return PAM_SUCCESS;
}
/* another expected hook */
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
- return PAM_SUCCESS;
+ return PAM_SUCCESS;
}
#ifdef PAM_STATIC
struct pam_module _pam_listfile_modstruct = {
- "pam_pwdfile",
- pam_sm_authenticate,
- pam_sm_setcred,
- NULL,
- NULL,
- NULL,
- NULL,
+ "pam_pwdfile",
+ pam_sm_authenticate,
+ pam_sm_setcred,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
};
#endif