xref: /freebsd/crypto/krb5/src/kadmin/server/misc.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
4*7f2fe78bSCy Schubert  *
5*7f2fe78bSCy Schubert  */
6*7f2fe78bSCy Schubert 
7*7f2fe78bSCy Schubert #include    <k5-int.h>
8*7f2fe78bSCy Schubert #include    <kdb.h>
9*7f2fe78bSCy Schubert #include    <kadm5/server_internal.h>
10*7f2fe78bSCy Schubert #include    "misc.h"
11*7f2fe78bSCy Schubert #include    "auth.h"
12*7f2fe78bSCy Schubert #include    "net-server.h"
13*7f2fe78bSCy Schubert kadm5_ret_t
schpw_util_wrapper(void * server_handle,krb5_principal client,krb5_principal target,krb5_boolean initial_flag,char * new_pw,char ** ret_pw,char * msg_ret,unsigned int msg_len)14*7f2fe78bSCy Schubert schpw_util_wrapper(void *server_handle,
15*7f2fe78bSCy Schubert                    krb5_principal client,
16*7f2fe78bSCy Schubert                    krb5_principal target,
17*7f2fe78bSCy Schubert                    krb5_boolean initial_flag,
18*7f2fe78bSCy Schubert                    char *new_pw, char **ret_pw,
19*7f2fe78bSCy Schubert                    char *msg_ret, unsigned int msg_len)
20*7f2fe78bSCy Schubert {
21*7f2fe78bSCy Schubert     kadm5_ret_t                 ret;
22*7f2fe78bSCy Schubert     kadm5_server_handle_t       handle = server_handle;
23*7f2fe78bSCy Schubert 
24*7f2fe78bSCy Schubert     /*
25*7f2fe78bSCy Schubert      * If no target is explicitly provided, then the target principal
26*7f2fe78bSCy Schubert      * is the client principal.
27*7f2fe78bSCy Schubert      */
28*7f2fe78bSCy Schubert     if (target == NULL)
29*7f2fe78bSCy Schubert         target = client;
30*7f2fe78bSCy Schubert 
31*7f2fe78bSCy Schubert     /* If the client is changing its own password, require it to use an initial
32*7f2fe78bSCy Schubert      * ticket, and enforce the policy min_life. */
33*7f2fe78bSCy Schubert     if (krb5_principal_compare(handle->context, client, target)) {
34*7f2fe78bSCy Schubert         if (!initial_flag) {
35*7f2fe78bSCy Schubert             strlcpy(msg_ret, "Ticket must be derived from a password",
36*7f2fe78bSCy Schubert                     msg_len);
37*7f2fe78bSCy Schubert             return KADM5_AUTH_INITIAL;
38*7f2fe78bSCy Schubert         }
39*7f2fe78bSCy Schubert 
40*7f2fe78bSCy Schubert         ret = check_min_life(server_handle, target, msg_ret, msg_len);
41*7f2fe78bSCy Schubert         if (ret != 0)
42*7f2fe78bSCy Schubert             return ret;
43*7f2fe78bSCy Schubert     }
44*7f2fe78bSCy Schubert 
45*7f2fe78bSCy Schubert     if (auth(handle->context, OP_CPW, client, target,
46*7f2fe78bSCy Schubert              NULL, NULL, NULL, NULL, 0)) {
47*7f2fe78bSCy Schubert         ret = kadm5_chpass_principal_util(server_handle,
48*7f2fe78bSCy Schubert                                           target,
49*7f2fe78bSCy Schubert                                           new_pw, ret_pw,
50*7f2fe78bSCy Schubert                                           msg_ret, msg_len);
51*7f2fe78bSCy Schubert     } else {
52*7f2fe78bSCy Schubert         ret = KADM5_AUTH_CHANGEPW;
53*7f2fe78bSCy Schubert         strlcpy(msg_ret, "Unauthorized request", msg_len);
54*7f2fe78bSCy Schubert     }
55*7f2fe78bSCy Schubert 
56*7f2fe78bSCy Schubert     return ret;
57*7f2fe78bSCy Schubert }
58*7f2fe78bSCy Schubert 
59*7f2fe78bSCy Schubert kadm5_ret_t
check_min_life(void * server_handle,krb5_principal principal,char * msg_ret,unsigned int msg_len)60*7f2fe78bSCy Schubert check_min_life(void *server_handle, krb5_principal principal,
61*7f2fe78bSCy Schubert                char *msg_ret, unsigned int msg_len)
62*7f2fe78bSCy Schubert {
63*7f2fe78bSCy Schubert     krb5_timestamp              now;
64*7f2fe78bSCy Schubert     kadm5_ret_t                 ret;
65*7f2fe78bSCy Schubert     kadm5_policy_ent_rec        pol;
66*7f2fe78bSCy Schubert     kadm5_principal_ent_rec     princ;
67*7f2fe78bSCy Schubert     kadm5_server_handle_t       handle = server_handle;
68*7f2fe78bSCy Schubert 
69*7f2fe78bSCy Schubert     if (msg_ret != NULL)
70*7f2fe78bSCy Schubert         *msg_ret = '\0';
71*7f2fe78bSCy Schubert 
72*7f2fe78bSCy Schubert     ret = krb5_timeofday(handle->context, &now);
73*7f2fe78bSCy Schubert     if (ret)
74*7f2fe78bSCy Schubert         return ret;
75*7f2fe78bSCy Schubert 
76*7f2fe78bSCy Schubert     ret = kadm5_get_principal(handle->lhandle, principal,
77*7f2fe78bSCy Schubert                               &princ, KADM5_PRINCIPAL_NORMAL_MASK);
78*7f2fe78bSCy Schubert     if(ret)
79*7f2fe78bSCy Schubert         return ret;
80*7f2fe78bSCy Schubert     if(princ.aux_attributes & KADM5_POLICY) {
81*7f2fe78bSCy Schubert         /* Look up the policy.  If it doesn't exist, treat this principal as if
82*7f2fe78bSCy Schubert          * it had no policy. */
83*7f2fe78bSCy Schubert         if((ret=kadm5_get_policy(handle->lhandle,
84*7f2fe78bSCy Schubert                                  princ.policy, &pol)) != KADM5_OK) {
85*7f2fe78bSCy Schubert             (void) kadm5_free_principal_ent(handle->lhandle, &princ);
86*7f2fe78bSCy Schubert             return (ret == KADM5_UNK_POLICY) ? 0 : ret;
87*7f2fe78bSCy Schubert         }
88*7f2fe78bSCy Schubert         if(ts_delta(now, princ.last_pwd_change) < pol.pw_min_life &&
89*7f2fe78bSCy Schubert            !(princ.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
90*7f2fe78bSCy Schubert             if (msg_ret != NULL) {
91*7f2fe78bSCy Schubert                 time_t until;
92*7f2fe78bSCy Schubert                 char *time_string, *ptr;
93*7f2fe78bSCy Schubert                 const char *errstr;
94*7f2fe78bSCy Schubert 
95*7f2fe78bSCy Schubert                 until = princ.last_pwd_change + pol.pw_min_life;
96*7f2fe78bSCy Schubert 
97*7f2fe78bSCy Schubert                 time_string = ctime(&until);
98*7f2fe78bSCy Schubert                 if (time_string == NULL)
99*7f2fe78bSCy Schubert                     time_string = "(error)";
100*7f2fe78bSCy Schubert                 errstr = error_message(CHPASS_UTIL_PASSWORD_TOO_SOON);
101*7f2fe78bSCy Schubert 
102*7f2fe78bSCy Schubert                 if (strlen(errstr) + strlen(time_string) < msg_len) {
103*7f2fe78bSCy Schubert                     if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')
104*7f2fe78bSCy Schubert                         *ptr = '\0';
105*7f2fe78bSCy Schubert                     snprintf(msg_ret, msg_len, errstr, time_string);
106*7f2fe78bSCy Schubert                 }
107*7f2fe78bSCy Schubert             }
108*7f2fe78bSCy Schubert 
109*7f2fe78bSCy Schubert             (void) kadm5_free_policy_ent(handle->lhandle, &pol);
110*7f2fe78bSCy Schubert             (void) kadm5_free_principal_ent(handle->lhandle, &princ);
111*7f2fe78bSCy Schubert             return KADM5_PASS_TOOSOON;
112*7f2fe78bSCy Schubert         }
113*7f2fe78bSCy Schubert 
114*7f2fe78bSCy Schubert         ret = kadm5_free_policy_ent(handle->lhandle, &pol);
115*7f2fe78bSCy Schubert         if (ret) {
116*7f2fe78bSCy Schubert             (void) kadm5_free_principal_ent(handle->lhandle, &princ);
117*7f2fe78bSCy Schubert             return ret;
118*7f2fe78bSCy Schubert         }
119*7f2fe78bSCy Schubert     }
120*7f2fe78bSCy Schubert 
121*7f2fe78bSCy Schubert     return kadm5_free_principal_ent(handle->lhandle, &princ);
122*7f2fe78bSCy Schubert }
123*7f2fe78bSCy Schubert 
124*7f2fe78bSCy Schubert #define MAXPRINCLEN 125
125*7f2fe78bSCy Schubert 
126*7f2fe78bSCy Schubert void
trunc_name(size_t * len,char ** dots)127*7f2fe78bSCy Schubert trunc_name(size_t *len, char **dots)
128*7f2fe78bSCy Schubert {
129*7f2fe78bSCy Schubert     *dots = *len > MAXPRINCLEN ? "..." : "";
130*7f2fe78bSCy Schubert     *len = *len > MAXPRINCLEN ? MAXPRINCLEN : *len;
131*7f2fe78bSCy Schubert }
132*7f2fe78bSCy Schubert 
133*7f2fe78bSCy Schubert krb5_error_code
make_toolong_error(void * handle,krb5_data ** out)134*7f2fe78bSCy Schubert make_toolong_error (void *handle, krb5_data **out)
135*7f2fe78bSCy Schubert {
136*7f2fe78bSCy Schubert     krb5_error errpkt;
137*7f2fe78bSCy Schubert     krb5_error_code retval;
138*7f2fe78bSCy Schubert     krb5_data *scratch;
139*7f2fe78bSCy Schubert     kadm5_server_handle_t server_handle = *(void **)handle;
140*7f2fe78bSCy Schubert 
141*7f2fe78bSCy Schubert     retval = krb5_us_timeofday(server_handle->context, &errpkt.stime, &errpkt.susec);
142*7f2fe78bSCy Schubert     if (retval)
143*7f2fe78bSCy Schubert         return retval;
144*7f2fe78bSCy Schubert     errpkt.error = KRB_ERR_FIELD_TOOLONG;
145*7f2fe78bSCy Schubert     retval = krb5_build_principal(server_handle->context, &errpkt.server,
146*7f2fe78bSCy Schubert                                   strlen(server_handle->params.realm),
147*7f2fe78bSCy Schubert                                   server_handle->params.realm,
148*7f2fe78bSCy Schubert                                   "kadmin", "changepw", NULL);
149*7f2fe78bSCy Schubert     if (retval)
150*7f2fe78bSCy Schubert         return retval;
151*7f2fe78bSCy Schubert     errpkt.client = NULL;
152*7f2fe78bSCy Schubert     errpkt.cusec = 0;
153*7f2fe78bSCy Schubert     errpkt.ctime = 0;
154*7f2fe78bSCy Schubert     errpkt.text.length = 0;
155*7f2fe78bSCy Schubert     errpkt.text.data = 0;
156*7f2fe78bSCy Schubert     errpkt.e_data.length = 0;
157*7f2fe78bSCy Schubert     errpkt.e_data.data = 0;
158*7f2fe78bSCy Schubert     scratch = malloc(sizeof(*scratch));
159*7f2fe78bSCy Schubert     if (scratch == NULL)
160*7f2fe78bSCy Schubert         return ENOMEM;
161*7f2fe78bSCy Schubert     retval = krb5_mk_error(server_handle->context, &errpkt, scratch);
162*7f2fe78bSCy Schubert     if (retval) {
163*7f2fe78bSCy Schubert         free(scratch);
164*7f2fe78bSCy Schubert         return retval;
165*7f2fe78bSCy Schubert     }
166*7f2fe78bSCy Schubert 
167*7f2fe78bSCy Schubert     *out = scratch;
168*7f2fe78bSCy Schubert     return 0;
169*7f2fe78bSCy Schubert }
170*7f2fe78bSCy Schubert 
get_context(void * handle)171*7f2fe78bSCy Schubert krb5_context get_context(void *handle)
172*7f2fe78bSCy Schubert {
173*7f2fe78bSCy Schubert     kadm5_server_handle_t server_handle = *(void **)handle;
174*7f2fe78bSCy Schubert     return server_handle->context;
175*7f2fe78bSCy Schubert }
176