source: MondoRescue/branches/stable/mindi-busybox/libbb/obscure.c @ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 4.6 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini weak password checker implementation for busybox
4 *
5 * Copyright (C) 2006 Tito Ragusa <farmatito@tiscali.it>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */
9
10/*  A good password:
11    1)  should contain at least six characters (man passwd);
12    2)  empty passwords are not permitted;
13    3)  should contain a mix of four different types of characters
14        upper case letters,
15        lower case letters,
16        numbers,
17        special characters such as !@#$%^&*,;".
18    This password types should not  be permitted:
19    a)  pure numbers: birthdates, social security number, license plate, phone numbers;
20    b)  words and all letters only passwords (uppercase, lowercase or mixed)
21        as palindromes, consecutive or repetitive letters
22        or adjacent letters on your keyboard;
23    c)  username, real name, company name or (e-mail?) address
24        in any form (as-is, reversed, capitalized, doubled, etc.).
25        (we can check only against username, gecos and hostname)
26    d)  common and obvious letter-number replacements
27        (e.g. replace the letter O with number 0)
28        such as "M1cr0$0ft" or "P@ssw0rd" (CAVEAT: we cannot check for them
29        without the use of a dictionary).
30
31    For each missing type of characters an increase of password length is
32    requested.
33
34    If user is root we warn only.
35
36    CAVEAT: some older versions of crypt() truncates passwords to 8 chars,
37    so that aaaaaaaa1Q$ is equal to aaaaaaaa making it possible to fool
38    some of our checks. We don't test for this special case as newer versions
39    of crypt do not truncate passwords.
40*/
41
42#include <ctype.h>
43#include <unistd.h>
44#include <string.h>
45#include <strings.h>
46
47#include "libbb.h"
48
49
50/* passwords should consist of 6 (to 8 characters) */
51#define MINLEN 6
52
53
54static int string_checker_helper(const char *p1, const char *p2) __attribute__ ((__pure__));
55
56static int string_checker_helper(const char *p1, const char *p2)
57{
58    /* as-is or capitalized */
59    if (strcasecmp(p1, p2) == 0
60    /* as sub-string */
61    || strcasestr(p2, p1) != NULL
62    /* invert in case haystack is shorter than needle */
63    || strcasestr(p1, p2) != NULL)
64        return 1;
65    return 0;
66}
67
68static int string_checker(const char *p1, const char *p2)
69{
70    int size;
71    /* check string */
72    int ret = string_checker_helper(p1, p2);
73    /* Make our own copy */
74    char *p = bb_xstrdup(p1);
75    /* reverse string */
76    size = strlen(p);
77
78    while (size--) {
79        *p = p1[size];
80        p++;
81    }
82    /* restore pointer */
83    p -= strlen(p1);
84    /* check reversed string */
85    ret |= string_checker_helper(p, p2);
86    /* clean up */
87    memset(p, 0, strlen(p1));
88    free(p);
89    return ret;
90}
91
92#define LOWERCASE          1
93#define UPPERCASE          2
94#define NUMBERS            4
95#define SPECIAL            8
96
97static const char *obscure_msg(const char *old_p, const char *new_p, const struct passwd *pw)
98{
99    int i;
100    int c;
101    int length;
102    int mixed = 0;
103    /* Add 1 for each type of characters to the minlen of password */
104    int size = MINLEN + 8;
105    const char *p;
106    char hostname[255];
107
108    /* size */
109    if (!new_p || (length = strlen(new_p)) < MINLEN)
110        return("too short");
111
112    /* no username as-is, as sub-string, reversed, capitalized, doubled */
113    if (string_checker(new_p, pw->pw_name)) {
114        return "similar to username";
115    }
116    /* no gecos as-is, as sub-string, reversed, capitalized, doubled */
117    if (*pw->pw_gecos && string_checker(new_p, pw->pw_gecos)) {
118        return "similar to gecos";
119    }
120    /* hostname as-is, as sub-string, reversed, capitalized, doubled */
121    if (gethostname(hostname, 255) == 0) {
122        hostname[254] = '\0';
123        if (string_checker(new_p, hostname)) {
124            return "similar to hostname";
125        }
126    }
127
128    /* Should / Must contain a mix of: */
129    for (i = 0; i < length; i++) {
130        if (islower(new_p[i])) {        /* a-z */
131            mixed |= LOWERCASE;
132        } else if (isupper(new_p[i])) { /* A-Z */
133            mixed |= UPPERCASE;
134        } else if (isdigit(new_p[i])) { /* 0-9 */
135            mixed |= NUMBERS;
136        } else  {                       /* special characters */
137            mixed |= SPECIAL;
138        }
139        /* More than 50% similar characters ? */
140        c = 0;
141        p = new_p;
142        while (1) {
143            if ((p = strchr(p, new_p[i])) == NULL) {
144                break;
145            }
146            c++;
147            if (!++p) {
148                break; /* move past the matched char if possible */
149            }
150        }
151
152        if (c >= (length / 2)) {
153            return "too many similar characters";
154        }
155    }
156    for (i=0; i<4; i++)
157        if (mixed & (1<<i)) size -= 2;
158    if (length < size)
159        return "too weak";
160
161    if (old_p && old_p[0] != '\0') {
162        /* check vs. old password */
163        if (string_checker(new_p, old_p)) {
164            return "similar to old password";
165        }
166    }
167    return NULL;
168}
169
170int obscure(const char *old, const char *newval, const struct passwd *pwdp)
171{
172    const char *msg;
173
174    if ((msg = obscure_msg(old, newval, pwdp))) {
175        printf("Bad password: %s.\n", msg);
176        /* If user is root warn only */
177        return (getuid())? 1 : 0;
178    }
179    return 0;
180}
Note: See TracBrowser for help on using the repository browser.