2 * Copyright (c) 1997-2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "kadm5_locl.h"
39 get_default(kadm5_server_context
*context
, krb5_principal princ
,
40 kadm5_principal_ent_t def
)
43 krb5_principal def_principal
;
44 krb5_const_realm realm
= krb5_principal_get_realm(context
->context
, princ
);
46 ret
= krb5_make_principal(context
->context
, &def_principal
,
47 realm
, "default", NULL
);
50 ret
= kadm5_s_get_principal(context
, def_principal
, def
,
51 KADM5_PRINCIPAL_NORMAL_MASK
);
52 krb5_free_principal (context
->context
, def_principal
);
55 /* Copy defaults from kadmin/init.c */
56 memset(def
, 0, sizeof(*def
));
57 def
->max_life
= 24 * 60 * 60;
58 def
->max_renewable_life
= 7 * def
->max_life
;
59 def
->attributes
= KRB5_KDB_DISALLOW_ALL_TIX
;
65 create_principal(kadm5_server_context
*context
,
66 kadm5_principal_ent_t princ
,
69 uint32_t required_mask
,
70 uint32_t forbidden_mask
)
73 kadm5_principal_ent_rec defrec
, *defent
;
76 memset(ent
, 0, sizeof(*ent
));
77 if((mask
& required_mask
) != required_mask
)
78 return KADM5_BAD_MASK
;
79 if((mask
& forbidden_mask
))
80 return KADM5_BAD_MASK
;
81 if((mask
& KADM5_POLICY
) && strcmp(princ
->policy
, "default"))
82 /* XXX no real policies for now */
83 return KADM5_UNK_POLICY
;
84 ret
= krb5_copy_principal(context
->context
, princ
->principal
,
90 ret
= get_default(context
, princ
->principal
, defent
);
95 def_mask
= KADM5_ATTRIBUTES
| KADM5_MAX_LIFE
| KADM5_MAX_RLIFE
;
98 ret
= _kadm5_setup_entry(context
,
103 kadm5_free_principal_ent(context
, defent
);
107 ent
->created_by
.time
= time(NULL
);
109 return krb5_copy_principal(context
->context
, context
->caller
,
110 &ent
->created_by
.principal
);
113 struct create_principal_hook_ctx
{
114 kadm5_server_context
*context
;
115 enum kadm5_hook_stage stage
;
116 krb5_error_code code
;
117 kadm5_principal_ent_t princ
;
119 const char *password
;
122 static krb5_error_code KRB5_LIB_CALL
123 create_principal_hook_cb(krb5_context context
,
129 const struct kadm5_hook_ftable
*ftable
= hook
;
130 struct create_principal_hook_ctx
*ctx
= userctx
;
132 ret
= ftable
->create(context
, hookctx
,
133 ctx
->stage
, ctx
->code
, ctx
->princ
,
134 ctx
->mask
, ctx
->password
);
135 if (ret
!= 0 && ret
!= KRB5_PLUGIN_NO_HANDLE
)
136 _kadm5_s_set_hook_error_message(ctx
->context
, ret
, "create",
139 /* only pre-commit plugins can abort */
140 if (ret
== 0 || ctx
->stage
== KADM5_HOOK_STAGE_POSTCOMMIT
)
141 ret
= KRB5_PLUGIN_NO_HANDLE
;
147 create_principal_hook(kadm5_server_context
*context
,
148 enum kadm5_hook_stage stage
,
149 krb5_error_code code
,
150 kadm5_principal_ent_t princ
,
152 const char *password
)
155 struct create_principal_hook_ctx ctx
;
157 ctx
.context
= context
;
162 ctx
.password
= password
;
164 ret
= _krb5_plugin_run_f(context
->context
, &kadm5_hook_plugin_data
,
165 0, &ctx
, create_principal_hook_cb
);
166 if (ret
== KRB5_PLUGIN_NO_HANDLE
)
173 kadm5_s_create_principal_with_key(void *server_handle
,
174 kadm5_principal_ent_t princ
,
179 kadm5_server_context
*context
= server_handle
;
181 if ((mask
& KADM5_KVNO
) == 0) {
182 /* create_principal() through _kadm5_setup_entry(), will need this */
187 ret
= create_principal_hook(context
, KADM5_HOOK_STAGE_PRECOMMIT
,
188 0, princ
, mask
, NULL
);
192 ret
= create_principal(context
, princ
, mask
, &ent
,
193 KADM5_PRINCIPAL
| KADM5_KEY_DATA
,
194 KADM5_LAST_PWD_CHANGE
| KADM5_MOD_TIME
195 | KADM5_MOD_NAME
| KADM5_MKVNO
196 | KADM5_AUX_ATTRIBUTES
197 | KADM5_POLICY_CLR
| KADM5_LAST_SUCCESS
198 | KADM5_LAST_FAILED
| KADM5_FAIL_AUTH_COUNT
);
202 if (!context
->keep_open
) {
203 ret
= context
->db
->hdb_open(context
->context
, context
->db
, O_RDWR
, 0);
205 hdb_free_entry(context
->context
, context
->db
, &ent
);
210 ret
= kadm5_log_init(context
);
214 ret
= hdb_seal_keys(context
->context
, context
->db
, &ent
);
219 * This logs the change for iprop and writes to the HDB.
221 * Creation of would-be virtual principals w/o the materialize flag will be
222 * rejected in kadm5_log_create().
224 ret
= kadm5_log_create(context
, &ent
);
226 (void) create_principal_hook(context
, KADM5_HOOK_STAGE_POSTCOMMIT
,
227 ret
, princ
, mask
, NULL
);
230 (void) kadm5_log_end(context
);
232 if (!context
->keep_open
) {
234 ret2
= context
->db
->hdb_close(context
->context
, context
->db
);
235 if (ret
== 0 && ret2
!= 0)
238 hdb_free_entry(context
->context
, context
->db
, &ent
);
239 return _kadm5_error_code(ret
);
244 kadm5_s_create_principal(void *server_handle
,
245 kadm5_principal_ent_t princ
,
248 krb5_key_salt_tuple
*ks_tuple
,
249 const char *password
)
253 kadm5_server_context
*context
= server_handle
;
256 if ((mask
& KADM5_ATTRIBUTES
) &&
257 (princ
->attributes
& (KRB5_KDB_VIRTUAL_KEYS
| KRB5_KDB_VIRTUAL
)) &&
258 !(princ
->attributes
& KRB5_KDB_MATERIALIZE
)) {
259 return _kadm5_error_code(KADM5_DUP
); /* XXX More like EINVAL */
261 if ((mask
& KADM5_ATTRIBUTES
) &&
262 (princ
->attributes
& KRB5_KDB_VIRTUAL_KEYS
) &&
263 (princ
->attributes
& KRB5_KDB_VIRTUAL
)) {
264 return _kadm5_error_code(KADM5_DUP
); /* XXX More like EINVAL */
267 if ((mask
& KADM5_ATTRIBUTES
) &&
268 (princ
->attributes
& KRB5_KDB_VIRTUAL
) &&
269 (princ
->attributes
& KRB5_KDB_MATERIALIZE
))
270 princ
->attributes
&= ~(KRB5_KDB_MATERIALIZE
| KRB5_KDB_VIRTUAL
);
272 if (password
[0] == '\0' && (mask
& KADM5_KEY_DATA
) && princ
->n_key_data
&&
273 !kadm5_all_keys_are_bogus(princ
->n_key_data
, princ
->key_data
))
276 if (use_pw
&& _kadm5_enforce_pwqual_on_admin_set_p(context
)) {
278 const char *pwd_reason
;
280 pwd_data
.data
= rk_UNCONST(password
);
281 pwd_data
.length
= strlen(password
);
283 pwd_reason
= kadm5_check_password_quality(context
->context
,
284 princ
->principal
, &pwd_data
);
285 if (pwd_reason
!= NULL
) {
286 krb5_set_error_message(context
->context
, KADM5_PASS_Q_DICT
, "%s", pwd_reason
);
287 return KADM5_PASS_Q_DICT
;
291 if ((mask
& KADM5_KVNO
) == 0) {
292 /* create_principal() through _kadm5_setup_entry(), will need this */
297 ret
= create_principal_hook(context
, KADM5_HOOK_STAGE_PRECOMMIT
,
298 0, princ
, mask
, password
);
303 ret
= create_principal(context
, princ
, mask
, &ent
,
305 KADM5_LAST_PWD_CHANGE
| KADM5_MOD_TIME
306 | KADM5_MOD_NAME
| KADM5_MKVNO
307 | KADM5_AUX_ATTRIBUTES
| KADM5_KEY_DATA
308 | KADM5_POLICY_CLR
| KADM5_LAST_SUCCESS
309 | KADM5_LAST_FAILED
| KADM5_FAIL_AUTH_COUNT
);
311 ret
= create_principal(context
, princ
, mask
, &ent
,
312 KADM5_PRINCIPAL
| KADM5_KEY_DATA
,
313 KADM5_LAST_PWD_CHANGE
| KADM5_MOD_TIME
314 | KADM5_MOD_NAME
| KADM5_MKVNO
315 | KADM5_AUX_ATTRIBUTES
316 | KADM5_POLICY_CLR
| KADM5_LAST_SUCCESS
317 | KADM5_LAST_FAILED
| KADM5_FAIL_AUTH_COUNT
);
321 if (!context
->keep_open
) {
322 ret
= context
->db
->hdb_open(context
->context
, context
->db
, O_RDWR
, 0);
324 hdb_free_entry(context
->context
, context
->db
, &ent
);
329 ret
= kadm5_log_init(context
);
333 free_Keys(&ent
.keys
);
336 ret
= _kadm5_set_keys(context
, &ent
, n_ks_tuple
, ks_tuple
, password
);
341 ret
= hdb_seal_keys(context
->context
, context
->db
, &ent
);
345 /* This logs the change for iprop and writes to the HDB */
346 ret
= kadm5_log_create(context
, &ent
);
348 (void) create_principal_hook(context
, KADM5_HOOK_STAGE_POSTCOMMIT
,
349 ret
, princ
, mask
, password
);
352 (void) kadm5_log_end(context
);
354 if (!context
->keep_open
) {
356 ret2
= context
->db
->hdb_close(context
->context
, context
->db
);
357 if (ret
== 0 && ret2
!= 0)
360 hdb_free_entry(context
->context
, context
->db
, &ent
);
361 return _kadm5_error_code(ret
);