diff options
Diffstat (limited to 'src/lib/kadm5')
-rw-r--r-- | src/lib/kadm5/server_internal.h | 42 | ||||
-rw-r--r-- | src/lib/kadm5/srv/Makefile.in | 12 | ||||
-rw-r--r-- | src/lib/kadm5/srv/pwqual.c | 63 | ||||
-rw-r--r-- | src/lib/kadm5/srv/pwqual_dict.c | 52 | ||||
-rw-r--r-- | src/lib/kadm5/srv/pwqual_empty.c (renamed from src/lib/kadm5/srv/pwqual_policy.c) | 45 | ||||
-rw-r--r-- | src/lib/kadm5/srv/pwqual_hesiod.c | 133 | ||||
-rw-r--r-- | src/lib/kadm5/srv/pwqual_princ.c | 72 | ||||
-rw-r--r-- | src/lib/kadm5/srv/server_misc.c | 105 |
8 files changed, 388 insertions, 136 deletions
diff --git a/src/lib/kadm5/server_internal.h b/src/lib/kadm5/server_internal.h index ceab3c9..076c18f 100644 --- a/src/lib/kadm5/server_internal.h +++ b/src/lib/kadm5/server_internal.h @@ -158,32 +158,23 @@ osa_free_princ_ent(osa_princ_ent_t val); /*** Password quality plugin consumer interface ***/ -/* Load the available password quality plugins and store the result into - * *handles. Free the result with k5_pwqual_free_handles. */ +/* Load all available password quality plugin modules, bind each module to the + * realm's dictionary file, and store the result into *handles. Free the + * result with k5_pwqual_free_handles. */ krb5_error_code -k5_pwqual_load(krb5_context context, pwqual_handle **handles); +k5_pwqual_load(krb5_context context, pwqual_handle **handles, + const char *dict_file); -/* Release a handle list allocated by k5_pwqual_load. All modules must have - * been closed by the caller. */ -krb5_error_code +/* Release a handle list allocated by k5_pwqual_load. */ +void k5_pwqual_free_handles(krb5_context context, pwqual_handle *handles); -/* Initialize a password quality plugin, possibly using the realm's configured - * dictionary filename. */ -krb5_error_code -k5_pwqual_open(krb5_context context, pwqual_handle handle, - const char *dict_file); - -/* Check a password using a password quality plugin. */ +/* Check a password using a password quality plugin module. */ krb5_error_code k5_pwqual_check(krb5_context context, pwqual_handle handle, - const char *password, kadm5_policy_ent_t policy, + const char *password, const char *policy_name, krb5_principal princ); -/* Release the memory used by a password quality plugin. */ -void -k5_pwqual_close(krb5_context context, pwqual_handle handle); - /*** initvt functions for built-in password quality modules ***/ /* The dict module checks passwords against the realm's dictionary. */ @@ -191,9 +182,20 @@ krb5_error_code pwqual_dict_initvt(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable); -/* The policy module enforces password policy constraints. */ +/* The empty module rejects empty passwords (even with no password policy). */ +krb5_error_code +pwqual_empty_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +/* The hesiod module checks passwords against GECOS fields from Hesiod passwd + * information (only if the tree was built with Hesiod support). */ krb5_error_code -pwqual_policy_initvt(krb5_context context, int maj_ver, int min_ver, +pwqual_hesiod_initvt(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable); +/* The princ module checks passwords against principal components. */ +krb5_error_code +pwqual_princ_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + #endif /* __KADM5_SERVER_INTERNAL_H__ */ diff --git a/src/lib/kadm5/srv/Makefile.in b/src/lib/kadm5/srv/Makefile.in index 6000d73..a513035 100644 --- a/src/lib/kadm5/srv/Makefile.in +++ b/src/lib/kadm5/srv/Makefile.in @@ -29,7 +29,9 @@ RELDIR=kadm5/srv SRCS = $(srcdir)/pwqual.c \ $(srcdir)/pwqual_dict.c \ - $(srcdir)/pwqual_policy.c \ + $(srcdir)/pwqual_empty.c \ + $(srcdir)/pwqual_hesiod.c \ + $(srcdir)/pwqual_princ.c \ $(srcdir)/svr_policy.c \ $(srcdir)/svr_principal.c \ $(srcdir)/server_acl.c \ @@ -42,7 +44,9 @@ SRCS = $(srcdir)/pwqual.c \ OBJS = pwqual.$(OBJEXT) \ pwqual_dict.$(OBJEXT) \ - pwqual_policy.$(OBJECT) \ + pwqual_empty.$(OBJEXT) \ + pwqual_hesiod.$(OBJEXT) \ + pwqual_princ.$(OBJEXT) \ svr_policy.$(OBJEXT) \ svr_principal.$(OBJEXT) \ server_acl.$(OBJEXT) \ @@ -56,7 +60,9 @@ OBJS = pwqual.$(OBJEXT) \ STLIBOBJS = \ pwqual.o \ pwqual_dict.o \ - pwqual_policy.o \ + pwqual_empty.o \ + pwqual_hesiod.o \ + pwqual_princ.o \ svr_policy.o \ svr_principal.o \ server_acl.o \ diff --git a/src/lib/kadm5/srv/pwqual.c b/src/lib/kadm5/srv/pwqual.c index c40f74f..cc92612 100644 --- a/src/lib/kadm5/srv/pwqual.c +++ b/src/lib/kadm5/srv/pwqual.c @@ -25,7 +25,7 @@ * or implied warranty. * * - * Consumer interface for password quality plugins + * Consumer interface for password quality plugins. */ #include "k5-int.h" @@ -38,7 +38,8 @@ struct pwqual_handle_st { }; krb5_error_code -k5_pwqual_load(krb5_context context, pwqual_handle **handles) +k5_pwqual_load(krb5_context context, pwqual_handle **handles, + const char *dict_file) { krb5_error_code ret; krb5_plugin_initvt_fn *modules = NULL, *mod; @@ -55,60 +56,60 @@ k5_pwqual_load(krb5_context context, pwqual_handle **handles) if (list == NULL) goto cleanup; - /* For each module, allocate a handle and initialize its vtable. Skip - * modules which don't successfully initialize. */ + /* For each module, allocate a handle, initialize its vtable, and bind the + * dictionary filename. */ count = 0; for (mod = modules; *mod != NULL; mod++) { handle = k5alloc(sizeof(*handle), &ret); if (handle == NULL) goto cleanup; ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&handle->vt); - if (ret == 0) - list[count++] = handle; - else + if (ret != 0) { /* Failed vtable init is non-fatal. */ free(handle); + continue; + } + handle->data = NULL; + if (handle->vt.open != NULL) { + ret = handle->vt.open(context, dict_file, &handle->data); + if (ret != 0) /* Failed dictionary binding is fatal. */ + goto cleanup; + } + list[count++] = handle; + list[count] = NULL; + handle = NULL; } + list[count] = NULL; *handles = list; list = NULL; cleanup: + free(handle); k5_plugin_free_modules(context, modules); k5_pwqual_free_handles(context, list); return ret; } -krb5_error_code +void k5_pwqual_free_handles(krb5_context context, pwqual_handle *handles) { - /* It's the caller's responsibility to close each handle, so all of the - * module data should be freed by now, leaving only the list itself. */ - free(handles); -} + pwqual_handle *hp, handle; -krb5_error_code -k5_pwqual_open(krb5_context context, pwqual_handle handle, - const char *dict_file) -{ - if (handle->data != NULL) - return EINVAL; - if (handle->vt.open == NULL) - return 0; - return handle->vt.open(context, dict_file, &handle->data); + if (handles == NULL) + return; + for (hp = handles; *hp != NULL; hp++) { + handle = *hp; + if (handle->vt.close != NULL) + handle->vt.close(context, handle->data); + } + free(handles); } krb5_error_code k5_pwqual_check(krb5_context context, pwqual_handle handle, - const char *password, kadm5_policy_ent_t policy, + const char *password, const char *policy_name, krb5_principal princ) { - return handle->vt.check(context, handle->data, password, policy, princ); -} - -void -k5_pwqual_close(krb5_context context, pwqual_handle handle) -{ - if (handle->vt.close) - handle->vt.close(context, handle->data); - handle->data = NULL; + return handle->vt.check(context, handle->data, password, policy_name, + princ); } diff --git a/src/lib/kadm5/srv/pwqual_dict.c b/src/lib/kadm5/srv/pwqual_dict.c index 23b8518..18892a0 100644 --- a/src/lib/kadm5/srv/pwqual_dict.c +++ b/src/lib/kadm5/srv/pwqual_dict.c @@ -1,16 +1,38 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* + * lib/kadm5/srv/pwqual_dict.c + * + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Dictionary initialization and lookup code is (see top-level NOTICE file for + * license): + * * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved * - * $Header$ + * + * Password quality module to look up passwords within the realm dictionary. */ -/* Password quality module to look up paswords within the realm dictionary. */ - -#if !defined(lint) && !defined(__CODECENTER__) -static char *rcsid = "$Header$"; -#endif - #include "k5-platform.h" #include <krb5/pwqual_plugin.h> #include <sys/types.h> @@ -191,15 +213,13 @@ dict_open(krb5_context context, const char *dict_file, * against the dictionary, as well as against principal components. */ static krb5_error_code dict_check(krb5_context context, krb5_pwqual_moddata data, - const char *password, kadm5_policy_ent_t policy, + const char *password, const char *policy_name, krb5_principal princ) { dict_moddata dict = (dict_moddata)data; - int i, n; - char *cp; /* Don't check the dictionary for principals with no password policy. */ - if (policy == NULL) + if (policy_name == NULL) return 0; /* Check against words in the dictionary if we successfully loaded one. */ @@ -208,16 +228,6 @@ dict_check(krb5_context context, krb5_pwqual_moddata data, word_compare) != NULL) return KADM5_PASS_Q_DICT; - /* Check against components of the principal. */ - n = krb5_princ_size(handle->context, princ); - cp = krb5_princ_realm(handle->context, princ)->data; - if (strcasecmp(cp, password) == 0) - return KADM5_PASS_Q_DICT; - for (i = 0; i < n; i++) { - cp = krb5_princ_component(handle->context, princ, i)->data; - if (strcasecmp(cp, password) == 0) - return KADM5_PASS_Q_DICT; - } return 0; } diff --git a/src/lib/kadm5/srv/pwqual_policy.c b/src/lib/kadm5/srv/pwqual_empty.c index 4c7c586..ba25502 100644 --- a/src/lib/kadm5/srv/pwqual_policy.c +++ b/src/lib/kadm5/srv/pwqual_empty.c @@ -1,6 +1,6 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* - * lib/kadm5/srv/pwqual_policy.c + * lib/kadm5/srv/pwqual_empty.c * * Copyright (C) 2010 by the Massachusetts Institute of Technology. * All rights reserved. @@ -25,57 +25,34 @@ * or implied warranty. * * - * Password quality module to enforce password policy + * Password quality module to reject empty passwords. */ #include "k5-platform.h" #include <krb5/pwqual_plugin.h> -#include <kadm5/admin.h> -#include <ctype.h> #include "server_internal.h" -/* Implement the password quality check module. */ static krb5_error_code -policy_check(krb5_context context, krb5_pwqual_moddata data, - const char *password, kadm5_policy_ent_t policy, - krb5_principal princ) +empty_check(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ) { - int nupper = 0, nlower = 0, ndigit = 0, npunct = 0, nspec = 0; - const char *s; - unsigned char c; - - if (policy == NULL) - return (*password == '\0') ? KADM5_PASS_Q_TOOSHORT : 0; - - if(strlen(password) < (size_t)policy->pw_min_length) + /* Unlike other built-in modules, this one operates even for principals + * with no password policy. */ + if (*password == '\0') return KADM5_PASS_Q_TOOSHORT; - s = password; - while ((c = (unsigned char)*s++)) { - if (islower(c)) - nlower = 1; - else if (isupper(c)) - nupper = 1; - else if (isdigit(c)) - ndigit = 1; - else if (ispunct(c)) - npunct = 1; - else - nspec = 1; - } - if ((nupper + nlower + ndigit + npunct + nspec) < policy->pw_min_classes) - return KADM5_PASS_Q_CLASS; return 0; } krb5_error_code -pwqual_policy_initvt(krb5_context context, int maj_ver, int min_ver, - krb5_plugin_vtable vtable) +pwqual_empty_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) { krb5_pwqual_vtable vt; if (maj_ver != 1) return KRB5_PLUGIN_VER_NOTSUPP; vt = (krb5_pwqual_vtable)vtable; - vt->check = policy_check; + vt->check = empty_check; return 0; } diff --git a/src/lib/kadm5/srv/pwqual_hesiod.c b/src/lib/kadm5/srv/pwqual_hesiod.c new file mode 100644 index 0000000..f8862a3 --- /dev/null +++ b/src/lib/kadm5/srv/pwqual_hesiod.c @@ -0,0 +1,133 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * lib/kadm5/srv/pwqual_hesiod.c + * + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Password quality module to check passwords against GECOS fields of Hesiod + * passwd information, if the tree is compiled with Hesiod support. + */ + +#include "k5-platform.h" +#include <krb5/pwqual_plugin.h> +#include "server_internal.h" +#include <ctype.h> + +#ifdef HESIOD +#include <pwd.h> + +static char * +reverse(char *str, char *newstr, size_t newstr_size) +{ + char *p, *q; + size_t i; + + i = strlen(str); + if (i >= newstr_size) + i = newstr_size - 1; + p = str + i - 1; + q = newstr; + q[i] = '\0'; + for (; i > 0; i--) + *q++ = *p--; + + return newstr; +} + +static int +str_check_gecos(char *gecos, const char *pwstr) +{ + char *cp, *ncp, *tcp, revbuf[80]; + + for (cp = gecos; *cp; ) { + /* Skip past punctuation */ + for (; *cp; cp++) + if (isalnum(*cp)) + break; + + /* Skip to the end of the word */ + for (ncp = cp; *ncp; ncp++) { + if (!isalnum(*ncp) && *ncp != '\'') + break; + } + + /* Delimit end of word */ + if (*ncp) + *ncp++ = '\0'; + + /* Check word to see if it's the password */ + if (*cp) { + if (!strcasecmp(pwstr, cp)) + return 1; + tcp = reverse(cp, revbuf, sizeof(revbuf)); + if (!strcasecmp(pwstr, tcp)) + return 1; + cp = ncp; + } else + break; + } + return 0; +} +#endif /* HESIOD */ + +static krb5_error_code +hesiod_check(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ) +{ +#ifdef HESIOD + extern struct passwd *hes_getpwnam(); + struct passwd *ent; + int i, n; + const char *cp; + + /* Don't check for principals with no password policy. */ + if (policy_name == NULL) + return 0; + + n = krb5_princ_size(handle->context, princ); + for (i = 0; i < n; i++) { + cp = krb5_princ_component(handle->context, princ, i)->data; + if (strcasecmp(cp, password) == 0) + return KADM5_PASS_Q_DICT; + ent = hes_getpwnam(cp); + if (ent && ent->pw_gecos && str_check_gecos(ent->pw_gecos, password)) + return KADM5_PASS_Q_DICT; + } +#endif /* HESIOD */ + return 0; +} + +krb5_error_code +pwqual_hesiod_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_pwqual_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_pwqual_vtable)vtable; + vt->check = hesiod_check; + return 0; +} diff --git a/src/lib/kadm5/srv/pwqual_princ.c b/src/lib/kadm5/srv/pwqual_princ.c new file mode 100644 index 0000000..06393a1 --- /dev/null +++ b/src/lib/kadm5/srv/pwqual_princ.c @@ -0,0 +1,72 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * lib/kadm5/srv/pwqual_princ.c + * + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Password quality module to check passwords against principal components. + */ + +#include "k5-platform.h" +#include <krb5/pwqual_plugin.h> +#include "server_internal.h" + +static krb5_error_code +princ_check(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ) +{ + int i, n; + char *cp; + + /* Don't check for principals with no password policy. */ + if (policy_name == NULL) + return 0; + + /* Check against components of the principal. */ + n = krb5_princ_size(handle->context, princ); + cp = krb5_princ_realm(handle->context, princ)->data; + if (strcasecmp(cp, password) == 0) + return KADM5_PASS_Q_DICT; + for (i = 0; i < n; i++) { + cp = krb5_princ_component(handle->context, princ, i)->data; + if (strcasecmp(cp, password) == 0) + return KADM5_PASS_Q_DICT; + } + + return 0; +} + +krb5_error_code +pwqual_princ_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_pwqual_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_pwqual_vtable)vtable; + vt->check = princ_check; + return 0; +} diff --git a/src/lib/kadm5/srv/server_misc.c b/src/lib/kadm5/srv/server_misc.c index 9bea86f..93369f0 100644 --- a/src/lib/kadm5/srv/server_misc.c +++ b/src/lib/kadm5/srv/server_misc.c @@ -1,14 +1,34 @@ /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * check_against_policy code is originally (see top-level NOTICE file for + * license): + * * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved * - * $Header$ */ -#if !defined(lint) && !defined(__CODECENTER__) -static char *rcsid = "$Header$"; -#endif - #include "k5-int.h" #include <kdb.h> #include <ctype.h> @@ -37,51 +57,86 @@ kadm5_ret_t init_pwqual(kadm5_server_handle_t handle) { krb5_error_code ret; - pwqual_handle *list, *h; + pwqual_handle *list; const char *dict_file = NULL; + /* Register the built-in password quality modules. */ ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL, "dict", pwqual_dict_initvt); if (ret != 0) return ret; - ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL, - "policy", pwqual_policy_initvt); + "empty", pwqual_empty_initvt); if (ret != 0) return ret; - - ret = k5_pwqual_load(handle->context, &list); + ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL, + "hesiod", pwqual_hesiod_initvt); + if (ret != 0) + return ret; + ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL, + "princ", pwqual_princ_initvt); if (ret != 0) return ret; + /* Load all available password quality modules. */ if (handle->params.mask & KADM5_CONFIG_DICT_FILE) dict_file = handle->params.dict_file; - - for (h = list; *h != NULL; h++) { - ret = k5_pwqual_open(handle->context, *h, dict_file); - if (ret != 0) { - /* Close any previously opened modules and error out. */ - for (; h > list; h--) - k5_pwqual_close(handle->context, *(h - 1)); - k5_pwqual_free_handles(handle->context, list); - return ret; - } - } + ret = k5_pwqual_load(handle->context, &list, dict_file); + if (ret != 0) + return ret; handle->qual_handles = list; return 0; } -/* Check a password against all available password quality plugin modules. */ +/* Check that a password meets the quality constraints given in pol. */ +static kadm5_ret_t +check_against_policy(kadm5_server_handle_t handle, const char *password, + kadm5_policy_ent_t pol) +{ + int hasupper = 0, haslower = 0, hasdigit = 0, haspunct = 0, hasspec = 0; + int c, nclasses; + + /* Check against the policy's minimum length. */ + if (strlen(password) < (size_t)pol->pw_min_length) + return KADM5_PASS_Q_TOOSHORT; + + /* Check against the policy's minimum number of character classes. */ + while ((c = (unsigned char)*password++) != '\0') { + if (islower(c)) + haslower = 1; + else if (isupper(c)) + hasupper = 1; + else if (isdigit(c)) + hasdigit = 1; + else if (ispunct(c)) + haspunct = 1; + else + hasspec = 1; + } + nclasses = hasupper + haslower + hasdigit + haspunct + hasspec; + if (nclasses < pol->pw_min_classes) + return KADM5_PASS_Q_CLASS; + return KADM5_OK; +} + +/* Check a password against all available password quality plugin modules + * and against policy. */ kadm5_ret_t passwd_check(kadm5_server_handle_t handle, const char *password, kadm5_policy_ent_t policy, krb5_principal princ) { krb5_error_code ret; pwqual_handle *h; + const char *polname = (policy == NULL) ? NULL : policy->policy; + if (policy != NULL) { + ret = check_against_policy(handle, password, policy); + if (ret != 0) + return ret; + } for (h = handle->qual_handles; *h != NULL; h++) { - ret = k5_pwqual_check(handle->context, *h, password, policy, princ); + ret = k5_pwqual_check(handle->context, *h, password, polname, princ); if (ret != 0) return ret; } @@ -91,10 +146,6 @@ passwd_check(kadm5_server_handle_t handle, const char *password, void destroy_pwqual(kadm5_server_handle_t handle) { - pwqual_handle *h; - - for (h = handle->qual_handles; *h != NULL; h++) - k5_pwqual_close(handle->context, *h); k5_pwqual_free_handles(handle->context, handle->qual_handles); handle->qual_handles = NULL; } |