xref: /freebsd/crypto/heimdal/lib/kadm5/set_keys.c (revision 5e9cd1ae3e10592ed70e7575551cba1bbab04d84)
1b528cefcSMark Murray /*
25e9cd1aeSAssar Westerlund  * Copyright (c) 1997 - 2000 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "kadm5_locl.h"
35b528cefcSMark Murray 
365e9cd1aeSAssar Westerlund RCSID("$Id: set_keys.c,v 1.23 2000/11/15 23:13:30 assar Exp $");
37b528cefcSMark Murray 
38b528cefcSMark Murray /*
39b528cefcSMark Murray  * the known and used DES enctypes
40b528cefcSMark Murray  */
41b528cefcSMark Murray 
42b528cefcSMark Murray static krb5_enctype des_types[] = { ETYPE_DES_CBC_CRC,
43b528cefcSMark Murray  				    ETYPE_DES_CBC_MD4,
44b528cefcSMark Murray  				    ETYPE_DES_CBC_MD5 };
455e9cd1aeSAssar Westerlund static unsigned n_des_types = sizeof(des_types) / sizeof(des_types[0]);
46b528cefcSMark Murray 
475e9cd1aeSAssar Westerlund static krb5_error_code
485e9cd1aeSAssar Westerlund make_keys(krb5_context context, krb5_principal principal, const char *password,
495e9cd1aeSAssar Westerlund 	  Key **keys_ret, size_t *num_keys_ret)
505e9cd1aeSAssar Westerlund {
515e9cd1aeSAssar Westerlund     krb5_enctype all_etypes[] = { ETYPE_DES3_CBC_SHA1,
525e9cd1aeSAssar Westerlund 				  ETYPE_DES_CBC_MD5,
535e9cd1aeSAssar Westerlund 				  ETYPE_DES_CBC_MD4,
545e9cd1aeSAssar Westerlund 				  ETYPE_DES_CBC_CRC };
555e9cd1aeSAssar Westerlund 
565e9cd1aeSAssar Westerlund 
575e9cd1aeSAssar Westerlund     krb5_enctype e;
585e9cd1aeSAssar Westerlund 
595e9cd1aeSAssar Westerlund     krb5_error_code ret = 0;
605e9cd1aeSAssar Westerlund     char **ktypes, **kp;
615e9cd1aeSAssar Westerlund 
625e9cd1aeSAssar Westerlund     Key *keys = NULL, *tmp;
635e9cd1aeSAssar Westerlund     int num_keys = 0;
645e9cd1aeSAssar Westerlund     Key key;
655e9cd1aeSAssar Westerlund 
665e9cd1aeSAssar Westerlund     int i;
675e9cd1aeSAssar Westerlund     char *v4_ktypes[] = {"des3:pw-salt", "v4", NULL};
685e9cd1aeSAssar Westerlund 
695e9cd1aeSAssar Westerlund     ktypes = krb5_config_get_strings(context, NULL, "kadmin",
705e9cd1aeSAssar Westerlund 				     "default_keys", NULL);
715e9cd1aeSAssar Westerlund 
725e9cd1aeSAssar Westerlund     /* for each entry in `default_keys' try to parse it as a sequence
735e9cd1aeSAssar Westerlund        of etype:salttype:salt, syntax of this if something like:
745e9cd1aeSAssar Westerlund        [(des|des3|etype):](pw|afs3)[:string], if etype is omitted it
755e9cd1aeSAssar Westerlund        means everything, and if string is omitted is means the default
765e9cd1aeSAssar Westerlund        string (for that principal). Additional special values:
775e9cd1aeSAssar Westerlund        v5 == pw-salt, and
785e9cd1aeSAssar Westerlund        v4 == pw-salt:
795e9cd1aeSAssar Westerlund     */
805e9cd1aeSAssar Westerlund 
815e9cd1aeSAssar Westerlund     if (ktypes == NULL
825e9cd1aeSAssar Westerlund 	&& krb5_config_get_bool (context, NULL, "kadmin",
835e9cd1aeSAssar Westerlund 				 "use_v4_salt", NULL))
845e9cd1aeSAssar Westerlund 	ktypes = v4_ktypes;
855e9cd1aeSAssar Westerlund 
865e9cd1aeSAssar Westerlund     for(kp = ktypes; kp && *kp; kp++) {
875e9cd1aeSAssar Westerlund 	krb5_enctype *etypes;
885e9cd1aeSAssar Westerlund 	int num_etypes;
895e9cd1aeSAssar Westerlund 	krb5_salt salt;
905e9cd1aeSAssar Westerlund 	krb5_boolean salt_set;
915e9cd1aeSAssar Westerlund 
925e9cd1aeSAssar Westerlund 	const char *p;
935e9cd1aeSAssar Westerlund 	char buf[3][256];
945e9cd1aeSAssar Westerlund 	int num_buf = 0;
955e9cd1aeSAssar Westerlund 
965e9cd1aeSAssar Westerlund 	p = *kp;
975e9cd1aeSAssar Westerlund 	if(strcmp(p, "v5") == 0)
985e9cd1aeSAssar Westerlund 	    p = "pw-salt";
995e9cd1aeSAssar Westerlund 	else if(strcmp(p, "v4") == 0)
1005e9cd1aeSAssar Westerlund 	    p = "des:pw-salt:";
1015e9cd1aeSAssar Westerlund 
1025e9cd1aeSAssar Westerlund 	/* split p in a list of :-separated strings */
1035e9cd1aeSAssar Westerlund 	for(num_buf = 0; num_buf < 3; num_buf++)
1045e9cd1aeSAssar Westerlund 	    if(strsep_copy(&p, ":", buf[num_buf], sizeof(buf[num_buf])) == -1)
1055e9cd1aeSAssar Westerlund 		break;
1065e9cd1aeSAssar Westerlund 
1075e9cd1aeSAssar Westerlund 	etypes = NULL;
1085e9cd1aeSAssar Westerlund 	num_etypes = 0;
1095e9cd1aeSAssar Westerlund 	memset(&salt, 0, sizeof(salt));
1105e9cd1aeSAssar Westerlund 	salt_set = FALSE;
1115e9cd1aeSAssar Westerlund 
1125e9cd1aeSAssar Westerlund 	for(i = 0; i < num_buf; i++) {
1135e9cd1aeSAssar Westerlund 	    if(etypes == NULL) {
1145e9cd1aeSAssar Westerlund 		/* this might be a etype specifier */
1155e9cd1aeSAssar Westerlund 		/* XXX there should be a string_to_etypes handling
1165e9cd1aeSAssar Westerlund                    special cases like `des' and `all' */
1175e9cd1aeSAssar Westerlund 		if(strcmp(buf[i], "des") == 0) {
1185e9cd1aeSAssar Westerlund 		    etypes = all_etypes + 1;
1195e9cd1aeSAssar Westerlund 		    num_etypes = 3;
1205e9cd1aeSAssar Westerlund 		    continue;
1215e9cd1aeSAssar Westerlund 		} else if(strcmp(buf[i], "des3") == 0) {
1225e9cd1aeSAssar Westerlund 		    e = ETYPE_DES3_CBC_SHA1;
1235e9cd1aeSAssar Westerlund 		    etypes = &e;
1245e9cd1aeSAssar Westerlund 		    num_etypes = 1;
1255e9cd1aeSAssar Westerlund 		    continue;
1265e9cd1aeSAssar Westerlund 		} else {
1275e9cd1aeSAssar Westerlund 		    ret = krb5_string_to_enctype(context, buf[i], &e);
1285e9cd1aeSAssar Westerlund 		    if(ret == 0) {
1295e9cd1aeSAssar Westerlund 			etypes = &e;
1305e9cd1aeSAssar Westerlund 			num_etypes = 1;
1315e9cd1aeSAssar Westerlund 			continue;
1325e9cd1aeSAssar Westerlund 		    }
1335e9cd1aeSAssar Westerlund 		}
1345e9cd1aeSAssar Westerlund 	    }
1355e9cd1aeSAssar Westerlund 	    if(salt.salttype == 0) {
1365e9cd1aeSAssar Westerlund 		/* interpret string as a salt specifier, if no etype
1375e9cd1aeSAssar Westerlund                    is set, this sets default values */
1385e9cd1aeSAssar Westerlund 		/* XXX should perhaps use string_to_salttype, but that
1395e9cd1aeSAssar Westerlund                    interface sucks */
1405e9cd1aeSAssar Westerlund 		if(strcmp(buf[i], "pw-salt") == 0) {
1415e9cd1aeSAssar Westerlund 		    if(etypes == NULL) {
1425e9cd1aeSAssar Westerlund 			etypes = all_etypes;
1435e9cd1aeSAssar Westerlund 			num_etypes = 4;
1445e9cd1aeSAssar Westerlund 		    }
1455e9cd1aeSAssar Westerlund 		    salt.salttype = KRB5_PW_SALT;
1465e9cd1aeSAssar Westerlund 		} else if(strcmp(buf[i], "afs3-salt") == 0) {
1475e9cd1aeSAssar Westerlund 		    if(etypes == NULL) {
1485e9cd1aeSAssar Westerlund 			etypes = all_etypes + 1;
1495e9cd1aeSAssar Westerlund 			num_etypes = 3;
1505e9cd1aeSAssar Westerlund 		    }
1515e9cd1aeSAssar Westerlund 		    salt.salttype = KRB5_AFS3_SALT;
1525e9cd1aeSAssar Westerlund 		}
1535e9cd1aeSAssar Westerlund 	    } else {
1545e9cd1aeSAssar Westerlund 		/* if there is a final string, use it as the string to
1555e9cd1aeSAssar Westerlund                    salt with, this is mostly useful with null salt for
1565e9cd1aeSAssar Westerlund                    v4 compat, and a cell name for afs compat */
1575e9cd1aeSAssar Westerlund 		salt.saltvalue.data = buf[i];
1585e9cd1aeSAssar Westerlund 		salt.saltvalue.length = strlen(buf[i]);
1595e9cd1aeSAssar Westerlund 		salt_set = TRUE;
1605e9cd1aeSAssar Westerlund 	    }
1615e9cd1aeSAssar Westerlund 	}
1625e9cd1aeSAssar Westerlund 
1635e9cd1aeSAssar Westerlund 	if(etypes == NULL || salt.salttype == 0) {
1645e9cd1aeSAssar Westerlund 	    krb5_warnx(context, "bad value for default_keys `%s'", *kp);
1655e9cd1aeSAssar Westerlund 	    continue;
1665e9cd1aeSAssar Westerlund 	}
1675e9cd1aeSAssar Westerlund 
1685e9cd1aeSAssar Westerlund 	if(!salt_set && salt.salttype == KRB5_PW_SALT)
1695e9cd1aeSAssar Westerlund 	    /* make up default salt */
1705e9cd1aeSAssar Westerlund 	    ret = krb5_get_pw_salt(context, principal, &salt);
1715e9cd1aeSAssar Westerlund 	memset(&key, 0, sizeof(key));
1725e9cd1aeSAssar Westerlund 	for(i = 0; i < num_etypes; i++) {
1735e9cd1aeSAssar Westerlund 	    ret = krb5_string_to_key_salt (context,
1745e9cd1aeSAssar Westerlund 					   etypes[i],
1755e9cd1aeSAssar Westerlund 					   password,
1765e9cd1aeSAssar Westerlund 					   salt,
1775e9cd1aeSAssar Westerlund 					   &key.key);
1785e9cd1aeSAssar Westerlund 
1795e9cd1aeSAssar Westerlund 	    if(ret)
1805e9cd1aeSAssar Westerlund 		goto out;
1815e9cd1aeSAssar Westerlund 
1825e9cd1aeSAssar Westerlund 	    if (salt.salttype != KRB5_PW_SALT || salt_set) {
1835e9cd1aeSAssar Westerlund 		key.salt = malloc (sizeof(*key.salt));
1845e9cd1aeSAssar Westerlund 		if (key.salt == NULL) {
1855e9cd1aeSAssar Westerlund 		    free_Key(&key);
1865e9cd1aeSAssar Westerlund 		    ret = ENOMEM;
1875e9cd1aeSAssar Westerlund 		    goto out;
1885e9cd1aeSAssar Westerlund 		}
1895e9cd1aeSAssar Westerlund 		key.salt->type = salt.salttype;
1905e9cd1aeSAssar Westerlund 		krb5_data_zero (&key.salt->salt);
1915e9cd1aeSAssar Westerlund 
1925e9cd1aeSAssar Westerlund 		/* is the salt has not been set explicitly, it will be
1935e9cd1aeSAssar Westerlund 		   the default salt, so there's no need to explicitly
1945e9cd1aeSAssar Westerlund 		   copy it */
1955e9cd1aeSAssar Westerlund 		if (salt_set) {
1965e9cd1aeSAssar Westerlund 		    ret = krb5_data_copy(&key.salt->salt,
1975e9cd1aeSAssar Westerlund 					 salt.saltvalue.data,
1985e9cd1aeSAssar Westerlund 					 salt.saltvalue.length);
1995e9cd1aeSAssar Westerlund 		    if (ret) {
2005e9cd1aeSAssar Westerlund 			free_Key(&key);
2015e9cd1aeSAssar Westerlund 			goto out;
2025e9cd1aeSAssar Westerlund 		    }
2035e9cd1aeSAssar Westerlund 		}
2045e9cd1aeSAssar Westerlund 	    }
2055e9cd1aeSAssar Westerlund 	    tmp = realloc(keys, (num_keys + 1) * sizeof(*keys));
2065e9cd1aeSAssar Westerlund 	    if(tmp == NULL) {
2075e9cd1aeSAssar Westerlund 		free_Key(&key);
2085e9cd1aeSAssar Westerlund 		ret = ENOMEM;
2095e9cd1aeSAssar Westerlund 		goto out;
2105e9cd1aeSAssar Westerlund 	    }
2115e9cd1aeSAssar Westerlund 	    keys = tmp;
2125e9cd1aeSAssar Westerlund 	    keys[num_keys++] = key;
2135e9cd1aeSAssar Westerlund 	}
2145e9cd1aeSAssar Westerlund     }
2155e9cd1aeSAssar Westerlund 
2165e9cd1aeSAssar Westerlund     if(num_keys == 0) {
2175e9cd1aeSAssar Westerlund 	/* if we didn't manage to find a single valid key, create a
2185e9cd1aeSAssar Westerlund            default set */
2195e9cd1aeSAssar Westerlund 	/* XXX only do this is there is no `default_keys'? */
2205e9cd1aeSAssar Westerlund 	krb5_salt v5_salt;
2215e9cd1aeSAssar Westerlund 	tmp = realloc(keys, (num_keys + 4) * sizeof(*keys));
2225e9cd1aeSAssar Westerlund 	if(tmp == NULL) {
2235e9cd1aeSAssar Westerlund 	    ret = ENOMEM;
2245e9cd1aeSAssar Westerlund 	    goto out;
2255e9cd1aeSAssar Westerlund 	}
2265e9cd1aeSAssar Westerlund 	keys = tmp;
2275e9cd1aeSAssar Westerlund 	ret = krb5_get_pw_salt(context, principal, &v5_salt);
2285e9cd1aeSAssar Westerlund 	if(ret)
2295e9cd1aeSAssar Westerlund 	    goto out;
2305e9cd1aeSAssar Westerlund 	for(i = 0; i < 4; i++) {
2315e9cd1aeSAssar Westerlund 	    memset(&key, 0, sizeof(key));
2325e9cd1aeSAssar Westerlund 	    ret = krb5_string_to_key_salt(context, all_etypes[i], password,
2335e9cd1aeSAssar Westerlund 					  v5_salt, &key.key);
2345e9cd1aeSAssar Westerlund 	    if(ret) {
2355e9cd1aeSAssar Westerlund 		krb5_free_salt(context, v5_salt);
2365e9cd1aeSAssar Westerlund 		goto out;
2375e9cd1aeSAssar Westerlund 	    }
2385e9cd1aeSAssar Westerlund 	    keys[num_keys++] = key;
2395e9cd1aeSAssar Westerlund 	}
2405e9cd1aeSAssar Westerlund 	krb5_free_salt(context, v5_salt);
2415e9cd1aeSAssar Westerlund     }
2425e9cd1aeSAssar Westerlund 
2435e9cd1aeSAssar Westerlund   out:
2445e9cd1aeSAssar Westerlund     if(ret == 0) {
2455e9cd1aeSAssar Westerlund 	*keys_ret = keys;
2465e9cd1aeSAssar Westerlund 	*num_keys_ret = num_keys;
2475e9cd1aeSAssar Westerlund     } else {
2485e9cd1aeSAssar Westerlund 	for(i = 0; i < num_keys; i++) {
2495e9cd1aeSAssar Westerlund 	    free_Key(&keys[i]);
2505e9cd1aeSAssar Westerlund 	}
2515e9cd1aeSAssar Westerlund 	free(keys);
2525e9cd1aeSAssar Westerlund     }
2535e9cd1aeSAssar Westerlund     return ret;
2545e9cd1aeSAssar Westerlund }
255b528cefcSMark Murray 
256b528cefcSMark Murray /*
257b528cefcSMark Murray  * Set the keys of `ent' to the string-to-key of `password'
258b528cefcSMark Murray  */
259b528cefcSMark Murray 
260b528cefcSMark Murray kadm5_ret_t
261b528cefcSMark Murray _kadm5_set_keys(kadm5_server_context *context,
262b528cefcSMark Murray 		hdb_entry *ent,
263b528cefcSMark Murray 		const char *password)
264b528cefcSMark Murray {
2655e9cd1aeSAssar Westerlund     kadm5_ret_t ret;
266b528cefcSMark Murray     Key *keys;
2675e9cd1aeSAssar Westerlund     size_t num_keys;
268b528cefcSMark Murray 
2695e9cd1aeSAssar Westerlund     ret = make_keys(context->context, ent->principal, password,
2705e9cd1aeSAssar Westerlund 		    &keys, &num_keys);
271b528cefcSMark Murray 
272b528cefcSMark Murray     if(ret)
2735e9cd1aeSAssar Westerlund 	return ret;
274b528cefcSMark Murray 
2755e9cd1aeSAssar Westerlund     _kadm5_free_keys (context, ent->keys.len, ent->keys.val);
276b528cefcSMark Murray     ent->keys.val = keys;
2775e9cd1aeSAssar Westerlund     ent->keys.len = num_keys;
278b528cefcSMark Murray     ent->kvno++;
2795e9cd1aeSAssar Westerlund     return 0;
280b528cefcSMark Murray }
281b528cefcSMark Murray 
282b528cefcSMark Murray /*
283b528cefcSMark Murray  * Set the keys of `ent' to (`n_key_data', `key_data')
284b528cefcSMark Murray  */
285b528cefcSMark Murray 
286b528cefcSMark Murray kadm5_ret_t
2875e9cd1aeSAssar Westerlund _kadm5_set_keys2(kadm5_server_context *context,
2885e9cd1aeSAssar Westerlund 		 hdb_entry *ent,
289b528cefcSMark Murray 		 int16_t n_key_data,
290b528cefcSMark Murray 		 krb5_key_data *key_data)
291b528cefcSMark Murray {
292b528cefcSMark Murray     krb5_error_code ret;
293b528cefcSMark Murray     int i;
2945e9cd1aeSAssar Westerlund     unsigned len;
2955e9cd1aeSAssar Westerlund     Key *keys;
296b528cefcSMark Murray 
2975e9cd1aeSAssar Westerlund     len  = n_key_data;
2985e9cd1aeSAssar Westerlund     keys = malloc (len * sizeof(*keys));
2995e9cd1aeSAssar Westerlund     if (keys == NULL)
300b528cefcSMark Murray 	return ENOMEM;
3015e9cd1aeSAssar Westerlund 
3025e9cd1aeSAssar Westerlund     _kadm5_init_keys (keys, len);
3035e9cd1aeSAssar Westerlund 
304b528cefcSMark Murray     for(i = 0; i < n_key_data; i++) {
3055e9cd1aeSAssar Westerlund 	keys[i].mkvno = NULL;
3065e9cd1aeSAssar Westerlund 	keys[i].key.keytype = key_data[i].key_data_type[0];
3075e9cd1aeSAssar Westerlund 	ret = krb5_data_copy(&keys[i].key.keyvalue,
308b528cefcSMark Murray 			     key_data[i].key_data_contents[0],
309b528cefcSMark Murray 			     key_data[i].key_data_length[0]);
310b528cefcSMark Murray 	if(ret)
3115e9cd1aeSAssar Westerlund 	    goto out;
312b528cefcSMark Murray 	if(key_data[i].key_data_ver == 2) {
313b528cefcSMark Murray 	    Salt *salt;
3145e9cd1aeSAssar Westerlund 
315b528cefcSMark Murray 	    salt = malloc(sizeof(*salt));
3165e9cd1aeSAssar Westerlund 	    if(salt == NULL) {
3175e9cd1aeSAssar Westerlund 		ret = ENOMEM;
3185e9cd1aeSAssar Westerlund 		goto out;
3195e9cd1aeSAssar Westerlund 	    }
3205e9cd1aeSAssar Westerlund 	    keys[i].salt = salt;
321b528cefcSMark Murray 	    salt->type = key_data[i].key_data_type[1];
322b528cefcSMark Murray 	    krb5_data_copy(&salt->salt,
323b528cefcSMark Murray 			   key_data[i].key_data_contents[1],
324b528cefcSMark Murray 			   key_data[i].key_data_length[1]);
325b528cefcSMark Murray 	} else
3265e9cd1aeSAssar Westerlund 	    keys[i].salt = NULL;
327b528cefcSMark Murray     }
3285e9cd1aeSAssar Westerlund     _kadm5_free_keys (context, ent->keys.len, ent->keys.val);
3295e9cd1aeSAssar Westerlund     ent->keys.len = len;
3305e9cd1aeSAssar Westerlund     ent->keys.val = keys;
331b528cefcSMark Murray     ent->kvno++;
332b528cefcSMark Murray     return 0;
3335e9cd1aeSAssar Westerlund  out:
3345e9cd1aeSAssar Westerlund     _kadm5_free_keys (context, len, keys);
3355e9cd1aeSAssar Westerlund     return ret;
3365e9cd1aeSAssar Westerlund }
3375e9cd1aeSAssar Westerlund 
3385e9cd1aeSAssar Westerlund /*
3395e9cd1aeSAssar Westerlund  * Set the keys of `ent' to `n_keys, keys'
3405e9cd1aeSAssar Westerlund  */
3415e9cd1aeSAssar Westerlund 
3425e9cd1aeSAssar Westerlund kadm5_ret_t
3435e9cd1aeSAssar Westerlund _kadm5_set_keys3(kadm5_server_context *context,
3445e9cd1aeSAssar Westerlund 		 hdb_entry *ent,
3455e9cd1aeSAssar Westerlund 		 int n_keys,
3465e9cd1aeSAssar Westerlund 		 krb5_keyblock *keyblocks)
3475e9cd1aeSAssar Westerlund {
3485e9cd1aeSAssar Westerlund     krb5_error_code ret;
3495e9cd1aeSAssar Westerlund     int i;
3505e9cd1aeSAssar Westerlund     unsigned len;
3515e9cd1aeSAssar Westerlund     Key *keys;
3525e9cd1aeSAssar Westerlund 
3535e9cd1aeSAssar Westerlund     len  = n_keys;
3545e9cd1aeSAssar Westerlund     keys = malloc (len * sizeof(*keys));
3555e9cd1aeSAssar Westerlund     if (keys == NULL)
3565e9cd1aeSAssar Westerlund 	return ENOMEM;
3575e9cd1aeSAssar Westerlund 
3585e9cd1aeSAssar Westerlund     _kadm5_init_keys (keys, len);
3595e9cd1aeSAssar Westerlund 
3605e9cd1aeSAssar Westerlund     for(i = 0; i < n_keys; i++) {
3615e9cd1aeSAssar Westerlund 	keys[i].mkvno = NULL;
3625e9cd1aeSAssar Westerlund 	ret = krb5_copy_keyblock_contents (context->context,
3635e9cd1aeSAssar Westerlund 					   &keyblocks[i],
3645e9cd1aeSAssar Westerlund 					   &keys[i].key);
3655e9cd1aeSAssar Westerlund 	if(ret)
3665e9cd1aeSAssar Westerlund 	    goto out;
3675e9cd1aeSAssar Westerlund 	keys[i].salt = NULL;
3685e9cd1aeSAssar Westerlund     }
3695e9cd1aeSAssar Westerlund     _kadm5_free_keys (context, ent->keys.len, ent->keys.val);
3705e9cd1aeSAssar Westerlund     ent->keys.len = len;
3715e9cd1aeSAssar Westerlund     ent->keys.val = keys;
3725e9cd1aeSAssar Westerlund     ent->kvno++;
3735e9cd1aeSAssar Westerlund     return 0;
3745e9cd1aeSAssar Westerlund  out:
3755e9cd1aeSAssar Westerlund     _kadm5_free_keys (context, len, keys);
3765e9cd1aeSAssar Westerlund     return ret;
377b528cefcSMark Murray }
378b528cefcSMark Murray 
379b528cefcSMark Murray /*
380b528cefcSMark Murray  * Set the keys of `ent' to random keys and return them in `n_keys'
381b528cefcSMark Murray  * and `new_keys'.
382b528cefcSMark Murray  */
383b528cefcSMark Murray 
384b528cefcSMark Murray kadm5_ret_t
385b528cefcSMark Murray _kadm5_set_keys_randomly (kadm5_server_context *context,
386b528cefcSMark Murray 			  hdb_entry *ent,
387b528cefcSMark Murray 			  krb5_keyblock **new_keys,
388b528cefcSMark Murray 			  int *n_keys)
389b528cefcSMark Murray {
390b528cefcSMark Murray     kadm5_ret_t ret = 0;
391b528cefcSMark Murray     int i;
392b528cefcSMark Murray     unsigned len;
393b528cefcSMark Murray     krb5_keyblock *keys;
394b528cefcSMark Murray     Key *hkeys;
395b528cefcSMark Murray 
396b528cefcSMark Murray     len  = n_des_types + 1;
397b528cefcSMark Murray     keys = malloc (len * sizeof(*keys));
398b528cefcSMark Murray     if (keys == NULL)
399b528cefcSMark Murray 	return ENOMEM;
400b528cefcSMark Murray 
401b528cefcSMark Murray     for (i = 0; i < len; ++i) {
402b528cefcSMark Murray 	keys[i].keyvalue.length = 0;
403b528cefcSMark Murray 	keys[i].keyvalue.data   = NULL;
404b528cefcSMark Murray     }
405b528cefcSMark Murray 
406b528cefcSMark Murray     hkeys = malloc (len * sizeof(*hkeys));
407b528cefcSMark Murray     if (hkeys == NULL) {
408b528cefcSMark Murray 	free (keys);
409b528cefcSMark Murray 	return ENOMEM;
410b528cefcSMark Murray     }
411b528cefcSMark Murray 
4125e9cd1aeSAssar Westerlund     _kadm5_init_keys (hkeys, len);
413b528cefcSMark Murray 
414b528cefcSMark Murray     ret = krb5_generate_random_keyblock (context->context,
415b528cefcSMark Murray 					 des_types[0],
416b528cefcSMark Murray 					 &keys[0]);
417b528cefcSMark Murray     if (ret)
418b528cefcSMark Murray 	goto out;
419b528cefcSMark Murray 
420b528cefcSMark Murray     ret = krb5_copy_keyblock_contents (context->context,
421b528cefcSMark Murray 				       &keys[0],
422b528cefcSMark Murray 				       &hkeys[0].key);
423b528cefcSMark Murray     if (ret)
424b528cefcSMark Murray 	goto out;
425b528cefcSMark Murray 
426b528cefcSMark Murray     for (i = 1; i < n_des_types; ++i) {
427b528cefcSMark Murray 	ret = krb5_copy_keyblock_contents (context->context,
428b528cefcSMark Murray 					   &keys[0],
429b528cefcSMark Murray 					   &keys[i]);
430b528cefcSMark Murray 	if (ret)
431b528cefcSMark Murray 	    goto out;
432b528cefcSMark Murray 	keys[i].keytype = des_types[i];
433b528cefcSMark Murray 	ret = krb5_copy_keyblock_contents (context->context,
434b528cefcSMark Murray 					   &keys[0],
435b528cefcSMark Murray 					   &hkeys[i].key);
436b528cefcSMark Murray 	if (ret)
437b528cefcSMark Murray 	    goto out;
438b528cefcSMark Murray 	hkeys[i].key.keytype = des_types[i];
439b528cefcSMark Murray     }
440b528cefcSMark Murray 
441b528cefcSMark Murray     ret = krb5_generate_random_keyblock (context->context,
442b528cefcSMark Murray 					 ETYPE_DES3_CBC_SHA1,
443b528cefcSMark Murray 					 &keys[n_des_types]);
444b528cefcSMark Murray     if (ret)
445b528cefcSMark Murray 	goto out;
446b528cefcSMark Murray 
447b528cefcSMark Murray     ret = krb5_copy_keyblock_contents (context->context,
448b528cefcSMark Murray 				       &keys[n_des_types],
449b528cefcSMark Murray 				       &hkeys[n_des_types].key);
450b528cefcSMark Murray     if (ret)
451b528cefcSMark Murray 	goto out;
452b528cefcSMark Murray 
4535e9cd1aeSAssar Westerlund     _kadm5_free_keys (context, ent->keys.len, ent->keys.val);
454b528cefcSMark Murray     ent->keys.len = len;
455b528cefcSMark Murray     ent->keys.val = hkeys;
456b528cefcSMark Murray     ent->kvno++;
457b528cefcSMark Murray     *new_keys     = keys;
458b528cefcSMark Murray     *n_keys       = len;
459b528cefcSMark Murray     return ret;
460b528cefcSMark Murray out:
461b528cefcSMark Murray     for (i = 0; i < len; ++i)
462b528cefcSMark Murray 	krb5_free_keyblock_contents (context->context, &keys[i]);
463b528cefcSMark Murray     free (keys);
4645e9cd1aeSAssar Westerlund     _kadm5_free_keys (context, len, hkeys);
465b528cefcSMark Murray     return ret;
466b528cefcSMark Murray }
467