New GPL'ed obscure.c replacement
Bernhard Fischer
rep.nop at aon.at
Wed Jan 18 15:12:09 UTC 2006
On Wed, Jan 18, 2006 at 02:46:06PM +0100, Tito wrote:
>Hi to all,
>this is a proposal to substitute obscure.c with a new GPL'ed version.
>This is just a proof of concept for auditing and review by the list members.
>This version is more restrictive than the previous ( maybe to much?)
What about a
config CONFIG_PASSWD_STRENGTH
bool " minimal strength for new password"
depends on CONFIG_PASSWORD
default 2
range 0 4
help
0 .. don't check strength of password
1 .. at least one different kind of character class
2 .. at least two different kinds of character classes
3 .. at least three different kinds of character classes
4 .. at least four different kinds of character classes
A character class is one of
- capital letter
- lowercase letter
- number
- other (none of the above)
That way it could be small if no checking was requested.
Just an idea
>and doesn't allow passwords that do not contain all four types
>of characters: upper, lower, digits and special chars.
>Size is:
>
>root at localhost:/dev/pts/2:/root/Desktop/busybox/libbb# size obscure.o.orig
> text data bss dec hex filename
> 757 0 0 757 2f5 obscure.o.orig
> text data bss dec hex filename
> 667 0 0 667 29b obscure.o
>
>Comments, critics and improvements are as always welcome.
>
>BTW: as this function is used only by passwd.c I think this file
> should be moved from libbb/ to loginutils/ dir.
Moving it to loginutils would be fine with me.
>
>Thanks in advance for your time and help.
>Ciao,
>Tito
>
>/* vi: set sw=4 ts=4: */
>/*
> * Mini weak password checker implementation for busybox
> *
> * Copyright (C) 2006 Tito Ragusa <farmatito at tiscali.it>
> *
> * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
> */
>
>/* A good password:
> 1) should contain at least six characters (man passwd) so empty passwords are not permitted
> 2) should contain a mix of four different types of characters
> upper case letters,
> lower case letters,
> numbers,
> special characters such as !@#$%^&*,;"
> so this password types are not permitted:
> a) pure numbers: birthdates,
> social security number,
> license plate,
> phone numbers;
> b) words and all letters only passwords (uppercase, lowercase or mixed)
> as palindromes, consecutive or repetitive letters
> or adjacent letters on your keyboard;
> also not permitted are:
> c) username, real name, company name or (e-mail?) address
> in any form (as-is, reversed, capitalized, doubled, etc.).
> (we can check only against username, gecos and hostname)
>
> CAVEAT: we cannot check for this without the use of dictionaries:
> d) common and obvious letter-number replacements
> (e.g. replace the letter O with number 0)
> such as "M1cr0$0ft" or "P at ssw0rd".
>*/
>
>#include <ctype.h>
>#include <unistd.h>
>#include <string.h>
>
>#include "libbb.h"
>
>#define MINLEN 6
I think empty passwords should be allowed too, at least optional. YMMV.
>
>static int string_checker_helper(const char *p1, const char *p2)
perhaps attribute_pure
>{
> /* as-is or capitalized */
> if (strcasecmp(p1, p2) == 0
> /* as sub-string */
> || strcasestr(p2, p1) != NULL
> /* invert in case haystack is shorter than needle */
> || strcasestr(p1, p2) != NULL)
> return 1;
> return 0;
>}
>
>static int string_checker(const char *p1, const char *p2)
>{
> int size;
> /* check string */
> int ret = string_checker_helper(p1, p2);
> /* Make our own copy */
> char *p = bb_xstrdup(p1);
> /* reverse string */
> size = strlen(p);
>
> while(size--) {
> *p = p1[size];
> p++;
> }
> /* restore pointer */
> p -= strlen(p1);
> /* check reversed string */
> ret |= string_checker_helper(p, p2);
> /* clean up */
> memset(p, 0, strlen(p));
> free(p);
> return ret;
>}
>
>#define LOWERCASE 1
>#define UPPERCASE 2
>#define NUMBERS 4
>#define SPECIAL 8
>
>static const char *obscure_msg(const char *old_p, const char *new_p, const struct passwd *pw)
>{
> int i;
> int c;
> int mixed = 0;
> const char *p;
> char hostname[255];
>
> /* size */
> if (!new_p || strlen(new_p) < MINLEN) return("to short");
s/to/too/
>
> /* 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 (string_checker(new_p, pw->pw_gecos)) return "similar to gecos";
> /* hostname as-is, as sub-string, reversed, capitalized, doubled */
> if(gethostname(hostname, 255) == 0) {
> if (string_checker(new_p, hostname)) return "similar to hostname";
> }
> /* Must contain a mix of: */
> for (i = 0; i < strlen(new_p); i++) {
>#if 0
> /* Forbbidden chars: is this needed? */
> if ( new_p[i] < 32 || new_p[i] == 126 ) /* Can we allow space ? new_p[i] == 33 */
space is ok, i think.
> return "contains illegal characters";
>#endif
> /* lowercase */
> if (islower(new_p[i])) /* a-z */
> mixed |= LOWERCASE;
> /* uppercase */
> else if (isupper(new_p[i])) /* A-Z */
> mixed |= UPPERCASE;
> /* numbers */
> else if (isdigit(new_p[i])) /* 0-9 */
> mixed |= NUMBERS;
> /* special characters */
> else
> mixed |= SPECIAL;
>
> /* More than 50% similar characters? */
> c = 0;
> p = new_p;
> while (1) {
> if ((p = strchr(p, new_p[i])) == NULL) break;
Look at .indent.pro; the "break" should go on it's own line, iirc.
> c++;
> if (!++p) break; /* move past the matched char if possible */
> }
>
> if (c >= (strlen(new_p) / 2)) return "to much similar characters";
s/to much/too many/
> }
>
> if (mixed < 15) return "to weak";
s/to /too /g;# also: put return into a new line. This makes the code
more readable..
>
> 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;
>}
>
>extern int obscure(const char *old, const char *newval, const struct passwd *pwdp)
>{
> const char *msg = obscure_msg(old, newval, pwdp);
>
> if (msg != NULL) {
> printf("Bad password: %s.\n", msg);
> return 1;
> }
> return 0;
>}
>
>
>/* END CODE */
>/*
>Local Variables:
>c-file-style: "linux"
>c-basic-offset: 4
>tab-width: 4
>End:
>*/
Looks nice from a short glance :)
More information about the busybox
mailing list