155682Smarkm/*
2233294Sstas * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2055682Smarkm *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "kadm5_locl.h"
3555682Smarkm
36233294SstasRCSID("$Id$");
3755682Smarkm
3855682Smarkm/*
3972445Sassar * Set the keys of `ent' to the string-to-key of `password'
4072445Sassar */
4172445Sassar
4272445Sassarkadm5_ret_t
4372445Sassar_kadm5_set_keys(kadm5_server_context *context,
44233294Sstas		hdb_entry *ent,
4572445Sassar		const char *password)
4672445Sassar{
4772445Sassar    Key *keys;
4872445Sassar    size_t num_keys;
49178825Sdfr    kadm5_ret_t ret;
5072445Sassar
51178825Sdfr    ret = hdb_generate_key_set_password(context->context,
52233294Sstas					ent->principal,
53178825Sdfr					password, &keys, &num_keys);
54178825Sdfr    if (ret)
55178825Sdfr	return ret;
5672445Sassar
57178825Sdfr    _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
5855682Smarkm    ent->keys.val = keys;
5972445Sassar    ent->keys.len = num_keys;
60178825Sdfr
61178825Sdfr    hdb_entry_set_pw_change_time(context->context, ent, 0);
62178825Sdfr
63233294Sstas    if (krb5_config_get_bool_default(context->context, NULL, FALSE,
64178825Sdfr				     "kadmin", "save-password", NULL))
65178825Sdfr    {
66178825Sdfr	ret = hdb_entry_set_password(context->context, context->db,
67178825Sdfr				     ent, password);
68178825Sdfr	if (ret)
69178825Sdfr	    return ret;
70178825Sdfr    }
71178825Sdfr
7272445Sassar    return 0;
7355682Smarkm}
7455682Smarkm
7555682Smarkm/*
7655682Smarkm * Set the keys of `ent' to (`n_key_data', `key_data')
7755682Smarkm */
7855682Smarkm
7955682Smarkmkadm5_ret_t
8072445Sassar_kadm5_set_keys2(kadm5_server_context *context,
81233294Sstas		 hdb_entry *ent,
82233294Sstas		 int16_t n_key_data,
8355682Smarkm		 krb5_key_data *key_data)
8455682Smarkm{
8555682Smarkm    krb5_error_code ret;
8655682Smarkm    int i;
8772445Sassar    unsigned len;
8872445Sassar    Key *keys;
8955682Smarkm
9072445Sassar    len  = n_key_data;
9172445Sassar    keys = malloc (len * sizeof(*keys));
92233294Sstas    if (keys == NULL && len != 0)
9355682Smarkm	return ENOMEM;
9472445Sassar
9572445Sassar    _kadm5_init_keys (keys, len);
9672445Sassar
9755682Smarkm    for(i = 0; i < n_key_data; i++) {
9872445Sassar	keys[i].mkvno = NULL;
9972445Sassar	keys[i].key.keytype = key_data[i].key_data_type[0];
10072445Sassar	ret = krb5_data_copy(&keys[i].key.keyvalue,
10155682Smarkm			     key_data[i].key_data_contents[0],
10255682Smarkm			     key_data[i].key_data_length[0]);
10355682Smarkm	if(ret)
10472445Sassar	    goto out;
10555682Smarkm	if(key_data[i].key_data_ver == 2) {
10655682Smarkm	    Salt *salt;
10772445Sassar
108233294Sstas	    salt = calloc(1, sizeof(*salt));
10972445Sassar	    if(salt == NULL) {
11072445Sassar		ret = ENOMEM;
11172445Sassar		goto out;
11272445Sassar	    }
11372445Sassar	    keys[i].salt = salt;
11455682Smarkm	    salt->type = key_data[i].key_data_type[1];
115233294Sstas	    krb5_data_copy(&salt->salt,
11655682Smarkm			   key_data[i].key_data_contents[1],
11755682Smarkm			   key_data[i].key_data_length[1]);
11855682Smarkm	} else
11972445Sassar	    keys[i].salt = NULL;
12055682Smarkm    }
121178825Sdfr    _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
12272445Sassar    ent->keys.len = len;
12372445Sassar    ent->keys.val = keys;
124178825Sdfr
125178825Sdfr    hdb_entry_set_pw_change_time(context->context, ent, 0);
126178825Sdfr    hdb_entry_clear_password(context->context, ent);
127178825Sdfr
12855682Smarkm    return 0;
12972445Sassar out:
130178825Sdfr    _kadm5_free_keys (context->context, len, keys);
13172445Sassar    return ret;
13255682Smarkm}
13355682Smarkm
13455682Smarkm/*
13572445Sassar * Set the keys of `ent' to `n_keys, keys'
13672445Sassar */
13772445Sassar
13872445Sassarkadm5_ret_t
13972445Sassar_kadm5_set_keys3(kadm5_server_context *context,
14072445Sassar		 hdb_entry *ent,
14172445Sassar		 int n_keys,
14272445Sassar		 krb5_keyblock *keyblocks)
14372445Sassar{
14472445Sassar    krb5_error_code ret;
14572445Sassar    int i;
14672445Sassar    unsigned len;
14772445Sassar    Key *keys;
14872445Sassar
14972445Sassar    len  = n_keys;
15072445Sassar    keys = malloc (len * sizeof(*keys));
151233294Sstas    if (keys == NULL && len != 0)
15272445Sassar	return ENOMEM;
15372445Sassar
15472445Sassar    _kadm5_init_keys (keys, len);
15572445Sassar
15672445Sassar    for(i = 0; i < n_keys; i++) {
15772445Sassar	keys[i].mkvno = NULL;
15872445Sassar	ret = krb5_copy_keyblock_contents (context->context,
15972445Sassar					   &keyblocks[i],
16072445Sassar					   &keys[i].key);
16172445Sassar	if(ret)
16272445Sassar	    goto out;
16372445Sassar	keys[i].salt = NULL;
16472445Sassar    }
165178825Sdfr    _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
16672445Sassar    ent->keys.len = len;
16772445Sassar    ent->keys.val = keys;
168178825Sdfr
169178825Sdfr    hdb_entry_set_pw_change_time(context->context, ent, 0);
170178825Sdfr    hdb_entry_clear_password(context->context, ent);
171178825Sdfr
17272445Sassar    return 0;
17372445Sassar out:
174178825Sdfr    _kadm5_free_keys (context->context, len, keys);
17572445Sassar    return ret;
17672445Sassar}
17772445Sassar
17872445Sassar/*
179178825Sdfr *
180178825Sdfr */
181178825Sdfr
182178825Sdfrstatic int
183178825Sdfris_des_key_p(int keytype)
184178825Sdfr{
185178825Sdfr    return keytype == ETYPE_DES_CBC_CRC ||
186178825Sdfr    	keytype == ETYPE_DES_CBC_MD4 ||
187178825Sdfr	keytype == ETYPE_DES_CBC_MD5;
188178825Sdfr}
189178825Sdfr
190178825Sdfr
191178825Sdfr/*
19255682Smarkm * Set the keys of `ent' to random keys and return them in `n_keys'
19355682Smarkm * and `new_keys'.
19455682Smarkm */
19555682Smarkm
19655682Smarkmkadm5_ret_t
19755682Smarkm_kadm5_set_keys_randomly (kadm5_server_context *context,
19855682Smarkm			  hdb_entry *ent,
19955682Smarkm			  krb5_keyblock **new_keys,
20055682Smarkm			  int *n_keys)
20155682Smarkm{
202178825Sdfr   krb5_keyblock *kblock = NULL;
203178825Sdfr   kadm5_ret_t ret = 0;
204233294Sstas   int des_keyblock;
205233294Sstas   size_t i, num_keys;
206178825Sdfr   Key *keys;
20755682Smarkm
208178825Sdfr   ret = hdb_generate_key_set(context->context, ent->principal,
209178825Sdfr			       &keys, &num_keys, 1);
210178825Sdfr   if (ret)
211178825Sdfr	return ret;
21255682Smarkm
213178825Sdfr   kblock = malloc(num_keys * sizeof(kblock[0]));
214178825Sdfr   if (kblock == NULL) {
215178825Sdfr	ret = ENOMEM;
216178825Sdfr	_kadm5_free_keys (context->context, num_keys, keys);
217178825Sdfr	return ret;
218178825Sdfr   }
219178825Sdfr   memset(kblock, 0, num_keys * sizeof(kblock[0]));
22055682Smarkm
221178825Sdfr   des_keyblock = -1;
222178825Sdfr   for (i = 0; i < num_keys; i++) {
22355682Smarkm
224233294Sstas	/*
225178825Sdfr	 * To make sure all des keys are the the same we generate only
226178825Sdfr	 * the first one and then copy key to all other des keys.
227178825Sdfr	 */
22855682Smarkm
229178825Sdfr	if (des_keyblock != -1 && is_des_key_p(keys[i].key.keytype)) {
230178825Sdfr	    ret = krb5_copy_keyblock_contents (context->context,
231178825Sdfr					       &kblock[des_keyblock],
232178825Sdfr					       &kblock[i]);
233178825Sdfr	    if (ret)
234178825Sdfr		goto out;
235178825Sdfr	    kblock[i].keytype = keys[i].key.keytype;
236178825Sdfr	} else {
237178825Sdfr	    ret = krb5_generate_random_keyblock (context->context,
238178825Sdfr						 keys[i].key.keytype,
239178825Sdfr						 &kblock[i]);
240178825Sdfr	    if (ret)
241178825Sdfr		goto out;
24255682Smarkm
243178825Sdfr	    if (is_des_key_p(keys[i].key.keytype))
244178825Sdfr		des_keyblock = i;
245178825Sdfr	}
24655682Smarkm
24755682Smarkm	ret = krb5_copy_keyblock_contents (context->context,
248178825Sdfr					   &kblock[i],
249178825Sdfr					   &keys[i].key);
25055682Smarkm	if (ret)
25155682Smarkm	    goto out;
252178825Sdfr   }
25355682Smarkm
254178825Sdfrout:
255178825Sdfr   if(ret) {
256178825Sdfr	for (i = 0; i < num_keys; ++i)
257178825Sdfr	    krb5_free_keyblock_contents (context->context, &kblock[i]);
258178825Sdfr	free(kblock);
259178825Sdfr	_kadm5_free_keys (context->context, num_keys, keys);
260178825Sdfr	return ret;
261178825Sdfr   }
262233294Sstas
263178825Sdfr   _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
264178825Sdfr   ent->keys.val = keys;
265178825Sdfr   ent->keys.len = num_keys;
266178825Sdfr   *new_keys     = kblock;
267178825Sdfr   *n_keys       = num_keys;
26855682Smarkm
269178825Sdfr   hdb_entry_set_pw_change_time(context->context, ent, 0);
270178825Sdfr   hdb_entry_clear_password(context->context, ent);
27155682Smarkm
272178825Sdfr   return 0;
27355682Smarkm}
274