libbb: shrink obscure()

function                                             old     new   delta
string_checker_helper                                 59      45     -14
string_checker                                       116      98     -18
obscure                                              367     204    -163
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-195)           Total: -195 bytes

Signed-off-by: Bob Dunlop <bob.dunlop@xyzzy.org.uk>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Bob Dunlop 2010-08-17 16:01:16 +02:00 committed by Denys Vlasenko
parent cda815996b
commit d71c770f05

View File

@ -45,53 +45,59 @@ static int string_checker_helper(const char *p1, const char *p2) __attribute__ (
static int string_checker_helper(const char *p1, const char *p2) static int string_checker_helper(const char *p1, const char *p2)
{ {
/* as-is or capitalized */
if (strcasecmp(p1, p2) == 0
/* as sub-string */ /* as sub-string */
|| strcasestr(p2, p1) != NULL if (strcasestr(p2, p1) != NULL
/* invert in case haystack is shorter than needle */ /* invert in case haystack is shorter than needle */
|| strcasestr(p1, p2) != NULL) || strcasestr(p1, p2) != NULL
/* as-is or capitalized */
/* || strcasecmp(p1, p2) == 0 - 1st strcasestr should catch this too */
) {
return 1; return 1;
}
return 0; return 0;
} }
static int string_checker(const char *p1, const char *p2) static int string_checker(const char *p1, const char *p2)
{ {
int size; int size, i;
/* check string */ /* check string */
int ret = string_checker_helper(p1, p2); int ret = string_checker_helper(p1, p2);
/* Make our own copy */ /* make our own copy */
char *p = xstrdup(p1); char *p = xstrdup(p1);
/* reverse string */
size = strlen(p);
while (size--) { /* reverse string */
*p = p1[size]; i = size = strlen(p1);
p++; while (--i >= 0) {
*p++ = p1[i];
} }
/* restore pointer */ p -= size; /* restore pointer */
p -= strlen(p1);
/* check reversed string */ /* check reversed string */
ret |= string_checker_helper(p, p2); ret |= string_checker_helper(p, p2);
/* clean up */ /* clean up */
memset(p, 0, strlen(p1)); memset(p, 0, size);
free(p); free(p);
return ret; return ret;
} }
#define CATEGORIES 4
#define LOWERCASE 1 #define LOWERCASE 1
#define UPPERCASE 2 #define UPPERCASE 2
#define NUMBERS 4 #define NUMBERS 4
#define SPECIAL 8 #define SPECIAL 8
#define LAST_CAT 8
static const char *obscure_msg(const char *old_p, const char *new_p, const struct passwd *pw) static const char *obscure_msg(const char *old_p, const char *new_p, const struct passwd *pw)
{ {
int i; unsigned length;
int c; unsigned size;
int length; unsigned mixed;
int mixed = 0; unsigned c;
/* Add 2 for each type of characters to the minlen of password */ unsigned i;
int size = CONFIG_PASSWORD_MINLEN + 8;
const char *p; const char *p;
char *hostname; char *hostname;
@ -104,7 +110,7 @@ static const char *obscure_msg(const char *old_p, const char *new_p, const struc
return "similar to username"; return "similar to username";
} }
/* no gecos as-is, as sub-string, reversed, capitalized, doubled */ /* no gecos as-is, as sub-string, reversed, capitalized, doubled */
if (*pw->pw_gecos && string_checker(new_p, pw->pw_gecos)) { if (pw->pw_gecos[0] && string_checker(new_p, pw->pw_gecos)) {
return "similar to gecos"; return "similar to gecos";
} }
/* hostname as-is, as sub-string, reversed, capitalized, doubled */ /* hostname as-is, as sub-string, reversed, capitalized, doubled */
@ -115,6 +121,7 @@ static const char *obscure_msg(const char *old_p, const char *new_p, const struc
return "similar to hostname"; return "similar to hostname";
/* Should / Must contain a mix of: */ /* Should / Must contain a mix of: */
mixed = 0;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
if (islower(new_p[i])) { /* a-z */ if (islower(new_p[i])) { /* a-z */
mixed |= LOWERCASE; mixed |= LOWERCASE;
@ -125,7 +132,7 @@ static const char *obscure_msg(const char *old_p, const char *new_p, const struc
} else { /* special characters */ } else { /* special characters */
mixed |= SPECIAL; mixed |= SPECIAL;
} }
/* More than 50% similar characters ? */ /* Count i'th char */
c = 0; c = 0;
p = new_p; p = new_p;
while (1) { while (1) {
@ -134,26 +141,31 @@ static const char *obscure_msg(const char *old_p, const char *new_p, const struc
break; break;
} }
c++; c++;
if (!++p) { p++;
break; /* move past the matched char if possible */ if (!*p) {
break;
} }
} }
/* More than 50% similar characters ? */
if (c >= (length / 2)) { if (c*2 >= length) {
return "too many similar characters"; return "too many similar characters";
} }
} }
for (i=0; i<4; i++)
if (mixed & (1<<i)) size -= 2; size = CONFIG_PASSWORD_MINLEN + 2*CATEGORIES;
for (i = 0; i <= LAST_CAT; i <<= 1)
if (mixed & i)
size -= 2;
if (length < size) if (length < size)
return "too weak"; return "too weak";
if (old_p && old_p[0] != '\0') { if (old_p && old_p[0]) {
/* check vs. old password */ /* check vs. old password */
if (string_checker(new_p, old_p)) { if (string_checker(new_p, old_p)) {
return "similar to old password"; return "similar to old password";
} }
} }
return NULL; return NULL;
} }