You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
8.1 KiB
321 lines
8.1 KiB
--- a/check_password.c 2009-10-31 18:59:06.000000000 +0100 |
|
+++ b/check_password.c 2014-12-17 12:25:00.148900907 +0100 |
|
@@ -10,7 +10,7 @@ |
|
#include <slap.h> |
|
|
|
#ifdef HAVE_CRACKLIB |
|
-#include "crack.h" |
|
+#include <crack.h> |
|
#endif |
|
|
|
#if defined(DEBUG) |
|
@@ -34,18 +34,77 @@ |
|
#define PASSWORD_TOO_SHORT_SZ \ |
|
"Password for dn=\"%s\" is too short (%d/6)" |
|
#define PASSWORD_QUALITY_SZ \ |
|
- "Password for dn=\"%s\" does not pass required number of strength checks (%d of %d)" |
|
+ "Password for dn=\"%s\" does not pass required number of strength checks for the required character sets (%d of %d)" |
|
#define BAD_PASSWORD_SZ \ |
|
"Bad password for dn=\"%s\" because %s" |
|
+#define UNKNOWN_ERROR_SZ \ |
|
+ "An unknown error occurred, please see your systems administrator" |
|
|
|
typedef int (*validator) (char*); |
|
-static int read_config_file (char *); |
|
+static int read_config_file (); |
|
static validator valid_word (char *); |
|
static int set_quality (char *); |
|
static int set_cracklib (char *); |
|
|
|
int check_password (char *pPasswd, char **ppErrStr, Entry *pEntry); |
|
|
|
+struct config_entry { |
|
+ char* key; |
|
+ char* value; |
|
+ char* def_value; |
|
+} config_entries[] = { { "minPoints", NULL, "3"}, |
|
+ { "useCracklib", NULL, "1"}, |
|
+ { "minUpper", NULL, "0"}, |
|
+ { "minLower", NULL, "0"}, |
|
+ { "minDigit", NULL, "0"}, |
|
+ { "minPunct", NULL, "0"}, |
|
+ { NULL, NULL, NULL }}; |
|
+ |
|
+int get_config_entry_int(char* entry) { |
|
+ struct config_entry* centry = config_entries; |
|
+ |
|
+ int i = 0; |
|
+ char* key = centry[i].key; |
|
+ while (key != NULL) { |
|
+ if ( strncmp(key, entry, strlen(key)) == 0 ) { |
|
+ if ( centry[i].value == NULL ) { |
|
+ return atoi(centry[i].def_value); |
|
+ } |
|
+ else { |
|
+ return atoi(centry[i].value); |
|
+ } |
|
+ } |
|
+ i++; |
|
+ key = centry[i].key; |
|
+ } |
|
+ |
|
+ return -1; |
|
+} |
|
+ |
|
+void dealloc_config_entries() { |
|
+ struct config_entry* centry = config_entries; |
|
+ |
|
+ int i = 0; |
|
+ while (centry[i].key != NULL) { |
|
+ if ( centry[i].value != NULL ) { |
|
+ ber_memfree(centry[i].value); |
|
+ } |
|
+ i++; |
|
+ } |
|
+} |
|
+ |
|
+char* chomp(char *s) |
|
+{ |
|
+ char* t = ber_memalloc(strlen(s)+1); |
|
+ strncpy (t,s,strlen(s)+1); |
|
+ |
|
+ if ( t[strlen(t)-1] == '\n' ) { |
|
+ t[strlen(t)-1] = '\0'; |
|
+ } |
|
+ |
|
+ return t; |
|
+} |
|
+ |
|
static int set_quality (char *value) |
|
{ |
|
#if defined(DEBUG) |
|
@@ -84,12 +143,12 @@ |
|
char * parameter; |
|
validator dealer; |
|
} list[] = { { "minPoints", set_quality }, |
|
- { "useCracklib", set_cracklib }, |
|
- { "minUpper", set_digit }, |
|
- { "minLower", set_digit }, |
|
- { "minDigit", set_digit }, |
|
- { "minPunct", set_digit }, |
|
- { NULL, NULL } }; |
|
+ { "useCracklib", set_cracklib }, |
|
+ { "minUpper", set_digit }, |
|
+ { "minLower", set_digit }, |
|
+ { "minDigit", set_digit }, |
|
+ { "minPunct", set_digit }, |
|
+ { NULL, NULL } }; |
|
int index = 0; |
|
|
|
#if defined(DEBUG) |
|
@@ -98,7 +157,7 @@ |
|
|
|
while (list[index].parameter != NULL) { |
|
if (strlen(word) == strlen(list[index].parameter) && |
|
- strcmp(list[index].parameter, word) == 0) { |
|
+ strcmp(list[index].parameter, word) == 0) { |
|
#if defined(DEBUG) |
|
syslog(LOG_NOTICE, "check_password: Parameter accepted."); |
|
#endif |
|
@@ -114,13 +173,15 @@ |
|
return NULL; |
|
} |
|
|
|
-static int read_config_file (char *keyWord) |
|
+static int read_config_file () |
|
{ |
|
FILE * config; |
|
char * line; |
|
int returnValue = -1; |
|
|
|
- if ((line = ber_memcalloc(260, sizeof(char))) == NULL) { |
|
+ line = ber_memcalloc(260, sizeof(char)); |
|
+ |
|
+ if ( line == NULL ) { |
|
return returnValue; |
|
} |
|
|
|
@@ -133,6 +194,8 @@ |
|
return returnValue; |
|
} |
|
|
|
+ returnValue = 0; |
|
+ |
|
while (fgets(line, 256, config) != NULL) { |
|
char *start = line; |
|
char *word, *value; |
|
@@ -145,23 +208,40 @@ |
|
|
|
while (isspace(*start) && isascii(*start)) start++; |
|
|
|
- if (! isascii(*start)) |
|
+ /* If we've got punctuation, just skip the line. */ |
|
+ if ( ispunct(*start)) { |
|
+#if defined(DEBUG) |
|
+ /* Debug traces to syslog. */ |
|
+ syslog(LOG_NOTICE, "check_password: Skipped line |%s|", line); |
|
+#endif |
|
continue; |
|
+ } |
|
|
|
- if ((word = strtok(start, " \t")) && (dealer = valid_word(word)) && (strcmp(keyWord,word)==0)) { |
|
- if ((value = strtok(NULL, " \t")) == NULL) |
|
- continue; |
|
+ if( isascii(*start)) { |
|
+ |
|
+ struct config_entry* centry = config_entries; |
|
+ int i = 0; |
|
+ char* keyWord = centry[i].key; |
|
+ if ((word = strtok(start, " \t")) && (value = strtok(NULL, " \t"))) { |
|
+ while ( keyWord != NULL ) { |
|
+ if ((strncmp(keyWord,word,strlen(keyWord)) == 0) && (dealer = valid_word(word)) ) { |
|
|
|
#if defined(DEBUG) |
|
- syslog(LOG_NOTICE, "check_password: Word = %s, value = %s", word, value); |
|
+ syslog(LOG_NOTICE, "check_password: Word = %s, value = %s", word, value); |
|
#endif |
|
|
|
- returnValue = (*dealer)(value); |
|
+ centry[i].value = chomp(value); |
|
+ break; |
|
+ } |
|
+ i++; |
|
+ keyWord = centry[i].key; |
|
+ } |
|
+ } |
|
} |
|
} |
|
- |
|
fclose(config); |
|
ber_memfree(line); |
|
+ |
|
return returnValue; |
|
} |
|
|
|
@@ -170,7 +250,7 @@ |
|
if (curlen < nextlen + MEMORY_MARGIN) { |
|
#if defined(DEBUG) |
|
syslog(LOG_WARNING, "check_password: Reallocating szErrStr from %d to %d", |
|
- curlen, nextlen + MEMORY_MARGIN); |
|
+ curlen, nextlen + MEMORY_MARGIN); |
|
#endif |
|
ber_memfree(*target); |
|
curlen = nextlen + MEMORY_MARGIN; |
|
@@ -180,7 +260,7 @@ |
|
return curlen; |
|
} |
|
|
|
- int |
|
+int |
|
check_password (char *pPasswd, char **ppErrStr, Entry *pEntry) |
|
{ |
|
|
|
@@ -210,20 +290,22 @@ |
|
nLen = strlen (pPasswd); |
|
if ( nLen < 6) { |
|
mem_len = realloc_error_message(&szErrStr, mem_len, |
|
- strlen(PASSWORD_TOO_SHORT_SZ) + |
|
- strlen(pEntry->e_name.bv_val) + 1); |
|
+ strlen(PASSWORD_TOO_SHORT_SZ) + |
|
+ strlen(pEntry->e_name.bv_val) + 1); |
|
sprintf (szErrStr, PASSWORD_TOO_SHORT_SZ, pEntry->e_name.bv_val, nLen); |
|
goto fail; |
|
} |
|
|
|
- /* Read config file */ |
|
- minQuality = read_config_file("minPoints"); |
|
+ if (read_config_file() == -1) { |
|
+ syslog(LOG_ERR, "Warning: Could not read values from config file %s. Using defaults.", CONFIG_FILE); |
|
+ } |
|
|
|
- useCracklib = read_config_file("useCracklib"); |
|
- minUpper = read_config_file("minUpper"); |
|
- minLower = read_config_file("minLower"); |
|
- minDigit = read_config_file("minDigit"); |
|
- minPunct = read_config_file("minPunct"); |
|
+ minQuality = get_config_entry_int("minPoints"); |
|
+ useCracklib = get_config_entry_int("useCracklib"); |
|
+ minUpper = get_config_entry_int("minUpper"); |
|
+ minLower = get_config_entry_int("minLower"); |
|
+ minDigit = get_config_entry_int("minDigit"); |
|
+ minPunct = get_config_entry_int("minPunct"); |
|
|
|
/** The password must have at least minQuality strength points with one |
|
* point for the first occurrance of a lower, upper, digit and |
|
@@ -232,8 +314,6 @@ |
|
|
|
for ( i = 0; i < nLen; i++ ) { |
|
|
|
- if ( nQuality >= minQuality ) break; |
|
- |
|
if ( islower (pPasswd[i]) ) { |
|
minLower--; |
|
if ( !nLower && (minLower < 1)) { |
|
@@ -279,12 +359,23 @@ |
|
} |
|
} |
|
|
|
- if ( nQuality < minQuality ) { |
|
+ /* |
|
+ * If you have a required field, then it should be required in the strength |
|
+ * checks. |
|
+ */ |
|
+ |
|
+ if ( |
|
+ (minLower > 0 ) || |
|
+ (minUpper > 0 ) || |
|
+ (minDigit > 0 ) || |
|
+ (minPunct > 0 ) || |
|
+ (nQuality < minQuality) |
|
+ ) { |
|
mem_len = realloc_error_message(&szErrStr, mem_len, |
|
- strlen(PASSWORD_QUALITY_SZ) + |
|
- strlen(pEntry->e_name.bv_val) + 2); |
|
+ strlen(PASSWORD_QUALITY_SZ) + |
|
+ strlen(pEntry->e_name.bv_val) + 2); |
|
sprintf (szErrStr, PASSWORD_QUALITY_SZ, pEntry->e_name.bv_val, |
|
- nQuality, minQuality); |
|
+ nQuality, minQuality); |
|
goto fail; |
|
} |
|
|
|
@@ -306,7 +397,7 @@ |
|
for ( j = 0; j < 3; j++ ) { |
|
|
|
snprintf (filename, FILENAME_MAXLEN - 1, "%s.%s", \ |
|
- CRACKLIB_DICTPATH, ext[j]); |
|
+ CRACKLIB_DICTPATH, ext[j]); |
|
|
|
if (( fp = fopen ( filename, "r")) == NULL ) { |
|
|
|
@@ -326,9 +417,9 @@ |
|
r = (char *) FascistCheck (pPasswd, CRACKLIB_DICTPATH); |
|
if ( r != NULL ) { |
|
mem_len = realloc_error_message(&szErrStr, mem_len, |
|
- strlen(BAD_PASSWORD_SZ) + |
|
- strlen(pEntry->e_name.bv_val) + |
|
- strlen(r)); |
|
+ strlen(BAD_PASSWORD_SZ) + |
|
+ strlen(pEntry->e_name.bv_val) + |
|
+ strlen(r)); |
|
sprintf (szErrStr, BAD_PASSWORD_SZ, pEntry->e_name.bv_val, r); |
|
goto fail; |
|
} |
|
@@ -342,15 +433,15 @@ |
|
} |
|
|
|
#endif |
|
- |
|
+ dealloc_config_entries(); |
|
*ppErrStr = strdup (""); |
|
ber_memfree(szErrStr); |
|
return (LDAP_SUCCESS); |
|
|
|
fail: |
|
+ dealloc_config_entries(); |
|
*ppErrStr = strdup (szErrStr); |
|
ber_memfree(szErrStr); |
|
return (EXIT_FAILURE); |
|
|
|
} |
|
-
|
|
|