aboutsummaryrefslogtreecommitdiff
path: root/src/lib/kadm5/srv
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2010-08-28 22:39:40 +0000
committerGreg Hudson <ghudson@mit.edu>2010-08-28 22:39:40 +0000
commit9f4797d0d86960b597257f0e0e8f4e0325b469a2 (patch)
tree25fee68110c96de19a4a3fd9bc7a62719d914e45 /src/lib/kadm5/srv
parentc9cf5c01e0e1b32325b095b9ae11b0e97d564b5c (diff)
downloadkrb5-9f4797d0d86960b597257f0e0e8f4e0325b469a2.zip
krb5-9f4797d0d86960b597257f0e0e8f4e0325b469a2.tar.gz
krb5-9f4797d0d86960b597257f0e0e8f4e0325b469a2.tar.bz2
Revise the password quality pluggable interface to match the project
page: * Modules receive the policy name but not the policy object. * Enforcement of password policy is out of the interface's scope. * Built-in modules are: empty, dict, hesiod, princ. * The consumer API loader takes care of open/close, so there is only a wrapper function for check. The project page is at: http://k5wiki.kerberos.org/wiki/Projects/Password_quality_pluggable_interface git-svn-id: svn://anonsvn.mit.edu/krb5/branches/plugins2@24266 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/kadm5/srv')
-rw-r--r--src/lib/kadm5/srv/Makefile.in12
-rw-r--r--src/lib/kadm5/srv/pwqual.c63
-rw-r--r--src/lib/kadm5/srv/pwqual_dict.c52
-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.c133
-rw-r--r--src/lib/kadm5/srv/pwqual_princ.c72
-rw-r--r--src/lib/kadm5/srv/server_misc.c105
7 files changed, 366 insertions, 116 deletions
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;
}