set_keys.c revision 55682
1193323Sed/*
2193323Sed * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H�gskolan
3193323Sed * (Royal Institute of Technology, Stockholm, Sweden).
4193323Sed * All rights reserved.
5193323Sed *
6193323Sed * Redistribution and use in source and binary forms, with or without
7193323Sed * modification, are permitted provided that the following conditions
8193323Sed * are met:
9193323Sed *
10193323Sed * 1. Redistributions of source code must retain the above copyright
11193323Sed *    notice, this list of conditions and the following disclaimer.
12203954Srdivacky *
13193323Sed * 2. Redistributions in binary form must reproduce the above copyright
14193323Sed *    notice, this list of conditions and the following disclaimer in the
15193323Sed *    documentation and/or other materials provided with the distribution.
16193323Sed *
17193323Sed * 3. Neither the name of the Institute nor the names of its contributors
18193323Sed *    may be used to endorse or promote products derived from this software
19234353Sdim *    without specific prior written permission.
20249423Sdim *
21239462Sdim * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22249423Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23249423Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24239462Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25243830Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30239462Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31263508Sdim * SUCH DAMAGE.
32193323Sed */
33193323Sed
34193323Sed#include "kadm5_locl.h"
35198090Srdivacky
36249423SdimRCSID("$Id: set_keys.c,v 1.18 1999/12/04 23:11:01 assar Exp $");
37249423Sdim
38249423Sdim/*
39193323Sed * free all the memory used by (len, keys)
40193323Sed */
41193323Sed
42226633Sdimstatic void
43226633Sdimfree_keys (kadm5_server_context *context,
44193323Sed	   int len, Key *keys)
45193323Sed{
46193323Sed    int i;
47193323Sed
48193323Sed    for (i = 0; i < len; ++i) {
49193323Sed	free (keys[i].mkvno);
50193323Sed	keys[i].mkvno = NULL;
51218893Sdim	if (keys[i].salt != NULL) {
52193323Sed	    free_Salt(keys[i].salt);
53193323Sed	    free(keys[i].salt);
54194612Sed	    keys[i].salt = NULL;
55193323Sed	}
56193323Sed	krb5_free_keyblock_contents(context->context, &keys[i].key);
57193323Sed    }
58198892Srdivacky    free (keys);
59193323Sed}
60193323Sed
61193323Sed/*
62193323Sed * null-ify `len', `keys'
63193323Sed */
64193323Sed
65193323Sedstatic void
66193323Sedinit_keys (Key *keys, int len)
67193323Sed{
68218893Sdim    int i;
69218893Sdim
70218893Sdim    for (i = 0; i < len; ++i) {
71218893Sdim	keys[i].mkvno               = NULL;
72193323Sed	keys[i].salt                = NULL;
73193323Sed	keys[i].key.keyvalue.length = 0;
74218893Sdim	keys[i].key.keyvalue.data   = NULL;
75218893Sdim    }
76218893Sdim}
77226633Sdim
78218893Sdim/*
79218893Sdim * the known and used DES enctypes
80218893Sdim */
81249423Sdim
82249423Sdimstatic krb5_enctype des_types[] = { ETYPE_DES_CBC_CRC,
83249423Sdim				    ETYPE_DES_CBC_MD4,
84249423Sdim				    ETYPE_DES_CBC_MD5 };
85249423Sdim
86249423Sdimstatic unsigned n_des_types = 3;
87249423Sdim
88194612Sed/*
89194612Sed * Set the keys of `ent' to the string-to-key of `password'
90249423Sdim */
91249423Sdim
92249423Sdimkadm5_ret_t
93249423Sdim_kadm5_set_keys(kadm5_server_context *context,
94249423Sdim		hdb_entry *ent,
95249423Sdim		const char *password)
96249423Sdim{
97249423Sdim    kadm5_ret_t ret = 0;
98249423Sdim    int i;
99193323Sed    unsigned len;
100193323Sed    Key *keys;
101193323Sed    krb5_salt salt;
102193323Sed    krb5_boolean v4_salt = FALSE;
103193323Sed
104218893Sdim    len  = n_des_types + 1;
105193323Sed    keys = malloc (len * sizeof(*keys));
106193323Sed    if (keys == NULL)
107193323Sed	return ENOMEM;
108193323Sed
109193323Sed    init_keys (keys, len);
110193323Sed
111193323Sed    salt.salttype         = KRB5_PW_SALT;
112193323Sed    salt.saltvalue.length = 0;
113193323Sed    salt.saltvalue.data   = NULL;
114193323Sed
115193323Sed    if (krb5_config_get_bool (context->context,
116193323Sed			      NULL, "kadmin", "use_v4_salt", NULL)) {
117239462Sdim	v4_salt = TRUE;
118239462Sdim    } else {
119239462Sdim	ret = krb5_get_pw_salt (context->context, ent->principal, &salt);
120239462Sdim	if (ret)
121239462Sdim	    goto out;
122239462Sdim    }
123239462Sdim
124239462Sdim    for (i = 0; i < n_des_types; ++i) {
125239462Sdim	ret = krb5_string_to_key_salt (context->context,
126239462Sdim				       des_types[i],
127239462Sdim				       password,
128239462Sdim				       salt,
129239462Sdim				       &keys[i].key);
130239462Sdim	if (ret)
131239462Sdim	    goto out;
132239462Sdim	if (v4_salt) {
133239462Sdim	    keys[i].salt = malloc (sizeof(*keys[i].salt));
134239462Sdim	    if (keys[i].salt == NULL) {
135239462Sdim		ret = ENOMEM;
136239462Sdim		goto out;
137239462Sdim	    }
138243830Sdim	    keys[i].salt->type = salt.salttype;
139239462Sdim	    ret = copy_octet_string (&salt.saltvalue, &keys[i].salt->salt);
140239462Sdim	    if (ret)
141239462Sdim		goto out;
142243830Sdim	}
143239462Sdim    }
144239462Sdim
145239462Sdim    ret = krb5_string_to_key (context->context,
146239462Sdim			      ETYPE_DES3_CBC_SHA1,
147239462Sdim			      password,
148239462Sdim			      ent->principal,
149239462Sdim			      &keys[n_des_types].key);
150239462Sdim    if (ret)
151239462Sdim	goto out;
152239462Sdim
153239462Sdim    free_keys (context, ent->keys.len, ent->keys.val);
154239462Sdim    ent->keys.len = len;
155239462Sdim    ent->keys.val = keys;
156239462Sdim    ent->kvno++;
157239462Sdim    return ret;
158239462Sdimout:
159239462Sdim    krb5_data_free (&salt.saltvalue);
160239462Sdim    free_keys (context, len, keys);
161239462Sdim    return ret;
162239462Sdim}
163239462Sdim
164239462Sdim/*
165239462Sdim * Set the keys of `ent' to (`n_key_data', `key_data')
166239462Sdim */
167239462Sdim
168239462Sdimkadm5_ret_t
169239462Sdim_kadm5_set_keys2(hdb_entry *ent,
170239462Sdim		 int16_t n_key_data,
171239462Sdim		 krb5_key_data *key_data)
172239462Sdim{
173239462Sdim    krb5_error_code ret;
174239462Sdim    int i;
175239462Sdim
176239462Sdim    ent->keys.len = n_key_data;
177239462Sdim    ent->keys.val = malloc(ent->keys.len * sizeof(*ent->keys.val));
178239462Sdim    if(ent->keys.val == NULL)
179239462Sdim	return ENOMEM;
180239462Sdim    for(i = 0; i < n_key_data; i++) {
181239462Sdim	ent->keys.val[i].mkvno = NULL;
182239462Sdim	ent->keys.val[i].key.keytype = key_data[i].key_data_type[0];
183243830Sdim	ret = krb5_data_copy(&ent->keys.val[i].key.keyvalue,
184239462Sdim			     key_data[i].key_data_contents[0],
185239462Sdim			     key_data[i].key_data_length[0]);
186239462Sdim	if(ret)
187239462Sdim	    return ret;
188239462Sdim	if(key_data[i].key_data_ver == 2) {
189239462Sdim	    Salt *salt;
190239462Sdim	    salt = malloc(sizeof(*salt));
191239462Sdim	    if(salt == NULL)
192239462Sdim		return ENOMEM;
193239462Sdim	    ent->keys.val[i].salt = salt;
194239462Sdim	    salt->type = key_data[i].key_data_type[1];
195239462Sdim	    krb5_data_copy(&salt->salt,
196243830Sdim			   key_data[i].key_data_contents[1],
197243830Sdim			   key_data[i].key_data_length[1]);
198239462Sdim	} else
199239462Sdim	    ent->keys.val[i].salt = NULL;
200239462Sdim    }
201239462Sdim    ent->kvno++;
202239462Sdim    return 0;
203239462Sdim}
204239462Sdim
205239462Sdim/*
206239462Sdim * Set the keys of `ent' to random keys and return them in `n_keys'
207239462Sdim * and `new_keys'.
208239462Sdim */
209239462Sdim
210239462Sdimkadm5_ret_t
211218893Sdim_kadm5_set_keys_randomly (kadm5_server_context *context,
212218893Sdim			  hdb_entry *ent,
213243830Sdim			  krb5_keyblock **new_keys,
214239462Sdim			  int *n_keys)
215239462Sdim{
216239462Sdim    kadm5_ret_t ret = 0;
217243830Sdim    int i;
218239462Sdim    unsigned len;
219239462Sdim    krb5_keyblock *keys;
220239462Sdim    Key *hkeys;
221239462Sdim
222239462Sdim    len  = n_des_types + 1;
223239462Sdim    keys = malloc (len * sizeof(*keys));
224239462Sdim    if (keys == NULL)
225239462Sdim	return ENOMEM;
226239462Sdim
227239462Sdim    for (i = 0; i < len; ++i) {
228239462Sdim	keys[i].keyvalue.length = 0;
229239462Sdim	keys[i].keyvalue.data   = NULL;
230239462Sdim    }
231239462Sdim
232239462Sdim    hkeys = malloc (len * sizeof(*hkeys));
233239462Sdim    if (hkeys == NULL) {
234239462Sdim	free (keys);
235239462Sdim	return ENOMEM;
236239462Sdim    }
237239462Sdim
238239462Sdim    init_keys (hkeys, len);
239239462Sdim
240239462Sdim    ret = krb5_generate_random_keyblock (context->context,
241239462Sdim					 des_types[0],
242239462Sdim					 &keys[0]);
243239462Sdim    if (ret)
244239462Sdim	goto out;
245239462Sdim
246239462Sdim    ret = krb5_copy_keyblock_contents (context->context,
247239462Sdim				       &keys[0],
248239462Sdim				       &hkeys[0].key);
249239462Sdim    if (ret)
250239462Sdim	goto out;
251239462Sdim
252239462Sdim    for (i = 1; i < n_des_types; ++i) {
253239462Sdim	ret = krb5_copy_keyblock_contents (context->context,
254239462Sdim					   &keys[0],
255239462Sdim					   &keys[i]);
256239462Sdim	if (ret)
257239462Sdim	    goto out;
258239462Sdim	keys[i].keytype = des_types[i];
259239462Sdim	ret = krb5_copy_keyblock_contents (context->context,
260239462Sdim					   &keys[0],
261239462Sdim					   &hkeys[i].key);
262239462Sdim	if (ret)
263239462Sdim	    goto out;
264239462Sdim	hkeys[i].key.keytype = des_types[i];
265221345Sdim    }
266221345Sdim
267218893Sdim    ret = krb5_generate_random_keyblock (context->context,
268263508Sdim					 ETYPE_DES3_CBC_SHA1,
269218893Sdim					 &keys[n_des_types]);
270218893Sdim    if (ret)
271218893Sdim	goto out;
272218893Sdim
273263508Sdim    ret = krb5_copy_keyblock_contents (context->context,
274234353Sdim				       &keys[n_des_types],
275234353Sdim				       &hkeys[n_des_types].key);
276218893Sdim    if (ret)
277218893Sdim	goto out;
278218893Sdim
279263508Sdim    free_keys (context, ent->keys.len, ent->keys.val);
280263508Sdim    ent->keys.len = len;
281263508Sdim    ent->keys.val = hkeys;
282263508Sdim    ent->kvno++;
283263508Sdim    *new_keys     = keys;
284263508Sdim    *n_keys       = len;
285263508Sdim    return ret;
286263508Sdimout:
287263508Sdim    for (i = 0; i < len; ++i)
288263508Sdim	krb5_free_keyblock_contents (context->context, &keys[i]);
289263508Sdim    free (keys);
290263508Sdim    free_keys (context, len, hkeys);
291263508Sdim    return ret;
292263508Sdim}
293263508Sdim