Exemple #1
0
int
secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth)
{
    char *pw_epasswd = auth->data;
#ifdef __alpha
    extern int crypt_type;

#  ifdef HAVE_DISPCRYPT
    if (strcmp(pw_epasswd, dispcrypt(pass, pw_epasswd, crypt_type)) == 0)
	return AUTH_SUCCESS;
#  else
    if (crypt_type == AUTH_CRYPT_BIGCRYPT) {
	if (strcmp(pw_epasswd, bigcrypt(pass, pw_epasswd)) == 0)
	    return AUTH_SUCCESS;
    } else if (crypt_type == AUTH_CRYPT_CRYPT16) {
	if (strcmp(pw_epasswd, crypt(pass, pw_epasswd)) == 0)
	    return AUTH_SUCCESS;
    }
#  endif /* HAVE_DISPCRYPT */
#elif defined(HAVE_BIGCRYPT)
    if (strcmp(pw_epasswd, bigcrypt(pass, pw_epasswd)) == 0)
	return AUTH_SUCCESS;
#endif /* __alpha */

	return AUTH_FAILURE;
}
Exemple #2
0
char *
xcrypt(const char *password, const char *salt)
{
	char *crypted;

	/*
	 * If we don't have a salt we are encrypting a fake password for
	 * for timing purposes.  Pick an appropriate salt.
	 */
	if (salt == NULL)
		salt = pick_salt();

# ifdef HAVE_MD5_PASSWORDS
	if (is_md5_salt(salt))
		crypted = md5_crypt(password, salt);
	else
		crypted = crypt(password, salt);
# elif defined(__hpux) && !defined(HAVE_SECUREWARE)
	if (iscomsec())
		crypted = bigcrypt(password, salt);
	else
		crypted = crypt(password, salt);
# elif defined(HAVE_SECUREWARE)
	crypted = bigcrypt(password, salt);
# else
	crypted = crypt(password, salt);
# endif

	return crypted;
}
Exemple #3
0
void priv_gpass(char *gpass)
{
    char *xgpass = NULL;
    struct acgrp *grp;
    uid_t uid;
    gid_t gid;

    if (group_given == 0) {
	reply(503, "Give group name with SITE GROUP first.");
	return;
    }
    /* OK, now they're getting a chance to specify a password.  Make them
     * give the group name again if they fail... */
    group_given = 0;

    grp = priv_getent(groupname);
    if (passbuf && gpass && *gpass != '\0' && grp && *grp->gpass != '\0')
#if defined(SecureWare) || defined(HPUX_10_TRUSTED)
	xgpass = bigcrypt(gpass, grp->gpass);
#else
	xgpass = crypt(gpass, grp->gpass);
#endif

    if (!(((gpass != NULL)
	   && (*gpass != '\0')
	   && (grp != NULL)
	   && (*grp->gpass != '\0')
	   && (strcmp(xgpass, grp->gpass) == 0))
	  || (((gpass == NULL)
	       || (*gpass == '\0'))
	      && (grp != NULL)
	      && (*grp->gpass == '\0'))
	)) {
	reply(530, "Group access request incorrect.");
	grp = NULL;
	if (++group_attempts >= lgi_failure_threshold) {
	    syslog(LOG_NOTICE,
		   "repeated group access failures from %s, group %s",
		   remoteident, groupname);
	    exit(0);
	}
	sleep(group_attempts);	/* slow down password crackers */
	return;
    }

    uid = geteuid();
    gid = grp->gr_gid;

    delay_signaling();		/* we can't allow any signals while euid==0: kinch */
    seteuid(0);
    setegid(gid);
    seteuid(uid);
    enable_signaling();		/* we can allow signals once again: kinch */

    reply(200, "Group access enabled.");
    group_attempts = 0;
}
int
main(int argc, char **argv)
{
	if (argc < 3) {
		fprintf(stderr, "Usage: %s password salt\n",
			strchr(argv[0], '/') ?
			(strchr(argv[0], '/') + 1) :
			argv[0]);
		return 0;
	}
	fprintf(stdout, "%s\n", bigcrypt(argv[1], argv[2]));
	return 0;
}
static Bool
passwds_match_p (const char *cleartext, const char *ciphertext)
{
  char *s = 0;  /* note that on some systems, crypt() may return null */

  s = (char *) crypt (cleartext, ciphertext);
  if (s && !strcmp (s, ciphertext))
    return True;

#ifdef HAVE_BIGCRYPT
  /* There seems to be no way to tell at runtime if an HP machine is in
     "trusted" mode, and thereby, which of crypt() or bigcrypt() we should
     be calling to compare passwords.  So call them both, and see which
     one works. */

  s = (char *) bigcrypt (cleartext, ciphertext);
  if (s && !strcmp (s, ciphertext))
    return True;

#endif /* HAVE_BIGCRYPT */
  
  return False;
}
Exemple #6
0
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
{
	struct passwd *pw = authctxt->pw;
	char *salt;
	int result;

	/* Just use the supplied fake password if authctxt is invalid */
	char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;

	/* Check for users with no password. */
	if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
		return (1);

	/* Encrypt the candidate password using the proper salt. */
	salt = (pw_password[0] && pw_password[1]) ? pw_password : "******";

	/*
	 * Authentication is accepted if the encrypted passwords
	 * are identical.
	 */
#ifdef UNIXWARE_LONG_PASSWORDS
	if (!nischeck(pw->pw_name)) {
		result = ((strcmp(bigcrypt(password, salt), pw_password) == 0)
		||  (strcmp(osr5bigcrypt(password, salt), pw_password) == 0));
	}
	else
#endif /* UNIXWARE_LONG_PASSWORDS */
		result = (strcmp(xcrypt(password, salt), pw_password) == 0);

#ifdef USE_LIBIAF
	if (authctxt->valid)
		free(pw_password);
#endif
	return(result);
}
/****************************************************************************
core of password checking routine
****************************************************************************/
BOOL password_check(char *password)
{

#ifdef USE_PAM
/* This falls through if the password check fails
	- if NO_CRYPT is defined this causes an error msg
		saying Warning - no crypt available
	- if NO_CRYPT is NOT defined this is a potential security hole
		as it may authenticate via the crypt call when PAM
		settings say it should fail.
  if (pam_auth(this_user,password)) return(True);
Hence we make a direct return to avoid a second chance!!!
*/
  return (pam_auth(this_user,password));
#endif

#ifdef AFS_AUTH
  if (afs_auth(this_user,password)) return(True);
#endif

#ifdef DFS_AUTH
  if (dfs_auth(this_user,password)) return(True);
#endif 

#ifdef KRB5_AUTH
  if (krb5_auth(this_user,password)) return(True);
#endif

#ifdef KRB4_AUTH
  if (krb4_auth(this_user,password)) return(True);
#endif

#ifdef PWDAUTH
  if (pwdauth(this_user,password) == 0)
    return(True);
#endif

#ifdef OSF1_ENH_SEC
  {
    BOOL ret = (strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
    if(!ret) {
      DEBUG(2,("password_check: OSF1_ENH_SEC failed. Trying normal crypt.\n"));
      ret = (strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
    }
    return ret;
  }
#endif

#ifdef ULTRIX_AUTH
  return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
#endif

#ifdef LINUX_BIGCRYPT
  return(linux_bigcrypt(password,this_salt,this_crypted));
#endif

#ifdef HPUX_10_TRUSTED
  return(strcmp(bigcrypt(password,this_salt),this_crypted) == 0);
#endif

#ifdef NO_CRYPT
  DEBUG(1,("Warning - no crypt available\n"));
  return(False);
#else
  return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
#endif
}
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
				int argc, const char **argv)
{
	unsigned int ctrl, lctrl;
	int retval, i;
	int remember = -1;

	/* <DO NOT free() THESE> */
	const char *user;
	char *pass_old, *pass_new;
	/* </DO NOT free() THESE> */

	D(("called."));

#ifdef USE_LCKPWDF
	/* our current locking system requires that we lock the
	   entire password database.  This avoids both livelock
	   and deadlock. */
	/* These values for the number of attempts and the sleep time
	   are, of course, completely arbitrary.
	   My reading of the PAM docs is that, once pam_chauthtok() has been
	   called with PAM_UPDATE_AUTHTOK, we are obliged to take any
	   reasonable steps to make sure the token is updated; so retrying
	   for 1/10 sec. isn't overdoing it.
	   The other possibility is to call lckpwdf() on the first
	   pam_chauthtok() pass, and hold the lock until released in the
	   second pass--but is this guaranteed to work? -SRL */
	i=0;
	while((retval = lckpwdf()) != 0 && i < 100) {
		usleep(1000);
	}
	if(retval != 0) {
		return PAM_AUTHTOK_LOCK_BUSY;
	}
#endif
	ctrl = _set_ctrl(pamh, flags, &remember, argc, argv);

	/*
	 * First get the name of a user
	 */
	retval = pam_get_user(pamh, &user, "Username: "******"bad username [%s]", user);
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return PAM_USER_UNKNOWN;
		}
		if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
			_log_err(LOG_DEBUG, pamh, "username [%s] obtained",
			         user);
	} else {
		if (on(UNIX_DEBUG, ctrl))
			_log_err(LOG_DEBUG, pamh,
			         "password - could not identify user");
#ifdef USE_LCKPWDF
		ulckpwdf();
#endif
		return retval;
	}

	D(("Got username of %s", user));

	/*
	 * This is not an AUTH module!
	 */
	if (on(UNIX__NONULL, ctrl))
		set(UNIX__NULLOK, ctrl);

	if (on(UNIX__PRELIM, ctrl)) {
		/*
		 * obtain and verify the current password (OLDAUTHTOK) for
		 * the user.
		 */
		char *Announce;

		D(("prelim check"));

		if (_unix_blankpasswd(ctrl, user)) {
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return PAM_SUCCESS;
		} else if (off(UNIX__IAMROOT, ctrl)) {

			/* instruct user what is happening */
#define greeting "Changing password for "
			Announce = (char *) malloc(sizeof(greeting) + strlen(user));
			if (Announce == NULL) {
				_log_err(LOG_CRIT, pamh,
				         "password - out of memory");
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return PAM_BUF_ERR;
			}
			(void) strcpy(Announce, greeting);
			(void) strcpy(Announce + sizeof(greeting) - 1, user);
#undef greeting

			lctrl = ctrl;
			set(UNIX__OLD_PASSWD, lctrl);
			retval = _unix_read_password(pamh, lctrl
						     ,Announce
					     ,"(current) UNIX password: "******"password - (old) token not obtained");
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return retval;
			}
			/* verify that this is the password for this user */

			retval = _unix_verify_password(pamh, user, pass_old, ctrl);
		} else {
			D(("process run by root so do nothing this time around"));
			pass_old = NULL;
			retval = PAM_SUCCESS;	/* root doesn't have too */
		}

		if (retval != PAM_SUCCESS) {
			D(("Authentication failed"));
			pass_old = NULL;
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
		pass_old = NULL;
		if (retval != PAM_SUCCESS) {
			_log_err(LOG_CRIT, pamh,
			         "failed to set PAM_OLDAUTHTOK");
		}
		retval = _unix_verify_shadow(user, ctrl);
		if (retval == PAM_AUTHTOK_ERR) {
			if (off(UNIX__IAMROOT, ctrl))
				_make_remark(pamh, ctrl, PAM_ERROR_MSG,
					    "You must wait longer to change your password");
			else
				retval = PAM_SUCCESS;
		}
	} else if (on(UNIX__UPDATE, ctrl)) {
		/*
		 * tpass is used below to store the _pam_md() return; it
		 * should be _pam_delete()'d.
		 */

		char *tpass = NULL;
		int retry = 0;

		/*
		 * obtain the proposed password
		 */

		D(("do update"));

		/*
		 * get the old token back. NULL was ok only if root [at this
		 * point we assume that this has already been enforced on a
		 * previous call to this function].
		 */

		if (off(UNIX_NOT_SET_PASS, ctrl)) {
			retval = pam_get_item(pamh, PAM_OLDAUTHTOK
					      ,(const void **) &pass_old);
		} else {
			retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK
					      ,(const void **) &pass_old);
			if (retval == PAM_NO_MODULE_DATA) {
				retval = PAM_SUCCESS;
				pass_old = NULL;
			}
		}
		D(("pass_old [%s]", pass_old));

		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh, "user not authenticated");
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		retval = _unix_verify_shadow(user, ctrl);
		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh, "user not authenticated 2");
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		D(("get new password now"));

		lctrl = ctrl;

		if (on(UNIX_USE_AUTHTOK, lctrl)) {
			set(UNIX_USE_FIRST_PASS, lctrl);
		}
		retry = 0;
		retval = PAM_AUTHTOK_ERR;
		while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) {
			/*
			 * use_authtok is to force the use of a previously entered
			 * password -- needed for pluggable password strength checking
			 */

			retval = _unix_read_password(pamh, lctrl
						     ,NULL
					     ,"Enter new UNIX password: "******"Retype new UNIX password: "******"password - new password not obtained");
				}
				pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return retval;
			}
			D(("returned to _unix_chauthtok"));

			/*
			 * At this point we know who the user is and what they
			 * propose as their new password. Verify that the new
			 * password is acceptable.
			 */

			if (pass_new[0] == '\0') {	/* "\0" password = NULL */
				pass_new = NULL;
			}
			retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
		}

		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh,
			         "new password not acceptable");
			_pam_overwrite(pass_new);
			_pam_overwrite(pass_old);
			pass_new = pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		/*
		 * By reaching here we have approved the passwords and must now
		 * rebuild the password database file.
		 */

		/*
		 * First we encrypt the new password.
		 */

		if (on(UNIX_MD5_PASS, ctrl)) {
			tpass = crypt_md5_wrapper(pass_new);
		} else {
			/*
			 * Salt manipulation is stolen from Rick Faith's passwd
			 * program.  Sorry Rick :) -- alex
			 */

			time_t tm;
			char salt[3];

			time(&tm);
			salt[0] = bin_to_ascii(tm & 0x3f);
			salt[1] = bin_to_ascii((tm >> 6) & 0x3f);
			salt[2] = '\0';

			if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) {
				/* 
				 * to avoid using the _extensions_ of the bigcrypt()
				 * function we truncate the newly entered password
				 */
				char *temp = malloc(9);
				char *e;

				if (temp == NULL) {
					_log_err(LOG_CRIT, pamh,
					         "out of memory for password");
					_pam_overwrite(pass_new);
					_pam_overwrite(pass_old);
					pass_new = pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
					ulckpwdf();
#endif
					return PAM_BUF_ERR;
				}
				/* copy first 8 bytes of password */
				strncpy(temp, pass_new, 8);
				temp[8] = '\0';

				/* no longer need cleartext */
				e = bigcrypt(temp, salt);
				tpass = x_strdup(e);

				_pam_overwrite(e);
				_pam_delete(temp);	/* tidy up */
			} else {
				char *e;

				/* no longer need cleartext */
				e = bigcrypt(pass_new, salt);
				tpass = x_strdup(e);

				_pam_overwrite(e);
			}
		}

		D(("password processed"));

		/* update the password database(s) -- race conditions..? */

		retval = _do_setpass(pamh, user, pass_old, tpass, ctrl,
		                     remember);
		_pam_overwrite(pass_new);
		_pam_overwrite(pass_old);
		_pam_delete(tpass);
		pass_old = pass_new = NULL;
	} else {		/* something has broken with the module */
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;
}
Exemple #10
0
PAMH_ARG_DECL(char * create_password_hash,
	const char *password, unsigned int ctrl, int rounds)
{
	const char *algoid;
	char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */
	char *sp;

	if (on(UNIX_MD5_PASS, ctrl)) {
		/* algoid = "$1" */
		return crypt_md5_wrapper(password);
	} else if (on(UNIX_BLOWFISH_PASS, ctrl)) {
		algoid = "$2a$";
	} else if (on(UNIX_SHA256_PASS, ctrl)) {
		algoid = "$5$";
	} else if (on(UNIX_SHA512_PASS, ctrl)) {
		algoid = "$6$";
	} else { /* must be crypt/bigcrypt */
		char tmppass[9];
		char *crypted;

		crypt_make_salt(salt, 2);
		if (off(UNIX_BIGCRYPT, ctrl) && strlen(password) > 8) {
			strncpy(tmppass, password, sizeof(tmppass)-1);
			tmppass[sizeof(tmppass)-1] = '\0';
			password = tmppass;
		}
		crypted = bigcrypt(password, salt);
		memset(tmppass, '\0', sizeof(tmppass));
		password = NULL;
		return crypted;
	}

#ifdef HAVE_CRYPT_GENSALT_R
	if (on(UNIX_BLOWFISH_PASS, ctrl)) {
		char entropy[17];
		crypt_make_salt(entropy, sizeof(entropy) - 1);
		sp = crypt_gensalt_r (algoid, rounds,
				      entropy, sizeof(entropy),
				      salt, sizeof(salt));
	} else {
#endif
		sp = stpcpy(salt, algoid);
		if (on(UNIX_ALGO_ROUNDS, ctrl)) {
			sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds);
		}
		crypt_make_salt(sp, 8);
		/* For now be conservative so the resulting hashes
		 * are not too long. 8 bytes of salt prevents dictionary
		 * attacks well enough. */
#ifdef HAVE_CRYPT_GENSALT_R
	}
#endif
	sp = crypt(password, salt);
	if (strncmp(algoid, sp, strlen(algoid)) != 0) {
		/* libxcrypt/libc doesn't know the algorithm, use MD5 */
		pam_syslog(pamh, LOG_ERR,
			   "Algo %s not supported by the crypto backend, "
			   "falling back to MD5\n",
			   on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" :
			   on(UNIX_SHA256_PASS, ctrl) ? "sha256" :
			   on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid);
		memset(sp, '\0', strlen(sp));
		return crypt_md5_wrapper(password);
	}

	return x_strdup(sp);
}
Exemple #11
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;
}
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;
}
/* 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;
}
Exemple #14
0
/****************************************************************************
core of password checking routine
****************************************************************************/
static NTSTATUS password_check(const char *password)
{
#ifdef WITH_PAM
	return smb_pam_passcheck(this_user, password);
#else

	BOOL ret;

#ifdef WITH_AFS
	if (afs_auth(this_user, password))
		return NT_STATUS_OK;
#endif /* WITH_AFS */

#ifdef WITH_DFS
	if (dfs_auth(this_user, password))
		return NT_STATUS_OK;
#endif /* WITH_DFS */

#ifdef OSF1_ENH_SEC
	
	ret = (strcmp(osf1_bigcrypt(password, this_salt),
		      this_crypted) == 0);
	if (!ret) {
		DEBUG(2,
		      ("OSF1_ENH_SEC failed. Trying normal crypt.\n"));
		ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
	}
	if (ret) {
		return NT_STATUS_OK;
	} else {
		return NT_STATUS_WRONG_PASSWORD;
	}
	
#endif /* OSF1_ENH_SEC */
	
#ifdef ULTRIX_AUTH
	ret = (strcmp((char *)crypt16(password, this_salt), this_crypted) == 0);
	if (ret) {
		return NT_STATUS_OK;
        } else {
		return NT_STATUS_WRONG_PASSWORD;
	}
	
#endif /* ULTRIX_AUTH */
	
#ifdef LINUX_BIGCRYPT
	ret = (linux_bigcrypt(password, this_salt, this_crypted));
        if (ret) {
		return NT_STATUS_OK;
	} else {
		return NT_STATUS_WRONG_PASSWORD;
	}
#endif /* LINUX_BIGCRYPT */
	
#if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS)
	
	/*
	 * Some systems have bigcrypt in the C library but might not
	 * actually use it for the password hashes (HPUX 10.20) is
	 * a noteable example. So we try bigcrypt first, followed
	 * by crypt.
	 */

	if (strcmp(bigcrypt(password, this_salt), this_crypted) == 0)
		return NT_STATUS_OK;
	else
		ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
	if (ret) {
		return NT_STATUS_OK;
	} else {
		return NT_STATUS_WRONG_PASSWORD;
	}
#else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
	
#ifdef HAVE_BIGCRYPT
	ret = (strcmp(bigcrypt(password, this_salt), this_crypted) == 0);
        if (ret) {
		return NT_STATUS_OK;
	} else {
		return NT_STATUS_WRONG_PASSWORD;
	}
#endif /* HAVE_BIGCRYPT */
	
#ifndef HAVE_CRYPT
	DEBUG(1, ("Warning - no crypt available\n"));
	return NT_STATUS_LOGON_FAILURE;
#else /* HAVE_CRYPT */
	ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0);
        if (ret) {
		return NT_STATUS_OK;
	} else {
		return NT_STATUS_WRONG_PASSWORD;
	}
#endif /* HAVE_CRYPT */
#endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */
#endif /* WITH_PAM */
}
Exemple #15
0
/* Returns TRUE if login is allowed with the given local password. */

#ifdef HAVE_SIA
Boolean ssh_user_validate_local_password(SshUser uc,
                                         const char *password,
                                         const char *remote_host)
#else /* HAVE_SIA */
Boolean ssh_user_validate_local_password(SshUser uc,
                                         const char *password)
#endif /* HAVE_SIA */
{
  char *encrypted_password;
  const char *correct_passwd = uc->correct_encrypted_passwd;

#ifdef HAVE_ULTRIX_SHADOW_PASSWORDS
  {
    struct svcinfo *svp;
    struct passwd *pw;

    pw = getpwnam(uc->name);
    if (!pw)
      return FALSE;

    svp = getsvc();
    if (svp == NULL)
      {
        error("getsvc() failed in ultrix code in auth_passwd");
        return FALSE;
      }
    if ((svp->svcauth.seclevel == SEC_UPGRADE &&
         strcmp(pw->pw_passwd, "*") == 0) ||
        svp->svcauth.seclevel == SEC_ENHANCED)
      return authenticate_user(pw, password, "/dev/ttypXX") >= 0;
  }
#endif /* HAVE_ULTRIX_SHADOW_PASSWORDS */

#ifdef HAVE_SIA
  {
    int argc;
    char **argv;

    /* Passing a collection routine to my_sia_validate_user() here would
       be useless and could be harmful.

       It would be useless because at this point, stdin/stdout/stderr
       are all redirected to /dev/null.

       It would be harmful if the collection routine tried to print
       anything to stdout, say, a warning that the password is incorrect.
       At this point, nothing has been printed to stdout yet and it's
       redirected to /dev/null.  Printing to stdout now would initialize
       it as fully buffered (not line buffered) since /dev/null isn't a
       tty.  That would cause problems later on in the child, which gets
       a copy of the stdout structure.  When the child printed /etc/motd
       and the mail notice, the user wouldn't see them because they'd
       be stuck in the stdout buffer. */

    get_sia_args(&argc, &argv);
    if (my_sia_validate_user(NULL, argc, argv,
                             (char *)remote_host, uc->name,
                             NULL, 0, NULL, (char *)password) == SIASUCCESS)
      return TRUE;
    else
      return FALSE;
  }
#endif /* HAVE_SIA */

  /* Encrypt the candidate password using the proper salt. */
#if defined(HAVE_SCO_ETC_SHADOW) || defined(HAVE_HPUX_TCB_AUTH)
  encrypted_password = bigcrypt(password, 
                                (correct_passwd[0] && correct_passwd[1]) ?
                                correct_passwd : "xx");
#else /* defined(HAVE_SCO_ETC_SHADOW) || defined(HAVE_HPUX_TCB_AUTH) */
  encrypted_password = crypt(password, 
                             (correct_passwd[0] && correct_passwd[1]) ?
                             correct_passwd : "xx");
#endif /* HAVE_SCO_ETC_SHADOW */

  /* Authentication is accepted if the encrypted passwords are identical. */
  return strcmp(encrypted_password, correct_passwd) == 0;
  
}