1/* 2 * Copyright 1989, 1990, 1991, 1992, John F. Haugh II 3 * All rights reserved. 4 * 5 * Permission is granted to copy and create derivative works for any 6 * non-commercial purpose, provided this copyright notice is preserved 7 * in all copies of source code, or included in human readable form 8 * and conspicuously displayed on all copies of object code or 9 * distribution media. 10 */ 11 12#include <ctype.h> 13#ifndef BSD 14#include <string.h> 15#include <memory.h> 16#else 17#include <strings.h> 18#define strchr index 19#define strrchr rindex 20#endif 21#include "config.h" 22 23#ifndef lint 24static char sccsid[] = "@(#)obscure.c 3.6 20:37:32 3/7/92"; 25#endif 26 27extern int getdef_bool(); 28extern int getdef_num(); 29 30#ifdef NEED_STRSTR 31/* 32 * strstr - find substring in string 33 */ 34 35char * 36strstr (string, pattern) 37char *string; 38char *pattern; 39{ 40 char *cp; 41 int len; 42 43 len = strlen (pattern); 44 45 for (cp = string;cp = strchr (cp, *pattern);) { 46 if (strncmp (cp, pattern, len) == 0) 47 return cp; 48 49 cp++; 50 } 51 return 0; 52} 53#endif 54 55/* 56 * Obscure - see if password is obscure enough. 57 * 58 * The programmer is encouraged to add as much complexity to this 59 * routine as desired. Included are some of my favorite ways to 60 * check passwords. 61 */ 62 63/*ARGSUSED*/ 64int obscure (old, new) 65char *old; 66char *new; 67{ 68 int i; 69 char oldmono[32]; 70 char newmono[32]; 71 char wrapped[64]; 72 73 if (old[0] == '\0') 74 return (1); 75 76 if ( strlen(new) < getdef_num("PASS_MIN_LEN", 0) ) { 77 printf ("Too short. "); 78 return (0); 79 } 80 81 /* 82 * Remaining checks are optional. 83 */ 84 if ( !getdef_bool("OBSCURE_CHECKS_ENAB") ) 85 return (1); 86 87 for (i = 0;new[i];i++) 88 newmono[i] = tolower (new[i]); 89 90 for (i = 0;old[i];i++) 91 oldmono[i] = tolower (old[i]); 92 93 if (strcmp (new, old) == 0) { /* the same */ 94 printf ("No Change. "); 95 return (0); 96 } 97 if (palindrome (newmono, oldmono)) /* a palindrome */ 98 return (0); 99 100 if (strcmp (newmono, oldmono) == 0) { /* case shifted */ 101 printf ("Case changes only. "); 102 return (0); 103 } 104 if (similiar (newmono, oldmono)) /* jumbled version */ 105 return (0); 106 107 if (simple (old, new)) /* keyspace size */ 108 return (0); 109 110 strcpy (wrapped, oldmono); 111 strcat (wrapped, oldmono); 112 if (strstr (wrapped, newmono)) { 113 printf ("Rotated. "); 114 return (0); 115 } 116 117 118/* 119#define CRACKLIB_DICTPATH "/usr/local/lib/pw_dict" 120*/ 121 122#ifdef CRACKLIB_DICTPATH 123 { 124 char *msg; 125 126 if (msg = (char *) FascistCheck(new, CRACKLIB_DICTPATH)) 127 { 128 printf("Problem: %s. "); 129 return(0); 130 } 131 } 132#else 133#error /* You need to edit and uncomment the value of CRACKLIB_DICTPATH */ 134*** : this is a syntax error - it ought to balls up most compilers : *** 135#endif /* CRACKLIB_DICTPATH */ 136 137 return (1); 138} 139 140/* 141 * can't be a palindrome - like `R A D A R' or `M A D A M' 142 */ 143 144/*ARGSUSED*/ 145int palindrome (old, new) 146char *old; 147char *new; 148{ 149 int i, j; 150 151 i = strlen (new); 152 153 for (j = 0;j < i;j++) 154 if (new[i - j - 1] != new[j]) 155 return (0); 156 157 printf ("A palindrome. "); 158 return (1); 159} 160 161/* 162 * more than half of the characters are different ones. 163 */ 164 165/*ARGSUSED*/ 166int similiar (old, new) 167char *old; 168char *new; 169{ 170 int i, j; 171 char *strchr (); 172 173 for (i = j = 0;new[i] && old[i];i++) 174 if (strchr (new, tolower (old[i]))) 175 j++; 176 177 if (i >= j * 2) 178 return (0); 179 180 printf ("Too similiar. "); 181 return (1); 182} 183 184/* 185 * a nice mix of characters. 186 */ 187 188/*ARGSUSED*/ 189int simple (old, new) 190char *old; 191char *new; 192{ 193 int digits = 0; 194 int uppers = 0; 195 int lowers = 0; 196 int others = 0; 197 int size; 198 int i; 199 200 for (i = 0;new[i];i++) { 201 if (isdigit (new[i])) 202 digits++; 203 else if (isupper (new[i])) 204 uppers++; 205 else if (islower (new[i])) 206 lowers++; 207 else 208 others++; 209 } 210 211 /* 212 * The scam is this - a password of only one character type 213 * must be 8 letters long. Two types, 7, and so on. 214 */ 215 216 size = 9; 217 if (digits) size--; 218 if (uppers) size--; 219 if (lowers) size--; 220 if (others) size--; 221 222 if (size <= i) 223 return 0; 224 225 printf ("Too Simple. Use a longer password, or a mix of upper\n"); 226 printf ("and lower case letters and numerics. "); 227 return 1; 228} 229