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$"); 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 && len != 0) 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 = calloc(1, 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 && len != 0) 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 des_keyblock; 205 size_t i, 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 } 274