]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - crypto/heimdal/lib/kadm5/set_keys.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / crypto / heimdal / lib / kadm5 / set_keys.c
1 /*
2  * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
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. 
16  *
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. 
20  *
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 
31  * SUCH DAMAGE. 
32  */
33
34 #include "kadm5_locl.h"
35
36 RCSID("$Id: set_keys.c 15888 2005-08-11 13:40:35Z lha $");
37
38 /*
39  * Set the keys of `ent' to the string-to-key of `password'
40  */
41
42 kadm5_ret_t
43 _kadm5_set_keys(kadm5_server_context *context,
44                 hdb_entry *ent, 
45                 const char *password)
46 {
47     Key *keys;
48     size_t num_keys;
49     kadm5_ret_t ret;
50
51     ret = hdb_generate_key_set_password(context->context,
52                                         ent->principal, 
53                                         password, &keys, &num_keys);
54     if (ret)
55         return ret;
56
57     _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
58     ent->keys.val = keys;
59     ent->keys.len = num_keys;
60
61     hdb_entry_set_pw_change_time(context->context, ent, 0);
62
63     if (krb5_config_get_bool_default(context->context, NULL, FALSE, 
64                                      "kadmin", "save-password", NULL))
65     {
66         ret = hdb_entry_set_password(context->context, context->db,
67                                      ent, password);
68         if (ret)
69             return ret;
70     }
71
72     return 0;
73 }
74
75 /*
76  * Set the keys of `ent' to (`n_key_data', `key_data')
77  */
78
79 kadm5_ret_t
80 _kadm5_set_keys2(kadm5_server_context *context,
81                  hdb_entry *ent, 
82                  int16_t n_key_data, 
83                  krb5_key_data *key_data)
84 {
85     krb5_error_code ret;
86     int i;
87     unsigned len;
88     Key *keys;
89
90     len  = n_key_data;
91     keys = malloc (len * sizeof(*keys));
92     if (keys == NULL)
93         return ENOMEM;
94
95     _kadm5_init_keys (keys, len);
96
97     for(i = 0; i < n_key_data; i++) {
98         keys[i].mkvno = NULL;
99         keys[i].key.keytype = key_data[i].key_data_type[0];
100         ret = krb5_data_copy(&keys[i].key.keyvalue,
101                              key_data[i].key_data_contents[0],
102                              key_data[i].key_data_length[0]);
103         if(ret)
104             goto out;
105         if(key_data[i].key_data_ver == 2) {
106             Salt *salt;
107
108             salt = malloc(sizeof(*salt));
109             if(salt == NULL) {
110                 ret = ENOMEM;
111                 goto out;
112             }
113             keys[i].salt = salt;
114             salt->type = key_data[i].key_data_type[1];
115             krb5_data_copy(&salt->salt, 
116                            key_data[i].key_data_contents[1],
117                            key_data[i].key_data_length[1]);
118         } else
119             keys[i].salt = NULL;
120     }
121     _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
122     ent->keys.len = len;
123     ent->keys.val = keys;
124
125     hdb_entry_set_pw_change_time(context->context, ent, 0);
126     hdb_entry_clear_password(context->context, ent);
127
128     return 0;
129  out:
130     _kadm5_free_keys (context->context, len, keys);
131     return ret;
132 }
133
134 /*
135  * Set the keys of `ent' to `n_keys, keys'
136  */
137
138 kadm5_ret_t
139 _kadm5_set_keys3(kadm5_server_context *context,
140                  hdb_entry *ent,
141                  int n_keys,
142                  krb5_keyblock *keyblocks)
143 {
144     krb5_error_code ret;
145     int i;
146     unsigned len;
147     Key *keys;
148
149     len  = n_keys;
150     keys = malloc (len * sizeof(*keys));
151     if (keys == NULL)
152         return ENOMEM;
153
154     _kadm5_init_keys (keys, len);
155
156     for(i = 0; i < n_keys; i++) {
157         keys[i].mkvno = NULL;
158         ret = krb5_copy_keyblock_contents (context->context,
159                                            &keyblocks[i],
160                                            &keys[i].key);
161         if(ret)
162             goto out;
163         keys[i].salt = NULL;
164     }
165     _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
166     ent->keys.len = len;
167     ent->keys.val = keys;
168
169     hdb_entry_set_pw_change_time(context->context, ent, 0);
170     hdb_entry_clear_password(context->context, ent);
171
172     return 0;
173  out:
174     _kadm5_free_keys (context->context, len, keys);
175     return ret;
176 }
177
178 /*
179  *
180  */
181
182 static int
183 is_des_key_p(int keytype)
184 {
185     return keytype == ETYPE_DES_CBC_CRC ||
186         keytype == ETYPE_DES_CBC_MD4 ||
187         keytype == ETYPE_DES_CBC_MD5;
188 }
189
190
191 /*
192  * Set the keys of `ent' to random keys and return them in `n_keys'
193  * and `new_keys'.
194  */
195
196 kadm5_ret_t
197 _kadm5_set_keys_randomly (kadm5_server_context *context,
198                           hdb_entry *ent,
199                           krb5_keyblock **new_keys,
200                           int *n_keys)
201 {
202    krb5_keyblock *kblock = NULL;
203    kadm5_ret_t ret = 0;
204    int i, des_keyblock;
205    size_t num_keys;
206    Key *keys;
207
208    ret = hdb_generate_key_set(context->context, ent->principal,
209                                &keys, &num_keys, 1);
210    if (ret)
211         return ret;
212
213    kblock = malloc(num_keys * sizeof(kblock[0]));
214    if (kblock == NULL) {
215         ret = ENOMEM;
216         _kadm5_free_keys (context->context, num_keys, keys);
217         return ret;
218    }
219    memset(kblock, 0, num_keys * sizeof(kblock[0]));
220
221    des_keyblock = -1;
222    for (i = 0; i < num_keys; i++) {
223
224         /* 
225          * To make sure all des keys are the the same we generate only
226          * the first one and then copy key to all other des keys.
227          */
228
229         if (des_keyblock != -1 && is_des_key_p(keys[i].key.keytype)) {
230             ret = krb5_copy_keyblock_contents (context->context,
231                                                &kblock[des_keyblock],
232                                                &kblock[i]);
233             if (ret)
234                 goto out;
235             kblock[i].keytype = keys[i].key.keytype;
236         } else {
237             ret = krb5_generate_random_keyblock (context->context,
238                                                  keys[i].key.keytype,
239                                                  &kblock[i]);
240             if (ret)
241                 goto out;
242
243             if (is_des_key_p(keys[i].key.keytype))
244                 des_keyblock = i;
245         }
246
247         ret = krb5_copy_keyblock_contents (context->context,
248                                            &kblock[i],
249                                            &keys[i].key);
250         if (ret)
251             goto out;
252    }
253
254 out:
255    if(ret) {
256         for (i = 0; i < num_keys; ++i)
257             krb5_free_keyblock_contents (context->context, &kblock[i]);
258         free(kblock);
259         _kadm5_free_keys (context->context, num_keys, keys);
260         return ret;
261    }
262    
263    _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
264    ent->keys.val = keys;
265    ent->keys.len = num_keys;
266    *new_keys     = kblock;
267    *n_keys       = num_keys;
268
269    hdb_entry_set_pw_change_time(context->context, ent, 0);
270    hdb_entry_clear_password(context->context, ent);
271
272    return 0;
273 }