2 * Copyright (c) 1997-2001, 2003, 2005-2006 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"
36 struct setkey_principal_hook_ctx {
37 kadm5_server_context *context;
38 enum kadm5_hook_stage stage;
40 krb5_const_principal princ;
43 krb5_key_salt_tuple *ks_tuple;
48 static krb5_error_code KRB5_LIB_CALL
49 setkey_principal_hook_cb(krb5_context context,
55 const struct kadm5_hook_ftable *ftable = hook;
56 struct setkey_principal_hook_ctx *ctx = userctx;
58 ret = ftable->set_keys(context, hookctx,
59 ctx->stage, ctx->code,
60 ctx->princ, ctx->flags,
61 ctx->n_ks_tuple, ctx->ks_tuple,
62 ctx->n_keys, ctx->keys);
63 if (ret != 0 && ret != KRB5_PLUGIN_NO_HANDLE)
64 _kadm5_s_set_hook_error_message(ctx->context, ret, "setkey",
67 /* only pre-commit plugins can abort */
68 if (ret == 0 || ctx->stage == KADM5_HOOK_STAGE_POSTCOMMIT)
69 ret = KRB5_PLUGIN_NO_HANDLE;
75 setkey_principal_hook(kadm5_server_context *context,
76 enum kadm5_hook_stage stage,
78 krb5_const_principal princ,
81 krb5_key_salt_tuple *ks_tuple,
83 krb5_keyblock *keyblocks)
86 struct setkey_principal_hook_ctx ctx;
88 ctx.context = context;
93 ctx.n_ks_tuple = n_ks_tuple;
94 ctx.ks_tuple = ks_tuple;
98 ret = _krb5_plugin_run_f(context->context, &kadm5_hook_plugin_data,
99 0, &ctx, setkey_principal_hook_cb);
100 if (ret == KRB5_PLUGIN_NO_HANDLE)
107 * Server-side function to set new keys for a principal.
110 kadm5_s_setkey_principal_3(void *server_handle,
111 krb5_principal princ,
112 krb5_boolean keepold,
114 krb5_key_salt_tuple *ks_tuple,
115 krb5_keyblock *keyblocks, int n_keys)
117 kadm5_server_context *context = server_handle;
122 memset(&ent, 0, sizeof(ent));
123 if (!context->keep_open)
124 ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
128 ret = kadm5_log_init(context);
130 if (!context->keep_open)
131 context->db->hdb_close(context->context, context->db);
135 /* NOTE: We do not use hdb_fetch_kvno() here (maybe we should?) */
136 ret = context->db->hdb_fetch_kvno(context->context, context->db, princ,
137 HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA,
140 (void) kadm5_log_end(context);
141 if (!context->keep_open)
142 context->db->hdb_close(context->context, context->db);
146 ret = setkey_principal_hook(context, KADM5_HOOK_STAGE_PRECOMMIT, 0,
147 princ, keepold ? KADM5_HOOK_FLAG_KEEPOLD : 0,
148 n_ks_tuple, ks_tuple, n_keys, keyblocks);
150 (void) kadm5_log_end(context);
151 if (!context->keep_open)
152 context->db->hdb_close(context->context, context->db);
157 ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
159 ret = hdb_clear_extension(context->context, &ent.entry,
160 choice_HDB_extension_data_hist_keys);
163 * Though in practice all real calls to this function will pass an empty
164 * ks_tuple, and cannot in any case employ any salts that require
165 * additional data, we go the extra mile to set any requested salt type
166 * along with a zero length salt value. While we're at it we check that
167 * each ks_tuple's enctype matches the corresponding key enctype.
170 free_Keys(&ent.entry.keys);
171 for (i = 0; i < n_keys; ++i) {
176 k.key = keyblocks[i];
180 if (ks_tuple[i].ks_enctype != keyblocks[i].keytype) {
181 ret = KADM5_SETKEY3_ETYPE_MISMATCH;
184 s.type = ks_tuple[i].ks_salttype;
189 if ((ret = add_Keys(&ent.entry.keys, &k)) != 0)
196 ent.entry.flags.require_pwchange = 0;
197 hdb_entry_set_pw_change_time(context->context, &ent.entry, 0);
198 hdb_entry_clear_password(context->context, &ent.entry);
200 if ((ret = hdb_seal_keys(context->context, context->db,
202 && (ret = _kadm5_set_modifier(context, &ent.entry)) == 0
203 && (ret = _kadm5_bump_pw_expire(context, &ent.entry)) == 0)
204 ret = kadm5_log_modify(context, &ent.entry,
205 KADM5_ATTRIBUTES | KADM5_PRINCIPAL |
206 KADM5_MOD_NAME | KADM5_MOD_TIME |
207 KADM5_KEY_DATA | KADM5_KVNO |
208 KADM5_PW_EXPIRATION | KADM5_TL_DATA);
211 (void) setkey_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, ret,
212 princ, keepold, n_ks_tuple, ks_tuple,
215 hdb_free_entry(context->context, &ent);
216 (void) kadm5_log_end(context);
217 if (!context->keep_open)
218 context->db->hdb_close(context->context, context->db);
219 return _kadm5_error_code(ret);