- /*
- * Remaining checks are optional.
- */
- /* Not for us -- Sean
- *if (!getdef_bool("OBSCURE_CHECKS_ENAB"))
- * return NULL;
- */
- msg = password_check(old, newval, pwdp);
- if (msg)
- return msg;
-
- /* The traditional crypt() truncates passwords to 8 chars. It is
- possible to circumvent the above checks by choosing an easy
- 8-char password and adding some random characters to it...
- Example: "password$%^&*123". So check it again, this time
- truncated to the maximum length. Idea from npasswd. --marekm */
-
- maxlen = 8;
- if (oldlen <= maxlen && newlen <= maxlen)
- return NULL;
-
- new1 = (char *) xstrdup(newval);
- old1 = (char *) xstrdup(old);
- if (newlen > maxlen)
- new1[maxlen] = '\0';
- if (oldlen > maxlen)
- old1[maxlen] = '\0';
-
- msg = password_check(old1, new1, pwdp);
-
- bzero(new1, newlen);
- bzero(old1, oldlen);
- free(new1);
- free(old1);
-
- return msg;
+ /* no username as-is, as sub-string, reversed, capitalized, doubled */
+ if (string_checker(new_p, pw->pw_name)) {
+ return "similar to username";
+ }
+ /* no gecos as-is, as sub-string, reversed, capitalized, doubled */
+ if (*pw->pw_gecos && string_checker(new_p, pw->pw_gecos)) {
+ return "similar to gecos";
+ }
+ /* hostname as-is, as sub-string, reversed, capitalized, doubled */
+ hostname = safe_gethostname();
+ i = string_checker(new_p, hostname);
+ free(hostname);
+ if (i)
+ return "similar to hostname";
+
+ /* Should / Must contain a mix of: */
+ for (i = 0; i < length; i++) {
+ if (islower(new_p[i])) { /* a-z */
+ mixed |= LOWERCASE;
+ } else if (isupper(new_p[i])) { /* A-Z */
+ mixed |= UPPERCASE;
+ } else if (isdigit(new_p[i])) { /* 0-9 */
+ mixed |= NUMBERS;
+ } else { /* special characters */
+ mixed |= SPECIAL;
+ }
+ /* More than 50% similar characters ? */
+ c = 0;
+ p = new_p;
+ while (1) {
+ p = strchr(p, new_p[i]);
+ if (p == NULL) {
+ break;
+ }
+ c++;
+ if (!++p) {
+ break; /* move past the matched char if possible */
+ }
+ }
+
+ if (c >= (length / 2)) {
+ return "too many similar characters";
+ }
+ }
+ for (i=0; i<4; i++)
+ if (mixed & (1<<i)) size -= 2;
+ if (length < size)
+ return "too weak";
+
+ if (old_p && old_p[0] != '\0') {
+ /* check vs. old password */
+ if (string_checker(new_p, old_p)) {
+ return "similar to old password";
+ }
+ }
+ return NULL;