155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadm5_locl.h" 3555682Smarkm 36233294SstasRCSID("$Id$"); 3755682Smarkm 3855682Smarkm/* 3972445Sassar * Set the keys of `ent' to the string-to-key of `password' 4072445Sassar */ 4172445Sassar 4272445Sassarkadm5_ret_t 4372445Sassar_kadm5_set_keys(kadm5_server_context *context, 44233294Sstas hdb_entry *ent, 4572445Sassar const char *password) 4672445Sassar{ 4772445Sassar Key *keys; 4872445Sassar size_t num_keys; 49178825Sdfr kadm5_ret_t ret; 5072445Sassar 51178825Sdfr ret = hdb_generate_key_set_password(context->context, 52233294Sstas ent->principal, 53178825Sdfr password, &keys, &num_keys); 54178825Sdfr if (ret) 55178825Sdfr return ret; 5672445Sassar 57178825Sdfr _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val); 5855682Smarkm ent->keys.val = keys; 5972445Sassar ent->keys.len = num_keys; 60178825Sdfr 61178825Sdfr hdb_entry_set_pw_change_time(context->context, ent, 0); 62178825Sdfr 63233294Sstas if (krb5_config_get_bool_default(context->context, NULL, FALSE, 64178825Sdfr "kadmin", "save-password", NULL)) 65178825Sdfr { 66178825Sdfr ret = hdb_entry_set_password(context->context, context->db, 67178825Sdfr ent, password); 68178825Sdfr if (ret) 69178825Sdfr return ret; 70178825Sdfr } 71178825Sdfr 7272445Sassar return 0; 7355682Smarkm} 7455682Smarkm 7555682Smarkm/* 7655682Smarkm * Set the keys of `ent' to (`n_key_data', `key_data') 7755682Smarkm */ 7855682Smarkm 7955682Smarkmkadm5_ret_t 8072445Sassar_kadm5_set_keys2(kadm5_server_context *context, 81233294Sstas hdb_entry *ent, 82233294Sstas int16_t n_key_data, 8355682Smarkm krb5_key_data *key_data) 8455682Smarkm{ 8555682Smarkm krb5_error_code ret; 8655682Smarkm int i; 8772445Sassar unsigned len; 8872445Sassar Key *keys; 8955682Smarkm 9072445Sassar len = n_key_data; 9172445Sassar keys = malloc (len * sizeof(*keys)); 92233294Sstas if (keys == NULL && len != 0) 9355682Smarkm return ENOMEM; 9472445Sassar 9572445Sassar _kadm5_init_keys (keys, len); 9672445Sassar 9755682Smarkm for(i = 0; i < n_key_data; i++) { 9872445Sassar keys[i].mkvno = NULL; 9972445Sassar keys[i].key.keytype = key_data[i].key_data_type[0]; 10072445Sassar ret = krb5_data_copy(&keys[i].key.keyvalue, 10155682Smarkm key_data[i].key_data_contents[0], 10255682Smarkm key_data[i].key_data_length[0]); 10355682Smarkm if(ret) 10472445Sassar goto out; 10555682Smarkm if(key_data[i].key_data_ver == 2) { 10655682Smarkm Salt *salt; 10772445Sassar 108233294Sstas salt = calloc(1, sizeof(*salt)); 10972445Sassar if(salt == NULL) { 11072445Sassar ret = ENOMEM; 11172445Sassar goto out; 11272445Sassar } 11372445Sassar keys[i].salt = salt; 11455682Smarkm salt->type = key_data[i].key_data_type[1]; 115233294Sstas krb5_data_copy(&salt->salt, 11655682Smarkm key_data[i].key_data_contents[1], 11755682Smarkm key_data[i].key_data_length[1]); 11855682Smarkm } else 11972445Sassar keys[i].salt = NULL; 12055682Smarkm } 121178825Sdfr _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val); 12272445Sassar ent->keys.len = len; 12372445Sassar ent->keys.val = keys; 124178825Sdfr 125178825Sdfr hdb_entry_set_pw_change_time(context->context, ent, 0); 126178825Sdfr hdb_entry_clear_password(context->context, ent); 127178825Sdfr 12855682Smarkm return 0; 12972445Sassar out: 130178825Sdfr _kadm5_free_keys (context->context, len, keys); 13172445Sassar return ret; 13255682Smarkm} 13355682Smarkm 13455682Smarkm/* 13572445Sassar * Set the keys of `ent' to `n_keys, keys' 13672445Sassar */ 13772445Sassar 13872445Sassarkadm5_ret_t 13972445Sassar_kadm5_set_keys3(kadm5_server_context *context, 14072445Sassar hdb_entry *ent, 14172445Sassar int n_keys, 14272445Sassar krb5_keyblock *keyblocks) 14372445Sassar{ 14472445Sassar krb5_error_code ret; 14572445Sassar int i; 14672445Sassar unsigned len; 14772445Sassar Key *keys; 14872445Sassar 14972445Sassar len = n_keys; 15072445Sassar keys = malloc (len * sizeof(*keys)); 151233294Sstas if (keys == NULL && len != 0) 15272445Sassar return ENOMEM; 15372445Sassar 15472445Sassar _kadm5_init_keys (keys, len); 15572445Sassar 15672445Sassar for(i = 0; i < n_keys; i++) { 15772445Sassar keys[i].mkvno = NULL; 15872445Sassar ret = krb5_copy_keyblock_contents (context->context, 15972445Sassar &keyblocks[i], 16072445Sassar &keys[i].key); 16172445Sassar if(ret) 16272445Sassar goto out; 16372445Sassar keys[i].salt = NULL; 16472445Sassar } 165178825Sdfr _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val); 16672445Sassar ent->keys.len = len; 16772445Sassar ent->keys.val = keys; 168178825Sdfr 169178825Sdfr hdb_entry_set_pw_change_time(context->context, ent, 0); 170178825Sdfr hdb_entry_clear_password(context->context, ent); 171178825Sdfr 17272445Sassar return 0; 17372445Sassar out: 174178825Sdfr _kadm5_free_keys (context->context, len, keys); 17572445Sassar return ret; 17672445Sassar} 17772445Sassar 17872445Sassar/* 179178825Sdfr * 180178825Sdfr */ 181178825Sdfr 182178825Sdfrstatic int 183178825Sdfris_des_key_p(int keytype) 184178825Sdfr{ 185178825Sdfr return keytype == ETYPE_DES_CBC_CRC || 186178825Sdfr keytype == ETYPE_DES_CBC_MD4 || 187178825Sdfr keytype == ETYPE_DES_CBC_MD5; 188178825Sdfr} 189178825Sdfr 190178825Sdfr 191178825Sdfr/* 19255682Smarkm * Set the keys of `ent' to random keys and return them in `n_keys' 19355682Smarkm * and `new_keys'. 19455682Smarkm */ 19555682Smarkm 19655682Smarkmkadm5_ret_t 19755682Smarkm_kadm5_set_keys_randomly (kadm5_server_context *context, 19855682Smarkm hdb_entry *ent, 19955682Smarkm krb5_keyblock **new_keys, 20055682Smarkm int *n_keys) 20155682Smarkm{ 202178825Sdfr krb5_keyblock *kblock = NULL; 203178825Sdfr kadm5_ret_t ret = 0; 204233294Sstas int des_keyblock; 205233294Sstas size_t i, num_keys; 206178825Sdfr Key *keys; 20755682Smarkm 208178825Sdfr ret = hdb_generate_key_set(context->context, ent->principal, 209178825Sdfr &keys, &num_keys, 1); 210178825Sdfr if (ret) 211178825Sdfr return ret; 21255682Smarkm 213178825Sdfr kblock = malloc(num_keys * sizeof(kblock[0])); 214178825Sdfr if (kblock == NULL) { 215178825Sdfr ret = ENOMEM; 216178825Sdfr _kadm5_free_keys (context->context, num_keys, keys); 217178825Sdfr return ret; 218178825Sdfr } 219178825Sdfr memset(kblock, 0, num_keys * sizeof(kblock[0])); 22055682Smarkm 221178825Sdfr des_keyblock = -1; 222178825Sdfr for (i = 0; i < num_keys; i++) { 22355682Smarkm 224233294Sstas /* 225178825Sdfr * To make sure all des keys are the the same we generate only 226178825Sdfr * the first one and then copy key to all other des keys. 227178825Sdfr */ 22855682Smarkm 229178825Sdfr if (des_keyblock != -1 && is_des_key_p(keys[i].key.keytype)) { 230178825Sdfr ret = krb5_copy_keyblock_contents (context->context, 231178825Sdfr &kblock[des_keyblock], 232178825Sdfr &kblock[i]); 233178825Sdfr if (ret) 234178825Sdfr goto out; 235178825Sdfr kblock[i].keytype = keys[i].key.keytype; 236178825Sdfr } else { 237178825Sdfr ret = krb5_generate_random_keyblock (context->context, 238178825Sdfr keys[i].key.keytype, 239178825Sdfr &kblock[i]); 240178825Sdfr if (ret) 241178825Sdfr goto out; 24255682Smarkm 243178825Sdfr if (is_des_key_p(keys[i].key.keytype)) 244178825Sdfr des_keyblock = i; 245178825Sdfr } 24655682Smarkm 24755682Smarkm ret = krb5_copy_keyblock_contents (context->context, 248178825Sdfr &kblock[i], 249178825Sdfr &keys[i].key); 25055682Smarkm if (ret) 25155682Smarkm goto out; 252178825Sdfr } 25355682Smarkm 254178825Sdfrout: 255178825Sdfr if(ret) { 256178825Sdfr for (i = 0; i < num_keys; ++i) 257178825Sdfr krb5_free_keyblock_contents (context->context, &kblock[i]); 258178825Sdfr free(kblock); 259178825Sdfr _kadm5_free_keys (context->context, num_keys, keys); 260178825Sdfr return ret; 261178825Sdfr } 262233294Sstas 263178825Sdfr _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val); 264178825Sdfr ent->keys.val = keys; 265178825Sdfr ent->keys.len = num_keys; 266178825Sdfr *new_keys = kblock; 267178825Sdfr *n_keys = num_keys; 26855682Smarkm 269178825Sdfr hdb_entry_set_pw_change_time(context->context, ent, 0); 270178825Sdfr hdb_entry_clear_password(context->context, ent); 27155682Smarkm 272178825Sdfr return 0; 27355682Smarkm} 274