Example #1
0
int
verify_pwd_hash(const char *p, char *hash, unsigned int nullok)
{
	size_t hash_len;
	char *pp = NULL;
	int retval;
	D(("called"));

	strip_hpux_aging(hash);
	hash_len = strlen(hash);
	if (!hash_len) {
		/* the stored password is NULL */
		if (nullok) { /* this means we've succeeded */
			D(("user has empty password - access granted"));
			retval = PAM_SUCCESS;
		} else {
			D(("user has empty password - access denied"));
			retval = PAM_AUTH_ERR;
		}
	} else if (!p || *hash == '*' || *hash == '!') {
		retval = PAM_AUTH_ERR;
	} else {
		if (!strncmp(hash, "$1$", 3)) {
			pp = Goodcrypt_md5(p, hash);
		    	if (pp && strcmp(pp, hash) != 0) {
				_pam_delete(pp);
				pp = Brokencrypt_md5(p, hash);
		    	}
		} else if (*hash != '$' && hash_len >= 13) {
		    	pp = bigcrypt(p, hash);
		    	if (pp && hash_len == 13 && strlen(pp) > hash_len) {
				_pam_overwrite(pp + hash_len);
		    	}
		} else {
                	/*
			 * Ok, we don't know the crypt algorithm, but maybe
			 * libcrypt knows about it? We should try it.
			 */
#ifdef HAVE_CRYPT_R
			struct crypt_data *cdata;
			cdata = malloc(sizeof(*cdata));
			if (cdata != NULL) {
				cdata->initialized = 0;
				pp = x_strdup(crypt_r(p, hash, cdata));
				memset(cdata, '\0', sizeof(*cdata));
				free(cdata);
			}
#else
			pp = x_strdup(crypt(p, hash));
#endif
		}
		p = NULL;		/* no longer needed here */

		/* the moment of truth -- do we agree with the password? */
		D(("comparing state of pp[%s] and hash[%s]", pp, hash));

		if (pp && strcmp(pp, hash) == 0) {
			retval = PAM_SUCCESS;
		} else {
			retval = PAM_AUTH_ERR;
		}
	}

	if (pp)
		_pam_delete(pp);
	D(("done [%d].", retval));

	return retval;
}
Example #2
0
static int _unix_verify_password(const char *name, const char *p, int opt)
{
	struct passwd *pwd = NULL;
	struct spwd *spwdent = NULL;
	char *salt = NULL;
	char *pp = NULL;
	int retval = UNIX_FAILED;

	/* UNIX passwords area */
	setpwent();
	pwd = getpwnam(name);	/* Get password file entry... */
	endpwent();
	if (pwd != NULL) {
		if (strcmp(pwd->pw_passwd, "x") == 0) {
			/*
			 * ...and shadow password file entry for this user,
			 * if shadowing is enabled
			 */
			setspent();
			spwdent = getspnam(name);
			endspent();
			if (spwdent != NULL)
				salt = x_strdup(spwdent->sp_pwdp);
			else
				pwd = NULL;
		} else {
			if (strcmp(pwd->pw_passwd, "*NP*") == 0) {	/* NIS+ */
				uid_t save_uid;

				save_uid = geteuid();
				seteuid(pwd->pw_uid);
				spwdent = getspnam(name);
				seteuid(save_uid);

				salt = x_strdup(spwdent->sp_pwdp);
			} else {
				salt = x_strdup(pwd->pw_passwd);
			}
		}
	}
	if (pwd == NULL || salt == NULL) {
		_log_err(LOG_ALERT, "check pass; user unknown");
		p = NULL;
		return retval;
	}

	if (strlen(salt) == 0)
		return (opt == 0) ? UNIX_FAILED : UNIX_PASSED;

	/* the moment of truth -- do we agree with the password? */
	retval = UNIX_FAILED;
	if (!strncmp(salt, "$1$", 3)) {
		pp = Goodcrypt_md5(p, salt);
		if (strcmp(pp, salt) == 0) {
			retval = UNIX_PASSED;
		} else {
			pp = Brokencrypt_md5(p, salt);
			if (strcmp(pp, salt) == 0)
				retval = UNIX_PASSED;
		}
	} else {
		pp = bigcrypt(p, salt);
		if (strcmp(pp, salt) == 0) {
			retval = UNIX_PASSED;
		}
	}
	p = NULL;		/* no longer needed here */

	/* clean up */
	{
		char *tp = pp;
		if (pp != NULL) {
			while (tp && *tp)
				*tp++ = '\0';
		}
		pp = tp = NULL;
	}

	return retval;
}
Example #3
0
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
				   int argc, const char **argv) {
    int i;
    const char *name;
    char const * password;
    char const * pwdfilename = NULL;
    char const * stored_crypted_password = NULL;
    char const * crypted_password;
    FILE *pwdfile;
    int use_flock = 0;
    int use_delay = 1;
    int legacy_crypt = 0;
    int debug = 0;
    char * linebuf = NULL;
    size_t linebuflen;
#ifdef USE_CRYPT_R
    struct crypt_data crypt_buf;
#endif
    
    /* we require the pwdfile switch and argument to be present, else we don't work */
    for (i = 0; i < argc; ++i) {
	if (!strcmp(argv[i], "pwdfile") && i + 1 < argc)
	    pwdfilename = argv[++i];
	else if (!strncmp(argv[i], "pwdfile=", strlen("pwdfile=")))
	    pwdfilename = argv[i] + strlen("pwdfile=");
	else if (!strcmp(argv[i], "flock"))
	    use_flock = 1;
	else if (!strcmp(argv[i], "noflock"))
	    use_flock = 0;
	else if (!strcmp(argv[i], "nodelay"))
	    use_delay = 0;
	else if (!strcmp(argv[i], "debug"))
	    debug = 1;
	else if (!strcmp(argv[i], "legacy_crypt"))
	    legacy_crypt = 1;
    }
    
#ifdef HAVE_PAM_FAIL_DELAY
    if (use_delay) {
	if (debug) pam_syslog(pamh, LOG_DEBUG, "setting fail delay");
	(void) pam_fail_delay(pamh, 2000000);   /* 2 sec */
    }
#endif
    
    if (!pwdfilename) {
	pam_syslog(pamh, LOG_ERR, "password file name not specified");
	return PAM_AUTHINFO_UNAVAIL;
    }
    
    if (pam_get_user(pamh, &name, NULL) != PAM_SUCCESS) {
	pam_syslog(pamh, LOG_ERR, "couldn't get username from PAM stack");
	return PAM_AUTH_ERR;
    }
    if (debug) pam_syslog(pamh, LOG_DEBUG, "username is %s", name);
    
    if (!(pwdfile = fopen(pwdfilename, "r"))) {
	pam_syslog(pamh, LOG_ALERT, "couldn't open password file %s", pwdfilename);
	return PAM_AUTHINFO_UNAVAIL;
    }
    
    if (use_flock && lock_fd(fileno(pwdfile)) == -1) {
	pam_syslog(pamh, LOG_ALERT, "couldn't lock password file %s", pwdfilename);
	fclose(pwdfile);
	return PAM_AUTHINFO_UNAVAIL;
    }
    
    /* get the crypted password corresponding to this user out of pwdfile */
    while (getline(&linebuf, &linebuflen, pwdfile) > 0) {
	/* strsep changes its argument, make a copy */
	char * nexttok = linebuf;
	
	/* first field: username */
	char * curtok = strsep(&nexttok, ":");
	
	/* skip non-matching usernames */
	if (strcmp(curtok, name))
	    continue;
	
	/* second field: password (until next colon or newline) */
	if ((curtok = strsep(&nexttok, ":\n"))) {
	    stored_crypted_password = curtok;
	    break;
	}
    }
    fclose(pwdfile);
    /* we keep linebuf (allocated by getline), stored_crypted_password is pointing into it */

    if (!stored_crypted_password)
	if (debug) pam_syslog(pamh, LOG_ERR, "user not found in password database");
    
    if (stored_crypted_password && !strlen(stored_crypted_password)) {
	if (debug) pam_syslog(pamh, LOG_DEBUG, "user has empty password field");
	free(linebuf);
	return flags & PAM_DISALLOW_NULL_AUTHTOK ? PAM_AUTH_ERR : PAM_SUCCESS;
    }
    
    if (pam_get_authtok(pamh, PAM_AUTHTOK, &password, NULL) != PAM_SUCCESS) {
	pam_syslog(pamh, LOG_ERR, "couldn't get password from PAM stack");
	free(linebuf);
	return PAM_AUTH_ERR;
    }
    
    if (!stored_crypted_password) {
	free(linebuf);
	return PAM_USER_UNKNOWN;
    }
    
    if (debug) pam_syslog(pamh, LOG_DEBUG, "got crypted password == '%s'", stored_crypted_password);
    
#ifdef USE_CRYPT_R
    crypt_buf.initialized = 0;
    if (!(crypted_password = crypt_r(password, stored_crypted_password, &crypt_buf)))
#else
    if (!(crypted_password = crypt(password, stored_crypted_password)))
#endif
    {
	pam_syslog(pamh, LOG_ERR, "crypt() failed");
	free(linebuf);
	return PAM_AUTH_ERR;
    }
    
    if (legacy_crypt && strcmp(crypted_password, stored_crypted_password)) {
	if (!strncmp(stored_crypted_password, "$1$", 3))
	    crypted_password = Brokencrypt_md5(password, stored_crypted_password);
	else
	    crypted_password = bigcrypt(password, stored_crypted_password);
    }

    if (strcmp(crypted_password, stored_crypted_password)) {
	pam_syslog(pamh, LOG_NOTICE, "wrong password for user %s", name);
	free(linebuf);
	return PAM_AUTH_ERR;
    }
    
    if (debug) pam_syslog(pamh, LOG_DEBUG, "passwords match");
    free(linebuf);
    return PAM_SUCCESS;
}
Example #4
0
/* 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], stored_crypted_password[CRYPTED_BCPWD_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]+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);
    
#ifdef HAVE_PAM_FAIL_DELAY
    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: "******"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) {
	D(_pam_log(LOG_ERR,"password hash type is 'md5'"));
	/* 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_BCPWD_LEN] = '\0';

	if (strlen(stored_crypted_password) <= CRYPTED_DESPWD_LEN) {
	    D(_pam_log(LOG_ERR,"password hash type is 'crypt'"));
	    crypted_password = crypt(password, salt);
	} else {
	    D(_pam_log(LOG_ERR,"password hash type is 'bigcrypt'"));
	    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;
}