123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- #include "libbb.h"
- static int string_checker_helper(const char *p1, const char *p2) __attribute__ ((__pure__));
- static int string_checker_helper(const char *p1, const char *p2)
- {
-
- if (strcasestr(p2, p1) != NULL
-
- || strcasestr(p1, p2) != NULL
-
-
- ) {
- return 1;
- }
- return 0;
- }
- static int string_checker(const char *p1, const char *p2)
- {
- int size, i;
-
- int ret = string_checker_helper(p1, p2);
-
- char *p = xstrdup(p1);
-
- i = size = strlen(p1);
- while (--i >= 0) {
- *p++ = p1[i];
- }
- p -= size;
-
- ret |= string_checker_helper(p, p2);
-
- nuke_str(p);
- free(p);
- return ret;
- }
- #define CATEGORIES 4
- #define LOWERCASE 1
- #define UPPERCASE 2
- #define NUMBERS 4
- #define SPECIAL 8
- #define LAST_CAT 8
- static const char *obscure_msg(const char *old_p, const char *new_p, const struct passwd *pw)
- {
- unsigned length;
- unsigned size;
- unsigned mixed;
- unsigned c;
- unsigned i;
- const char *p;
- char *hostname;
-
- if (!new_p || (length = strlen(new_p)) < CONFIG_PASSWORD_MINLEN)
- return "too short";
-
- if (string_checker(new_p, pw->pw_name)) {
- return "similar to username";
- }
- #ifndef __BIONIC__
-
- if (pw->pw_gecos[0] && string_checker(new_p, pw->pw_gecos)) {
- return "similar to gecos";
- }
- #endif
-
- hostname = safe_gethostname();
- i = string_checker(new_p, hostname);
- free(hostname);
- if (i)
- return "similar to hostname";
-
- mixed = 0;
- for (i = 0; i < length; i++) {
- if (islower(new_p[i])) {
- mixed |= LOWERCASE;
- } else if (isupper(new_p[i])) {
- mixed |= UPPERCASE;
- } else if (isdigit(new_p[i])) {
- mixed |= NUMBERS;
- } else {
- mixed |= SPECIAL;
- }
-
- c = 0;
- p = new_p;
- while (1) {
- p = strchr(p, new_p[i]);
- if (p == NULL) {
- break;
- }
- c++;
- p++;
- if (!*p) {
- break;
- }
- }
-
- if (c*2 >= length) {
- return "too many similar characters";
- }
- }
- size = CONFIG_PASSWORD_MINLEN + 2*CATEGORIES;
- for (i = 1; i <= LAST_CAT; i <<= 1)
- if (mixed & i)
- size -= 2;
- if (length < size)
- return "too weak";
- if (old_p && old_p[0]) {
-
- if (string_checker(new_p, old_p)) {
- return "similar to old password";
- }
- }
- return NULL;
- }
- int FAST_FUNC obscure(const char *old, const char *newval, const struct passwd *pw)
- {
- const char *msg;
- msg = obscure_msg(old, newval, pw);
- if (msg) {
- printf("Bad password: %s\n", msg);
- return 1;
- }
- return 0;
- }
- #if ENABLE_UNIT_TEST
- static const struct passwd pw = {
- .pw_name = (char *)"johndoe",
- .pw_gecos = (char *)"John Doe",
- };
- BBUNIT_DEFINE_TEST(obscure_weak_pass)
- {
-
- BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "", &pw));
-
- BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "23577315", &pw));
-
- BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "johndoe123%", &pw));
-
- BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "eoD nhoJ^44@", &pw));
-
- BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "d4#21?'S", &pw));
-
- BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "qwerty123", &pw));
-
- BBUNIT_ASSERT_NOTNULL(obscure_msg("Ad4#21?'S|", "^33Daaaaaa1", &pw));
- BBUNIT_ENDTEST;
- }
- BBUNIT_DEFINE_TEST(obscure_strong_pass)
- {
- BBUNIT_ASSERT_NULL(obscure_msg("Rt4##2&:'|", "}(^#rrSX3S*22", &pw));
- BBUNIT_ENDTEST;
- }
- #endif
|