diff options
author | Tomas Mraz <tmraz@redhat.com> | 2011-09-21 11:39:19 +0200 |
---|---|---|
committer | Tomas Mraz <tmraz@redhat.com> | 2011-09-21 11:39:19 +0200 |
commit | 4df3d90fec8fc92881a47eebcbc71af5bfadcb21 (patch) | |
tree | 3ce15c164ab46f87e8b1b85fd5ff333b67ed2747 /src | |
parent | f2704b82f30f1cf83307f9015f61aaef38f1d125 (diff) | |
download | libpwquality-4df3d90fec8fc92881a47eebcbc71af5bfadcb21.tar.gz |
Incorporate better error message handling.
Diffstat (limited to 'src')
-rw-r--r-- | src/check.c | 59 | ||||
-rw-r--r-- | src/error.c | 63 | ||||
-rw-r--r-- | src/generate.c | 2 | ||||
-rw-r--r-- | src/libpwquality.map | 1 | ||||
-rw-r--r-- | src/pam_pwquality.c | 50 | ||||
-rw-r--r-- | src/pwmake.c | 31 | ||||
-rw-r--r-- | src/pwquality.h | 50 | ||||
-rw-r--r-- | src/pwscore.c | 67 | ||||
-rw-r--r-- | src/settings.c | 40 |
9 files changed, 190 insertions, 173 deletions
diff --git a/src/check.c b/src/check.c index c02d1b4..1b65409 100644 --- a/src/check.c +++ b/src/check.c @@ -191,7 +191,7 @@ numclass(pwquality_settings_t *pwq, * present in the password */ static int -simple(pwquality_settings_t *pwq, const char *new) +simple(pwquality_settings_t *pwq, const char *new, void **auxerror) { int digits = 0; int uppers = 0; @@ -227,27 +227,42 @@ simple(pwquality_settings_t *pwq, const char *new) if (pwq->dig_credit >= 0) size -= digits; - else if (digits < pwq->dig_credit * -1) + else if (digits < -pwq->dig_credit) { + if (auxerror) + *auxerror = (void *)(long)-pwq->dig_credit; return PWQ_ERROR_MIN_DIGITS; + } if (pwq->up_credit >= 0) size -= uppers; - else if (uppers < pwq->up_credit * -1) + else if (uppers < -pwq->up_credit) { + if (auxerror) + *auxerror = (void *)(long)-pwq->up_credit; return PWQ_ERROR_MIN_UPPERS; + } if (pwq->low_credit >= 0) size -= lowers; - else if (lowers < pwq->low_credit * -1) + else if (lowers < -pwq->low_credit) { + if (auxerror) + *auxerror = (void *)(long)-pwq->low_credit; return PWQ_ERROR_MIN_LOWERS; + } if (pwq->oth_credit >= 0) size -= others; - else if (others < pwq->oth_credit * -1) + else if (others < -pwq->oth_credit) { + if (auxerror) + *auxerror = (void *)(long)-pwq->oth_credit; return PWQ_ERROR_MIN_OTHERS; + } if (size <= i) return 0; + if (auxerror) + *auxerror = (void *)(long)size; + return PWQ_ERROR_MIN_LENGTH; } @@ -256,7 +271,7 @@ simple(pwquality_settings_t *pwq, const char *new) */ static int -consecutive(pwquality_settings_t *pwq, const char *new) +consecutive(pwquality_settings_t *pwq, const char *new, void **auxerror) { char c; int i; @@ -268,8 +283,11 @@ consecutive(pwquality_settings_t *pwq, const char *new) for (i = 0; new[i]; i++) { if (i > 0 && new[i] == c) { ++same; - if (same > pwq->max_repeat) + if (same > pwq->max_repeat) { + if (auxerror) + *auxerror = (void *)(long)pwq->max_repeat; return 1; + } } else { c = new[i]; same = 1; @@ -301,7 +319,7 @@ x_strdup(const char *string) static int password_check(pwquality_settings_t *pwq, - const char *new, const char *old) + const char *new, const char *old, void **auxerror) { int rv = 0; char *oldmono = NULL, *newmono, *wrapped = NULL; @@ -332,15 +350,19 @@ password_check(pwquality_settings_t *pwq, rv = similar(pwq, oldmono, newmono); if (!rv) - rv = simple(pwq, new); + rv = simple(pwq, new, auxerror); if (!rv && wrapped && strstr(wrapped, newmono)) rv = PWQ_ERROR_ROTATED; - if (!rv && numclass(pwq, new) < pwq->min_class) + if (!rv && numclass(pwq, new) < pwq->min_class) { rv = PWQ_ERROR_MIN_CLASSES; + if (auxerror) { + *auxerror = (void *)(long)pwq->min_class; + } + } - if (!rv && consecutive(pwq, new)) + if (!rv && consecutive(pwq, new, auxerror)) rv = PWQ_ERROR_MAX_CONSECUTIVE; if (newmono) { @@ -417,17 +439,18 @@ password_score(pwquality_settings_t *pwq, const char *password) } /* check the password according to the settings - * it returns either score <0-100>, negative error number, - * and in case of PWQ_ERROR_CRACKLIB also auxiliary - * error message returned from cracklib; + * it returns either score <0-100> or negative error number; * the old password is optional */ int pwquality_check(pwquality_settings_t *pwq, const char *password, - const char *oldpassword, const char **error) + const char *oldpassword, void **auxerror) { const char *msg; int score; + if (auxerror) + *auxerror = NULL; + if (password == NULL || *password == '\0') { return PWQ_ERROR_EMPTY_PASSWORD; } @@ -438,12 +461,12 @@ pwquality_check(pwquality_settings_t *pwq, const char *password, msg = FascistCheck(password, pwq->dict_path); if (msg) { - if (error) - *error = msg; + if (auxerror) + *auxerror = (void *)msg; return PWQ_ERROR_CRACKLIB_CHECK; } - score = password_check(pwq, password, oldpassword); + score = password_check(pwq, password, oldpassword, auxerror); if (score == 0) { score = password_score(pwq, password); } diff --git a/src/error.c b/src/error.c index c1f6e26..790dbed 100644 --- a/src/error.c +++ b/src/error.c @@ -7,16 +7,16 @@ #include <stdio.h> #include <string.h> +#include <stdlib.h> #include "pwquality.h" #include "pwqprivate.h" /* Create an error message, the auxerror is generated by the library call * and so it can be an arbitrary thing - it does not have to be a pointer - * to string. Also in future it might be a string that will have to be - * deallocated inside this function. */ -char * -pwquality_strerror(char *buf, size_t len, int rv, char *auxerror) + * to string. */ +const char * +pwquality_strerror(char *buf, size_t len, int rv, void *auxerror) { static char intbuf[PWQ_MAX_ERROR_MESSAGE_LEN]; @@ -27,6 +27,11 @@ pwquality_strerror(char *buf, size_t len, int rv, char *auxerror) switch(rv) { case PWQ_ERROR_MEM_ALLOC: + if (auxerror) { + snprintf(buf, len, "%s - %s", _("Memory allocation error when setting"), (const char *)auxerror); + free(auxerror); + return buf; + } return _("Memory allocation error"); case PWQ_ERROR_SAME_PASSWORD: return _("The password is the same as the old one"); @@ -38,31 +43,31 @@ pwquality_strerror(char *buf, size_t len, int rv, char *auxerror) return _("The password is too similar to the old one"); case PWQ_ERROR_MIN_DIGITS: if (auxerror) { - snprintf(buf, len, _("The password contains less than %d digits"), (int)auxerror); + snprintf(buf, len, _("The password contains less than %ld digits"), (long)auxerror); return buf; } return _("The password contains too few digits"); case PWQ_ERROR_MIN_UPPERS: if (auxerror) { - snprintf(buf, len, _("The password contains less than %d uppercase letters"), (int)auxerror); + snprintf(buf, len, _("The password contains less than %ld uppercase letters"), (long)auxerror); return buf; } return _("The password contains too few uppercase letters"); case PWQ_ERROR_MIN_LOWERS: if (auxerror) { - snprintf(buf, len, _("The password contains less than %d lowercase letters"), (int)auxerror); + snprintf(buf, len, _("The password contains less than %ld lowercase letters"), (long)auxerror); return buf; } return _("The password contains too few lowercase letters"); case PWQ_ERROR_MIN_OTHERS: if (auxerror) { - snprintf(buf, len, _("The password contains less than %d non-alphanumeric characters"), (int)auxerror); + snprintf(buf, len, _("The password contains less than %ld non-alphanumeric characters"), (long)auxerror); return buf; } return _("The password contains too few non-alphanumeric characters"); case PWQ_ERROR_MIN_LENGTH: if (auxerror) { - snprintf(buf, len, _("The password is shorter than %d characters"), (int)auxerror); + snprintf(buf, len, _("The password is shorter than %ld characters"), (long)auxerror); return buf; } return _("The password is too short"); @@ -70,13 +75,13 @@ pwquality_strerror(char *buf, size_t len, int rv, char *auxerror) return _("The password is just rotated old one"); case PWQ_ERROR_MIN_CLASSES: if (auxerror) { - snprintf(buf, len, _("The password contains less than %d character classes"), (int)auxerror); + snprintf(buf, len, _("The password contains less than %ld character classes"), (long)auxerror); return buf; } return _("The password does not contain enough character classes"); case PWQ_ERROR_MAX_CONSECUTIVE: if (auxerror) { - snprintf(buf, len, _("The password contains more than %d same characters consecutively"), (int)auxerror); + snprintf(buf, len, _("The password contains more than %ld same characters consecutively"), (long)auxerror); return buf; } return _("The password contains too many same characters consecutively"); @@ -88,10 +93,44 @@ pwquality_strerror(char *buf, size_t len, int rv, char *auxerror) return _("Password generation failed - required entropy too low for settings"); case PWQ_ERROR_CRACKLIB_CHECK: if (auxerror) { - snprintf(buf, len, "%s - %s", _("The password fails the dictionary check"), auxerror); + snprintf(buf, len, "%s - %s", _("The password fails the dictionary check"), (const char *)auxerror); return buf; } return _("The password fails the dictionary check"); + case PWQ_ERROR_UNKNOWN_SETTING: + if (auxerror) { + snprintf(buf, len, "%s - %s", _("Unknown setting"), (const char *)auxerror); + free(auxerror); + return buf; + } + return _("Unknown setting"); + case PWQ_ERROR_INTEGER: + if (auxerror) { + snprintf(buf, len, "%s - %s", _("Bad integer value of setting"), (const char *)auxerror); + free(auxerror); + return buf; + } + return _("Bad integer value"); + case PWQ_ERROR_NON_INT_SETTING: + if (auxerror) { + snprintf(buf, len, _("Setting %s is not of integer type"), (const char *)auxerror); + free(auxerror); + return buf; + } + return _("Setting is not of integer type"); + case PWQ_ERROR_NON_STR_SETTING: + if (auxerror) { + snprintf(buf, len, _("Setting %s is not of string type"), (const char *)auxerror); + free(auxerror); + return buf; + } + return _("Setting is not of string type"); + case PWQ_ERROR_CFGFILE_OPEN: + return _("Opening the configuration file failed"); + case PWQ_ERROR_CFGFILE_MALFORMED: + return _("The configuration file is malformed"); + case PWQ_ERROR_FATAL_FAILURE: + return _("Fatal failure"); default: return _("Unknown error"); } diff --git a/src/generate.c b/src/generate.c index 24c158b..193e27b 100644 --- a/src/generate.c +++ b/src/generate.c @@ -118,7 +118,7 @@ pwquality_generate(pwquality_settings_t *pwq, int entropy_bits, char **password) tmp = malloc(maxlen); if (tmp == NULL) { - return PWQ_ERROR_FATAL_FAILURE; + return PWQ_ERROR_MEM_ALLOC; } do { diff --git a/src/libpwquality.map b/src/libpwquality.map index 231dd02..f49ef96 100644 --- a/src/libpwquality.map +++ b/src/libpwquality.map @@ -10,6 +10,7 @@ LIBPWQUALITY_1.0 { pwquality_get_str_value; pwquality_generate; pwquality_check; + pwquality_strerror; local: *; }; diff --git a/src/pam_pwquality.c b/src/pam_pwquality.c index e3cd522..8c9e164 100644 --- a/src/pam_pwquality.c +++ b/src/pam_pwquality.c @@ -52,16 +52,20 @@ _pam_parse (pam_handle_t *pamh, struct module_options *opt, int argc, const char **argv) { int ctrl = 0; + int rv; pwquality_settings_t *pwq; + void *auxerror; + char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; pwq = pwquality_default_settings(); if (pwq == NULL) return -1; /* just log error here */ - if (pwquality_read_config(pwq, NULL)) + if ((rv=pwquality_read_config(pwq, NULL, &auxerror)) != 0) pam_syslog(pamh, LOG_ERR, - "Reading pwquality configuration file failed: %m"); + "Reading pwquality configuration file failed: %s", + pwquality_strerror(buf, sizeof(buf), rv, auxerror)); /* step through arguments */ for (ctrl = 0; argc-- > 0; ++argv) { @@ -96,41 +100,6 @@ _pam_parse (pam_handle_t *pamh, struct module_options *opt, return ctrl; } -static const char * -make_error_message(int rv, const char *crack_msg) -{ - switch(rv) { - case PWQ_ERROR_MEM_ALLOC: - return _("memory allocation error"); - case PWQ_ERROR_SAME_PASSWORD: - return _("is the same as the old one"); - case PWQ_ERROR_PALINDROME: - return _("is a palindrome"); - case PWQ_ERROR_CASE_CHANGES_ONLY: - return _("case changes only"); - case PWQ_ERROR_TOO_SIMILAR: - return _("is too similar to the old one"); - case PWQ_ERROR_MIN_DIGITS: - case PWQ_ERROR_MIN_UPPERS: - case PWQ_ERROR_MIN_LOWERS: - case PWQ_ERROR_MIN_OTHERS: - case PWQ_ERROR_MIN_LENGTH: - return _("is too simple"); - case PWQ_ERROR_ROTATED: - return _("is rotated"); - case PWQ_ERROR_MIN_CLASSES: - return _("not enough character classes"); - case PWQ_ERROR_MAX_CONSECUTIVE: - return _("contains too many same characters consecutively"); - case PWQ_ERROR_EMPTY_PASSWORD: - return _("No password supplied"); - case PWQ_ERROR_CRACKLIB_CHECK: - return crack_msg; - default: - return _("Error in service module"); - } -} - PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) @@ -165,7 +134,7 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, tries = 0; while (tries < options.retry_times) { - const char *crack_msg; + void *auxerror; const char *newtoken = NULL; tries++; @@ -188,11 +157,12 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags, } /* now test this passwd against libpwquality */ - retval = pwquality_check(options.pwq, newtoken, oldtoken, &crack_msg); + retval = pwquality_check(options.pwq, newtoken, oldtoken, &auxerror); if (retval < 0) { const char *msg; - msg = make_error_message(retval, crack_msg); + char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; + msg = pwquality_strerror(buf, sizeof(buf), retval, auxerror); if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh, LOG_DEBUG, "bad password: %s", msg); pam_error(pamh, _("BAD PASSWORD: %s"), msg); diff --git a/src/pwmake.c b/src/pwmake.c index 876ef1c..6c4c84e 100644 --- a/src/pwmake.c +++ b/src/pwmake.c @@ -12,6 +12,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <errno.h> +#include <libgen.h> #include "pwquality.h" @@ -20,20 +21,6 @@ usage(const char *progname) { fprintf(stderr, _("Usage: %s <entropy-bits>\n"), progname); } -static const char * -make_error_message(int rv) -{ - switch(rv) { - case PWQ_ERROR_MEM_ALLOC: - return _("Memory allocation error"); - case PWQ_ERROR_RNG: - return _("Cannot obtain random numbers from the RNG device"); - case PWQ_ERROR_GENERATION_FAILED: - return _("Password generation failed - required entropy too low for settings"); - default: - return _("Unknown error"); - } -} /* score a password */ int @@ -43,9 +30,14 @@ main(int argc, char *argv[]) char *password; int rv; int bits; + void *auxerror; + + setlocale(LC_ALL, ""); + bindtextdomain("libpwquality", "/usr/share/locale"); + textdomain("libpwquality"); if (argc != 2) { - usage(argv[0]); + usage(basename(argv[0])); exit(3); } @@ -53,16 +45,19 @@ main(int argc, char *argv[]) pwq = pwquality_default_settings(); if (pwq == NULL) { - fprintf(stderr, "Error: %s\n", _("Error: Memory allocation error")); + fprintf(stderr, "Error: %s\n", pwquality_strerror(NULL, 0, PWQ_ERROR_MEM_ALLOC, NULL)); exit(2); } - pwquality_read_config(pwq, NULL); + if ((rv = pwquality_read_config(pwq, NULL, &auxerror)) != 0) { + fprintf(stderr, "Error: %s\n", pwquality_strerror(NULL, 0, rv, auxerror)); + exit(3); + } rv = pwquality_generate(pwq, bits, &password); if (rv != 0) { - fprintf(stderr, "Error: %s\n", make_error_message(rv)); + fprintf(stderr, "Error: %s\n", pwquality_strerror(NULL, 0, rv, NULL)); exit(1); } diff --git a/src/pwquality.h b/src/pwquality.h index 5e7105b..e6de079 100644 --- a/src/pwquality.h +++ b/src/pwquality.h @@ -24,6 +24,8 @@ #define PWQ_MAX_ENTROPY_BITS 256 #define PWQ_MIN_ENTROPY_BITS 56 +#define PWQ_MAX_ERROR_MESSAGE_LEN 256 + #define PWQ_ERROR_SUCCESS 0 /* implicit, not used in the library code */ #define PWQ_ERROR_FATAL_FAILURE -1 #define PWQ_ERROR_INTEGER -2 @@ -52,56 +54,70 @@ typedef struct pwquality_settings pwquality_settings_t; -/* returns default pwquality settings to be used in other library calls */ +/* Return default pwquality settings to be used in other library calls. */ pwquality_settings_t * pwquality_default_settings(void); -/* frees pwquality settings data */ +/* Free pwquality settings data. */ void pwquality_free_settings(pwquality_settings_t *pwq); -/* parse the configuration file (if NULL then the default one) */ +/* Parse the configuration file (if cfgfile is NULL then the default one). + * If auxerror is not NULL it also possibly returns auxiliary error information + * that must be passed into pwquality_strerror() function. */ int -pwquality_read_config(pwquality_settings_t *pwq, const char *cfgfile); +pwquality_read_config(pwquality_settings_t *pwq, const char *cfgfile, + void **auxerror); -/* useful for setting the options as configured on a pam module +/* Useful for setting the options as configured on a pam module * command line in form of <opt>=<val> */ int pwquality_set_option(pwquality_settings_t *pwq, const char *option); -/* set value of an integer setting */ +/* Set value of an integer setting. */ int pwquality_set_int_value(pwquality_settings_t *pwq, int setting, int value); -/* set value of a string setting */ +/* Set value of a string setting. */ int pwquality_set_str_value(pwquality_settings_t *pwq, int setting, const char *value); -/* get value of an integer setting, or -1 if setting unknown */ +/* Get value of an integer setting. */ int -pwquality_get_int_value(pwquality_settings_t *pwq, int setting); +pwquality_get_int_value(pwquality_settings_t *pwq, int setting, int *value); -/* get value of a string setting, or NULL if setting unknown */ +/* Get value of a string setting, or NULL if setting unknown. */ const char * pwquality_get_str_value(pwquality_settings_t *pwq, int setting); -/* generate a random password of entropy_bits entropy and check it according to - * the settings */ +/* Generate a random password of entropy_bits entropy and check it according to + * the settings. */ int pwquality_generate(pwquality_settings_t *pwq, int entropy_bits, char **password); -/* check the password according to the settings - * it returns either score <0-100>, negative error number, - * and in case of PWQ_ERROR_CRACKLIB also auxiliary - * error message returned from cracklib +/* Check the password according to the settings. + * It returns either score <0-100>, negative error number, + * and possibly also auxiliary error information that must be + * passed into pwquality_strerror() function. * The old password is optional and can be NULL. + * The auxerror can be NULL - in that case the auxiliary error information + * is not returned. + * Not passing the *auxerror into pwquality_strerror() can lead to memory leaks. * The score depends on PWQ_SETTING_MIN_LENGTH. If it is set higher, * the score for the same passwords will be lower. */ int pwquality_check(pwquality_settings_t *pwq, const char *password, - const char *oldpassword, const char **error); + const char *oldpassword, void **auxerror); + +/* Translate the error code and auxiliary message into a localized + * text message. + * If buf is NULL it uses an internal static buffer which + * makes the function non-reentrant in that case. + * The returned pointer is not guaranteed to point to the buf. */ +const char * +pwquality_strerror(char *buf, size_t len, int errcode, void *auxerror); #endif /* PWQUALITY_H */ diff --git a/src/pwscore.c b/src/pwscore.c index 9046bbb..c9db396 100644 --- a/src/pwscore.c +++ b/src/pwscore.c @@ -12,6 +12,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <errno.h> +#include <libgen.h> #include "pwquality.h" @@ -21,66 +22,27 @@ usage(const char *progname) { fprintf(stderr, _(" The command reads the password to be scored from the standard input.\n")); } -static const char * -make_error_message(int rv, const char *crack_msg) -{ - static char buf[200]; - - switch(rv) { - case PWQ_ERROR_MEM_ALLOC: - return _("Memory allocation error"); - case PWQ_ERROR_SAME_PASSWORD: - return _("The password is the same as the old one"); - case PWQ_ERROR_PALINDROME: - return _("The password is a palindrome"); - case PWQ_ERROR_CASE_CHANGES_ONLY: - return _("The password differs with case changes only"); - case PWQ_ERROR_TOO_SIMILAR: - return _("The password is too similar to the old one"); - case PWQ_ERROR_MIN_DIGITS: - return _("The password contains too few digits"); - case PWQ_ERROR_MIN_UPPERS: - return _("The password contains too few uppercase letters"); - case PWQ_ERROR_MIN_LOWERS: - return _("The password contains too few lowercase letters"); - case PWQ_ERROR_MIN_OTHERS: - return _("The password contains too few non-alphanumeric characters"); - case PWQ_ERROR_MIN_LENGTH: - return _("The password is too short"); - case PWQ_ERROR_ROTATED: - return _("The password is just rotated old one"); - case PWQ_ERROR_MIN_CLASSES: - return _("The password does not contain enough character classes"); - case PWQ_ERROR_MAX_CONSECUTIVE: - return _("The password contains too many same characters consecutively"); - case PWQ_ERROR_EMPTY_PASSWORD: - return _("No password supplied"); - case PWQ_ERROR_CRACKLIB_CHECK: - snprintf(buf, sizeof(buf), _("The password fails the dictionary check - %s"), crack_msg); - return buf; - default: - return _("Unknown error"); - } -} - - /* score a password */ int main(int argc, char *argv[]) { pwquality_settings_t *pwq; int rv; - const char *crack_msg; + void *auxerror; char buf[1024]; size_t len; + setlocale(LC_ALL, ""); + bindtextdomain("libpwquality", "/usr/share/locale"); + textdomain("libpwquality"); + if (argc != 1) { - usage(argv[0]); + usage(basename(argv[0])); exit(3); } if (fgets(buf, sizeof(buf), stdin) == NULL || (len = strlen(buf)) == 0) { - fprintf(stderr, "Error: Could not obtain the password to be scored\n"); + fprintf(stderr, _("Error: %s\n"), _("Could not obtain the password to be scored")); exit(4); } if (buf[len - 1] == '\n') @@ -88,17 +50,20 @@ main(int argc, char *argv[]) pwq = pwquality_default_settings(); if (pwq == NULL) { - fprintf(stderr, _("Error: %s\n"), make_error_message(PWQ_ERROR_MEM_ALLOC, NULL)); + fprintf(stderr, _("Error: %s\n"), pwquality_strerror(NULL, 0, PWQ_ERROR_MEM_ALLOC, NULL)); exit(2); } - pwquality_read_config(pwq, NULL); + if ((rv=pwquality_read_config(pwq, NULL, &auxerror)) != 0) { + fprintf(stderr, _("Error: %s\n"), pwquality_strerror(NULL, 0, rv, auxerror)); + exit(3); + } - rv = pwquality_check(pwq, buf, NULL, &crack_msg); + rv = pwquality_check(pwq, buf, NULL, &auxerror); if (rv < 0) { - fprintf(stderr, _("Password quality check failed: %s\n"), - make_error_message(rv, crack_msg)); + fprintf(stderr, _("Password quality check failed:\n %s\n"), + pwquality_strerror(NULL, 0, rv, auxerror)); exit(1); } diff --git a/src/settings.c b/src/settings.c index 70c0c2e..329e3d1 100644 --- a/src/settings.c +++ b/src/settings.c @@ -98,18 +98,24 @@ set_name_value(pwquality_settings_t *pwq, const char *name, const char *value) /* parse the configuration file (if NULL then the default one) */ int -pwquality_read_config(pwquality_settings_t *pwq, const char *cfgfile) +pwquality_read_config(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror) { FILE *f; char linebuf[PWQSETTINGS_MAX_LINELEN+1]; int rv = 0; + if (auxerror) + *auxerror = NULL; if (cfgfile == NULL) cfgfile = PWQUALITY_DEFAULT_CFGFILE; f = fopen(cfgfile, "r"); - if (f == NULL) + if (f == NULL) { + /* ignore non-existent default config file */ + if (errno == ENOENT && strcmp(cfgfile, PWQUALITY_DEFAULT_CFGFILE) == 0) + return 0; return PWQ_ERROR_CFGFILE_OPEN; + } while (fgets(linebuf, sizeof(linebuf), f) != NULL) { size_t len; @@ -159,6 +165,8 @@ pwquality_read_config(pwquality_settings_t *pwq, const char *cfgfile) } if ((rv=set_name_value(pwq, name, ptr)) != 0) { + if (auxerror) + *auxerror = strdup(name); break; } } @@ -262,41 +270,42 @@ pwquality_set_str_value(pwquality_settings_t *pwq, int setting, return 0; } -/* get value of an integer setting, or -1 if setting unknown */ +/* get value of an integer setting */ int -pwquality_get_int_value(pwquality_settings_t *pwq, int setting) +pwquality_get_int_value(pwquality_settings_t *pwq, int setting, int *value) { switch(setting) { case PWQ_SETTING_DIFF_OK: - return pwq->diff_ok; + *value = pwq->diff_ok; break; case PWQ_SETTING_DIFF_IGNORE: - return pwq->diff_ignore; + *value = pwq->diff_ignore; break; case PWQ_SETTING_MIN_LENGTH: - return pwq->min_length; + *value = pwq->min_length; break; case PWQ_SETTING_DIG_CREDIT: - return pwq->dig_credit; + *value = pwq->dig_credit; break; case PWQ_SETTING_UP_CREDIT: - return pwq->up_credit; + *value = pwq->up_credit; break; case PWQ_SETTING_LOW_CREDIT: - return pwq->low_credit; + *value = pwq->low_credit; break; case PWQ_SETTING_OTH_CREDIT: - return pwq->oth_credit; + *value = pwq->oth_credit; break; case PWQ_SETTING_MIN_CLASS: - return pwq->min_class; + *value = pwq->min_class; break; case PWQ_SETTING_MAX_REPEAT: - return pwq->max_repeat; + *value = pwq->max_repeat; break; default: - return -1; - } + return PWQ_ERROR_NON_INT_SETTING; + } + return 0; } /* get value of a string setting, or NULL if setting unknown */ @@ -306,7 +315,6 @@ pwquality_get_str_value(pwquality_settings_t *pwq, int setting) switch(setting) { case PWQ_SETTING_DICT_PATH: return pwq->dict_path; - break; default: return NULL; } |