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; }
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; }