summaryrefslogtreecommitdiff
path: root/i/pc104/initrd/conf/busybox/libbb/obscure.c
diff options
context:
space:
mode:
Diffstat (limited to 'i/pc104/initrd/conf/busybox/libbb/obscure.c')
-rw-r--r--i/pc104/initrd/conf/busybox/libbb/obscure.c170
1 files changed, 170 insertions, 0 deletions
diff --git a/i/pc104/initrd/conf/busybox/libbb/obscure.c b/i/pc104/initrd/conf/busybox/libbb/obscure.c
new file mode 100644
index 0000000..2599095
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/libbb/obscure.c
@@ -0,0 +1,170 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini weak password checker implementation for busybox
+ *
+ * Copyright (C) 2006 Tito Ragusa <farmatito@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);
+ 2) empty passwords are not permitted;
+ 3) should contain a mix of four different types of characters
+ upper case letters,
+ lower case letters,
+ numbers,
+ special characters such as !@#$%^&*,;".
+ This password types should not be 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;
+ 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)
+ d) common and obvious letter-number replacements
+ (e.g. replace the letter O with number 0)
+ such as "M1cr0$0ft" or "P@ssw0rd" (CAVEAT: we cannot check for them
+ without the use of a dictionary).
+
+ For each missing type of characters an increase of password length is
+ requested.
+
+ If user is root we warn only.
+
+ CAVEAT: some older versions of crypt() truncates passwords to 8 chars,
+ so that aaaaaaaa1Q$ is equal to aaaaaaaa making it possible to fool
+ some of our checks. We don't test for this special case as newer versions
+ of crypt do not truncate passwords.
+*/
+
+#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)
+{
+ /* 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 = 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(p1));
+ 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 length;
+ int mixed = 0;
+ /* Add 2 for each type of characters to the minlen of password */
+ int size = CONFIG_PASSWORD_MINLEN + 8;
+ const char *p;
+ char hostname[255];
+
+ /* size */
+ if (!new_p || (length = strlen(new_p)) < CONFIG_PASSWORD_MINLEN)
+ return "too short";
+
+ /* 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 */
+ if (gethostname(hostname, 255) == 0) {
+ hostname[254] = '\0';
+ if (string_checker(new_p, hostname)) {
+ 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) {
+ if ((p = strchr(p, new_p[i])) == 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;
+}
+
+int 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;
+}