1 /* $NetBSD: set_keys.c,v 1.1.1.2 2014/04/24 12:45:49 pettai Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "kadm5_locl.h" 37 38 __RCSID("NetBSD"); 39 40 /* 41 * Set the keys of `ent' to the string-to-key of `password' 42 */ 43 44 kadm5_ret_t 45 _kadm5_set_keys(kadm5_server_context *context, 46 hdb_entry *ent, 47 const char *password) 48 { 49 Key *keys; 50 size_t num_keys; 51 kadm5_ret_t ret; 52 53 ret = hdb_generate_key_set_password(context->context, 54 ent->principal, 55 password, &keys, &num_keys); 56 if (ret) 57 return ret; 58 59 _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val); 60 ent->keys.val = keys; 61 ent->keys.len = num_keys; 62 63 hdb_entry_set_pw_change_time(context->context, ent, 0); 64 65 if (krb5_config_get_bool_default(context->context, NULL, FALSE, 66 "kadmin", "save-password", NULL)) 67 { 68 ret = hdb_entry_set_password(context->context, context->db, 69 ent, password); 70 if (ret) 71 return ret; 72 } 73 74 return 0; 75 } 76 77 /* 78 * Set the keys of `ent' to (`n_key_data', `key_data') 79 */ 80 81 kadm5_ret_t 82 _kadm5_set_keys2(kadm5_server_context *context, 83 hdb_entry *ent, 84 int16_t n_key_data, 85 krb5_key_data *key_data) 86 { 87 krb5_error_code ret; 88 int i; 89 unsigned len; 90 Key *keys; 91 92 len = n_key_data; 93 keys = malloc (len * sizeof(*keys)); 94 if (keys == NULL && len != 0) 95 return ENOMEM; 96 97 _kadm5_init_keys (keys, len); 98 99 for(i = 0; i < n_key_data; i++) { 100 keys[i].mkvno = NULL; 101 keys[i].key.keytype = key_data[i].key_data_type[0]; 102 ret = krb5_data_copy(&keys[i].key.keyvalue, 103 key_data[i].key_data_contents[0], 104 key_data[i].key_data_length[0]); 105 if(ret) 106 goto out; 107 if(key_data[i].key_data_ver == 2) { 108 Salt *salt; 109 110 salt = calloc(1, sizeof(*salt)); 111 if(salt == NULL) { 112 ret = ENOMEM; 113 goto out; 114 } 115 keys[i].salt = salt; 116 salt->type = key_data[i].key_data_type[1]; 117 krb5_data_copy(&salt->salt, 118 key_data[i].key_data_contents[1], 119 key_data[i].key_data_length[1]); 120 } else 121 keys[i].salt = NULL; 122 } 123 _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val); 124 ent->keys.len = len; 125 ent->keys.val = keys; 126 127 hdb_entry_set_pw_change_time(context->context, ent, 0); 128 hdb_entry_clear_password(context->context, ent); 129 130 return 0; 131 out: 132 _kadm5_free_keys (context->context, len, keys); 133 return ret; 134 } 135 136 /* 137 * Set the keys of `ent' to `n_keys, keys' 138 */ 139 140 kadm5_ret_t 141 _kadm5_set_keys3(kadm5_server_context *context, 142 hdb_entry *ent, 143 int n_keys, 144 krb5_keyblock *keyblocks) 145 { 146 krb5_error_code ret; 147 int i; 148 unsigned len; 149 Key *keys; 150 151 len = n_keys; 152 keys = malloc (len * sizeof(*keys)); 153 if (keys == NULL && len != 0) 154 return ENOMEM; 155 156 _kadm5_init_keys (keys, len); 157 158 for(i = 0; i < n_keys; i++) { 159 keys[i].mkvno = NULL; 160 ret = krb5_copy_keyblock_contents (context->context, 161 &keyblocks[i], 162 &keys[i].key); 163 if(ret) 164 goto out; 165 keys[i].salt = NULL; 166 } 167 _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val); 168 ent->keys.len = len; 169 ent->keys.val = keys; 170 171 hdb_entry_set_pw_change_time(context->context, ent, 0); 172 hdb_entry_clear_password(context->context, ent); 173 174 return 0; 175 out: 176 _kadm5_free_keys (context->context, len, keys); 177 return ret; 178 } 179 180 /* 181 * 182 */ 183 184 static int 185 is_des_key_p(int keytype) 186 { 187 return keytype == ETYPE_DES_CBC_CRC || 188 keytype == ETYPE_DES_CBC_MD4 || 189 keytype == ETYPE_DES_CBC_MD5; 190 } 191 192 193 /* 194 * Set the keys of `ent' to random keys and return them in `n_keys' 195 * and `new_keys'. 196 */ 197 198 kadm5_ret_t 199 _kadm5_set_keys_randomly (kadm5_server_context *context, 200 hdb_entry *ent, 201 krb5_keyblock **new_keys, 202 int *n_keys) 203 { 204 krb5_keyblock *kblock = NULL; 205 kadm5_ret_t ret = 0; 206 int des_keyblock; 207 size_t i, num_keys; 208 Key *keys; 209 210 ret = hdb_generate_key_set(context->context, ent->principal, 211 &keys, &num_keys, 1); 212 if (ret) 213 return ret; 214 215 kblock = malloc(num_keys * sizeof(kblock[0])); 216 if (kblock == NULL) { 217 ret = ENOMEM; 218 _kadm5_free_keys (context->context, num_keys, keys); 219 return ret; 220 } 221 memset(kblock, 0, num_keys * sizeof(kblock[0])); 222 223 des_keyblock = -1; 224 for (i = 0; i < num_keys; i++) { 225 226 /* 227 * To make sure all des keys are the the same we generate only 228 * the first one and then copy key to all other des keys. 229 */ 230 231 if (des_keyblock != -1 && is_des_key_p(keys[i].key.keytype)) { 232 ret = krb5_copy_keyblock_contents (context->context, 233 &kblock[des_keyblock], 234 &kblock[i]); 235 if (ret) 236 goto out; 237 kblock[i].keytype = keys[i].key.keytype; 238 } else { 239 ret = krb5_generate_random_keyblock (context->context, 240 keys[i].key.keytype, 241 &kblock[i]); 242 if (ret) 243 goto out; 244 245 if (is_des_key_p(keys[i].key.keytype)) 246 des_keyblock = i; 247 } 248 249 ret = krb5_copy_keyblock_contents (context->context, 250 &kblock[i], 251 &keys[i].key); 252 if (ret) 253 goto out; 254 } 255 256 out: 257 if(ret) { 258 for (i = 0; i < num_keys; ++i) 259 krb5_free_keyblock_contents (context->context, &kblock[i]); 260 free(kblock); 261 _kadm5_free_keys (context->context, num_keys, keys); 262 return ret; 263 } 264 265 _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val); 266 ent->keys.val = keys; 267 ent->keys.len = num_keys; 268 *new_keys = kblock; 269 *n_keys = num_keys; 270 271 hdb_entry_set_pw_change_time(context->context, ent, 0); 272 hdb_entry_clear_password(context->context, ent); 273 274 return 0; 275 } 276