示例#1
0
/*
 * This wordlist check is now the least important given the checks above
 * and the support for passphrases (which are based on dictionary words,
 * and checked by other means).  It is still useful to trap simple short
 * passwords (if short passwords are allowed) that are word-based, but
 * passed the other checks due to uncommon capitalization, digits, and
 * special characters.  We (mis)use the same set of words that are used
 * to generate random passwords.  This list is much smaller than those
 * used for password crackers, and it doesn't contain common passwords
 * that aren't short English words.  Perhaps support for large wordlists
 * should still be added, even though this is now of little importance.
 */
static const char *is_word_based(const passwdqc_params_qc_t *params,
    const char *needle, const char *original, int is_reversed)
{
	char word[7];
	char *unified;
	unsigned int i;
	int length;
	int mode;

	if (!params->match_length)	/* disabled */
		return NULL;

	mode = is_reversed | 2;
	for (i = 0; i < sizeof(seq) / sizeof(seq[0]); i++) {
		unified = unify(NULL, seq[i]);
		if (!unified)
			return REASON_ERROR;
		if (is_based(params, unified, needle, original, mode)) {
			free(unified);
			return REASON_SEQ;
		}
		free(unified);
	}

	mode = is_reversed | 1;
	word[6] = '\0';
	for (i = 0; i < 0x1000; i++) {
		if (params->lang == 0) {
			memcpy(word, _passwdqc_wordset_4k[i], 6);
		} else {
			memcpy(word, _passwdqc_wordset_4k_es[i], 6);
		}
		length = strlen(word);
		if (length < params->match_length)
			continue;
		if (params->lang == 0 && i < 0xfff &&
		    !memcmp(word, _passwdqc_wordset_4k[i + 1], length))
			continue;
		if (params->lang == 1 && i < 0xfff &&
		    !memcmp(word, _passwdqc_wordset_4k_es[i + 1], length))
			continue;
		unify(word, word);
		if (is_based(params, word, needle, original, mode))
			return REASON_WORD;
	}

	mode = is_reversed | 2;
	if (params->match_length <= 4)
	for (i = 1900; i <= 2039; i++) {
		sprintf(word, "%u", i);
		if (is_based(params, word, needle, original, mode))
			return REASON_SEQ;
	}

	return NULL;
}
示例#2
0
/*
 * This wordlist check is now the least important given the checks above
 * and the support for passphrases (which are based on dictionary words,
 * and checked by other means). It is still useful to trap simple short
 * passwords (if short passwords are allowed) that are word-based, but
 * passed the other checks due to uncommon capitalization, digits, and
 * special characters. We (mis)use the same set of words that are used
 * to generate random passwords. This list is much smaller than those
 * used for password crackers, and it doesn't contain common passwords
 * that aren't short English words. Perhaps support for large wordlists
 * should still be added, even though this is now of little importance.
 */
static int is_word_based(passwdqc_params_t *params,
    const char *needle, const char *original)
{
	char word[7];
	char *unified;
	int i;

	word[6] = '\0';
	for (i = 0; i < 0x1000; i++) {
		memcpy(word, _passwdqc_wordset_4k[i], 6);
		if ((int)strlen(word) < params->match_length) continue;
		unified = unify(word);
		if (is_based(params, unified, needle, original)) {
			clean(unified);
			return 1;
		}
		clean(unified);
	}

	return 0;
}
示例#3
0
const char *_passwdqc_check(passwdqc_params_t *params,
    const char *newpass, const char *oldpass, struct passwd *pw)
{
	char truncated[9], *reversed;
	char *u_newpass, *u_reversed;
	char *u_oldpass;
	char *u_name, *u_gecos;
	const char *reason;
	int length;

	reversed = NULL;
	u_newpass = u_reversed = NULL;
	u_oldpass = NULL;
	u_name = u_gecos = NULL;

	reason = NULL;

	if (oldpass && !strcmp(oldpass, newpass))
		reason = REASON_SAME;

	length = strlen(newpass);

	if (!reason && length < params->min[4])
		reason = REASON_SHORT;

	if (!reason && length > params->max) {
		if (params->max == 8) {
			truncated[0] = '\0';
			strncat(truncated, newpass, 8);
			newpass = truncated;
			if (oldpass && !strncmp(oldpass, newpass, 8))
				reason = REASON_SAME;
		} else
			reason = REASON_LONG;
	}

	if (!reason && is_simple(params, newpass)) {
		if (length < params->min[1] && params->min[1] <= params->max)
			reason = REASON_SIMPLESHORT;
		else
			reason = REASON_SIMPLE;
	}

	if (!reason) {
		if ((reversed = reverse(newpass))) {
			u_newpass = unify(newpass);
			u_reversed = unify(reversed);
			if (oldpass)
				u_oldpass = unify(oldpass);
			if (pw) {
				u_name = unify(pw->pw_name);
				u_gecos = unify(pw->pw_gecos);
			}
		}
		if (!reversed ||
		    !u_newpass || !u_reversed ||
		    (oldpass && !u_oldpass) ||
		    (pw && (!u_name || !u_gecos)))
			reason = REASON_ERROR;
	}

	if (!reason && oldpass && params->similar_deny &&
	    (is_based(params, u_oldpass, u_newpass, newpass) ||
	    is_based(params, u_oldpass, u_reversed, reversed)))
		reason = REASON_SIMILAR;

	if (!reason && pw &&
	    (is_based(params, u_name, u_newpass, newpass) ||
	    is_based(params, u_name, u_reversed, reversed) ||
	    is_based(params, u_gecos, u_newpass, newpass) ||
	    is_based(params, u_gecos, u_reversed, reversed)))
		reason = REASON_PERSONAL;

	if (!reason && (int)strlen(newpass) < params->min[2] &&
	    (is_word_based(params, u_newpass, newpass) ||
	    is_word_based(params, u_reversed, reversed)))
		reason = REASON_WORD;

	memset(truncated, 0, sizeof(truncated));
	clean(reversed);
	clean(u_newpass); clean(u_reversed);
	clean(u_oldpass);
	clean(u_name); clean(u_gecos);

	return reason;
}
示例#4
0
const char *passwdqc_check(const passwdqc_params_qc_t *params,
    const char *newpass, const char *oldpass, const struct passwd *pw)
{
	char truncated[9];
	char *u_newpass, *u_reversed;
	char *u_oldpass;
	char *u_name, *u_gecos, *u_dir;
	const char *reason;
	int length;

	u_newpass = u_reversed = NULL;
	u_oldpass = NULL;
	u_name = u_gecos = u_dir = NULL;

	reason = REASON_ERROR;

	if (oldpass && !strcmp(oldpass, newpass)) {
		reason = REASON_SAME;
		goto out;
	}

	length = strlen(newpass);

	if (length < params->min[4]) {
		reason = REASON_SHORT;
		goto out;
	}

	if (length > params->max) {
		if (params->max == 8) {
			truncated[0] = '\0';
			strncat(truncated, newpass, 8);
			newpass = truncated;
			if (oldpass && !strncmp(oldpass, newpass, 8)) {
				reason = REASON_SAME;
				goto out;
			}
		} else {
			reason = REASON_LONG;
			goto out;
		}
	}

	if (is_simple(params, newpass, 0)) {
		reason = REASON_SIMPLE;
		if (length < params->min[1] && params->min[1] <= params->max)
			reason = REASON_SIMPLESHORT;
		goto out;
	}

	if (!(u_newpass = unify(NULL, newpass)))
		goto out; /* REASON_ERROR */
	if (!(u_reversed = reverse(u_newpass)))
		goto out;
	if (oldpass && !(u_oldpass = unify(NULL, oldpass)))
		goto out;
	if (pw) {
		if (!(u_name = unify(NULL, pw->pw_name)) ||
		    !(u_gecos = unify(NULL, pw->pw_gecos)) ||
		    !(u_dir = unify(NULL, pw->pw_dir)))
			goto out;
	}

	if (oldpass && params->similar_deny &&
	    (is_based(params, u_oldpass, u_newpass, newpass, 0) ||
	     is_based(params, u_oldpass, u_reversed, newpass, 0x100))) {
		reason = REASON_SIMILAR;
		goto out;
	}

	if (pw &&
	    (is_based(params, u_name, u_newpass, newpass, 0) ||
	     is_based(params, u_name, u_reversed, newpass, 0x100) ||
	     is_based(params, u_gecos, u_newpass, newpass, 0) ||
	     is_based(params, u_gecos, u_reversed, newpass, 0x100) ||
	     is_based(params, u_dir, u_newpass, newpass, 0) ||
	     is_based(params, u_dir, u_reversed, newpass, 0x100))) {
		reason = REASON_PERSONAL;
		goto out;
	}

	reason = is_word_based(params, u_newpass, newpass, 0);
	if (!reason)
		reason = is_word_based(params, u_reversed, newpass, 0x100);

out:
	memset(truncated, 0, sizeof(truncated));
	clean(u_newpass);
	clean(u_reversed);
	clean(u_oldpass);
	clean(u_name);
	clean(u_gecos);
	clean(u_dir);

	return reason;
}