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