xref: /freebsd/crypto/krb5/src/lib/kadm5/srv/server_misc.c (revision b670c9bafc0e31c7609969bf374b2e80bdc00211)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Copyright (C) 2010 by the Massachusetts Institute of Technology.
4  * All rights reserved.
5  *
6  * Export of this software from the United States of America may
7  *   require a specific license from the United States Government.
8  *   It is the responsibility of any person or organization contemplating
9  *   export to obtain such a license before exporting.
10  *
11  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12  * distribute this software and its documentation for any purpose and
13  * without fee is hereby granted, provided that the above copyright
14  * notice appear in all copies and that both that copyright notice and
15  * this permission notice appear in supporting documentation, and that
16  * the name of M.I.T. not be used in advertising or publicity pertaining
17  * to distribution of the software without specific, written prior
18  * permission.  Furthermore if you modify this software you must label
19  * your software as modified software and not distribute it in such a
20  * fashion that it might be confused with the original M.I.T. software.
21  * M.I.T. makes no representations about the suitability of
22  * this software for any purpose.  It is provided "as is" without express
23  * or implied warranty.
24  */
25 /*
26  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
27  */
28 
29 #include    "k5-int.h"
30 #include    <kdb.h>
31 #include    <ctype.h>
32 #include    <pwd.h>
33 #include    <syslog.h>
34 #include    "server_internal.h"
35 #include    <adm_proto.h>
36 
37 kadm5_ret_t
38 init_pwqual(kadm5_server_handle_t handle)
39 {
40     krb5_error_code ret;
41     pwqual_handle *list;
42     const char *dict_file = NULL;
43 
44     /* Register the built-in password quality modules. */
45     ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL,
46                              "dict", pwqual_dict_initvt);
47     if (ret != 0)
48         return ret;
49     ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL,
50                              "empty", pwqual_empty_initvt);
51     if (ret != 0)
52         return ret;
53     ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL,
54                              "hesiod", pwqual_hesiod_initvt);
55     if (ret != 0)
56         return ret;
57     ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL,
58                              "princ", pwqual_princ_initvt);
59     if (ret != 0)
60         return ret;
61 
62     /* Load all available password quality modules. */
63     if (handle->params.mask & KADM5_CONFIG_DICT_FILE)
64         dict_file = handle->params.dict_file;
65     ret = k5_pwqual_load(handle->context, dict_file, &list);
66     if (ret != 0)
67         return ret;
68 
69     handle->qual_handles = list;
70     return 0;
71 }
72 
73 /* Check that a password meets the quality constraints given in pol. */
74 static kadm5_ret_t
75 check_against_policy(kadm5_server_handle_t handle, const char *password,
76                      kadm5_policy_ent_t pol)
77 {
78     int hasupper = 0, haslower = 0, hasdigit = 0, haspunct = 0, hasspec = 0;
79     int c, nclasses;
80 
81     /* Check against the policy's minimum length. */
82     if (strlen(password) < (size_t)pol->pw_min_length)
83         return KADM5_PASS_Q_TOOSHORT;
84 
85     /* Check against the policy's minimum number of character classes. */
86     while ((c = (unsigned char)*password++) != '\0') {
87         if (islower(c))
88             haslower = 1;
89         else if (isupper(c))
90             hasupper = 1;
91         else if (isdigit(c))
92             hasdigit = 1;
93         else if (ispunct(c))
94             haspunct = 1;
95         else
96             hasspec = 1;
97     }
98     nclasses = hasupper + haslower + hasdigit + haspunct + hasspec;
99     if (nclasses < pol->pw_min_classes)
100         return KADM5_PASS_Q_CLASS;
101     return KADM5_OK;
102 }
103 
104 /* Check a password against all available password quality plugin modules
105  * and against policy. */
106 kadm5_ret_t
107 passwd_check(kadm5_server_handle_t handle, const char *password,
108              kadm5_policy_ent_t policy, krb5_principal princ)
109 {
110     krb5_error_code ret;
111     pwqual_handle *h;
112     const char *polname = (policy == NULL) ? NULL : policy->policy;
113 
114     if (policy != NULL) {
115         ret = check_against_policy(handle, password, policy);
116         if (ret != 0)
117             return ret;
118     }
119     for (h = handle->qual_handles; *h != NULL; h++) {
120         ret = k5_pwqual_check(handle->context, *h, password, polname, princ);
121         if (ret != 0) {
122             const char *e = krb5_get_error_message(handle->context, ret);
123             const char *modname = k5_pwqual_name(handle->context, *h);
124             char *princname;
125             if (krb5_unparse_name(handle->context, princ, &princname) != 0)
126                 princname = NULL;
127             krb5_klog_syslog(LOG_ERR,
128                              _("password quality module %s rejected password "
129                                "for %s: %s"), modname,
130                              princname ? princname : "(can't unparse)", e);
131             krb5_free_error_message(handle->context, e);
132             free(princname);
133             return ret;
134         }
135     }
136     return 0;
137 }
138 
139 void
140 destroy_pwqual(kadm5_server_handle_t handle)
141 {
142     k5_pwqual_free_handles(handle->context, handle->qual_handles);
143     handle->qual_handles = NULL;
144 }
145 
146 kadm5_ret_t
147 kadm5_get_privs(void *server_handle, long *privs)
148 {
149     CHECK_HANDLE(server_handle);
150 
151     /* this is impossible to do with the current interface.  For now,
152        return all privs, which will confuse some clients, but not
153        deny any access to users of "smart" clients which try to cache */
154 
155     *privs = ~0;
156 
157     return KADM5_OK;
158 }
159