155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2006 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 38178825Sdfrstatic kadm5_ret_t 39233294Sstasadd_tl_data(kadm5_principal_ent_t ent, int16_t type, 40178825Sdfr const void *data, size_t size) 41178825Sdfr{ 42178825Sdfr krb5_tl_data *tl; 43178825Sdfr 44178825Sdfr tl = calloc(1, sizeof(*tl)); 45178825Sdfr if (tl == NULL) 46178825Sdfr return _kadm5_error_code(ENOMEM); 47178825Sdfr 48178825Sdfr tl->tl_data_type = type; 49178825Sdfr tl->tl_data_length = size; 50178825Sdfr tl->tl_data_contents = malloc(size); 51233294Sstas if (tl->tl_data_contents == NULL && size != 0) { 52178825Sdfr free(tl); 53178825Sdfr return _kadm5_error_code(ENOMEM); 54178825Sdfr } 55178825Sdfr memcpy(tl->tl_data_contents, data, size); 56178825Sdfr 57178825Sdfr tl->tl_data_next = ent->tl_data; 58178825Sdfr ent->tl_data = tl; 59178825Sdfr ent->n_tl_data++; 60178825Sdfr 61178825Sdfr return 0; 62178825Sdfr} 63178825Sdfr 64233294SstasKRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL 65178825Sdfr_krb5_put_int(void *buffer, unsigned long value, size_t size); /* XXX */ 66178825Sdfr 6755682Smarkmkadm5_ret_t 68233294Sstaskadm5_s_get_principal(void *server_handle, 69233294Sstas krb5_principal princ, 70233294Sstas kadm5_principal_ent_t out, 71178825Sdfr uint32_t mask) 7255682Smarkm{ 7355682Smarkm kadm5_server_context *context = server_handle; 7455682Smarkm kadm5_ret_t ret; 75178825Sdfr hdb_entry_ex ent; 76233294Sstas 77178825Sdfr memset(&ent, 0, sizeof(ent)); 78178825Sdfr ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0); 7955682Smarkm if(ret) 8055682Smarkm return ret; 81233294Sstas ret = context->db->hdb_fetch_kvno(context->context, context->db, princ, 82233294Sstas HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent); 83178825Sdfr context->db->hdb_close(context->context, context->db); 8455682Smarkm if(ret) 8555682Smarkm return _kadm5_error_code(ret); 8655682Smarkm 8755682Smarkm memset(out, 0, sizeof(*out)); 8855682Smarkm if(mask & KADM5_PRINCIPAL) 89233294Sstas ret = krb5_copy_principal(context->context, ent.entry.principal, 9055682Smarkm &out->principal); 9155682Smarkm if(ret) 9255682Smarkm goto out; 93178825Sdfr if(mask & KADM5_PRINC_EXPIRE_TIME && ent.entry.valid_end) 94178825Sdfr out->princ_expire_time = *ent.entry.valid_end; 95178825Sdfr if(mask & KADM5_PW_EXPIRATION && ent.entry.pw_end) 96178825Sdfr out->pw_expiration = *ent.entry.pw_end; 9755682Smarkm if(mask & KADM5_LAST_PWD_CHANGE) 98178825Sdfr hdb_entry_get_pw_change_time(&ent.entry, &out->last_pwd_change); 9955682Smarkm if(mask & KADM5_ATTRIBUTES){ 100178825Sdfr out->attributes |= ent.entry.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED; 101178825Sdfr out->attributes |= ent.entry.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE; 102178825Sdfr out->attributes |= ent.entry.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0; 103178825Sdfr out->attributes |= ent.entry.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE; 104178825Sdfr out->attributes |= ent.entry.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE; 105178825Sdfr out->attributes |= ent.entry.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0; 106178825Sdfr out->attributes |= ent.entry.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0; 107178825Sdfr out->attributes |= ent.entry.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR; 108178825Sdfr out->attributes |= ent.entry.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0; 109178825Sdfr out->attributes |= ent.entry.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0; 110178825Sdfr out->attributes |= ent.entry.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0; 111178825Sdfr out->attributes |= ent.entry.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0; 112178825Sdfr out->attributes |= ent.entry.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0; 11355682Smarkm } 11472445Sassar if(mask & KADM5_MAX_LIFE) { 115178825Sdfr if(ent.entry.max_life) 116178825Sdfr out->max_life = *ent.entry.max_life; 11772445Sassar else 11872445Sassar out->max_life = INT_MAX; 11972445Sassar } 12055682Smarkm if(mask & KADM5_MOD_TIME) { 121178825Sdfr if(ent.entry.modified_by) 122178825Sdfr out->mod_date = ent.entry.modified_by->time; 12355682Smarkm else 124178825Sdfr out->mod_date = ent.entry.created_by.time; 12555682Smarkm } 12655682Smarkm if(mask & KADM5_MOD_NAME) { 127178825Sdfr if(ent.entry.modified_by) { 128178825Sdfr if (ent.entry.modified_by->principal != NULL) 129233294Sstas ret = krb5_copy_principal(context->context, 130178825Sdfr ent.entry.modified_by->principal, 13155682Smarkm &out->mod_name); 132178825Sdfr } else if(ent.entry.created_by.principal != NULL) 133233294Sstas ret = krb5_copy_principal(context->context, 134178825Sdfr ent.entry.created_by.principal, 13555682Smarkm &out->mod_name); 13672445Sassar else 13772445Sassar out->mod_name = NULL; 13855682Smarkm } 13955682Smarkm if(ret) 14055682Smarkm goto out; 14155682Smarkm 14255682Smarkm if(mask & KADM5_KVNO) 143178825Sdfr out->kvno = ent.entry.kvno; 14455682Smarkm if(mask & KADM5_MKVNO) { 145233294Sstas size_t n; 14655682Smarkm out->mkvno = 0; /* XXX */ 147178825Sdfr for(n = 0; n < ent.entry.keys.len; n++) 148178825Sdfr if(ent.entry.keys.val[n].mkvno) { 149178825Sdfr out->mkvno = *ent.entry.keys.val[n].mkvno; /* XXX this isn't right */ 15055682Smarkm break; 15155682Smarkm } 15255682Smarkm } 153233294Sstas#if 0 /* XXX implement */ 15455682Smarkm if(mask & KADM5_AUX_ATTRIBUTES) 155233294Sstas ; 156233294Sstas if(mask & KADM5_LAST_SUCCESS) 157233294Sstas ; 158233294Sstas if(mask & KADM5_LAST_FAILED) 159233294Sstas ; 160233294Sstas if(mask & KADM5_FAIL_AUTH_COUNT) 161233294Sstas ; 162233294Sstas#endif 16355682Smarkm if(mask & KADM5_POLICY) 16455682Smarkm out->policy = NULL; 16572445Sassar if(mask & KADM5_MAX_RLIFE) { 166178825Sdfr if(ent.entry.max_renew) 167178825Sdfr out->max_renewable_life = *ent.entry.max_renew; 16872445Sassar else 16972445Sassar out->max_renewable_life = INT_MAX; 17072445Sassar } 17155682Smarkm if(mask & KADM5_KEY_DATA){ 172233294Sstas size_t i; 17355682Smarkm Key *key; 17455682Smarkm krb5_key_data *kd; 17555682Smarkm krb5_salt salt; 17655682Smarkm krb5_data *sp; 177178825Sdfr krb5_get_pw_salt(context->context, ent.entry.principal, &salt); 178178825Sdfr out->key_data = malloc(ent.entry.keys.len * sizeof(*out->key_data)); 179233294Sstas if (out->key_data == NULL && ent.entry.keys.len != 0) { 180178825Sdfr ret = ENOMEM; 181178825Sdfr goto out; 182178825Sdfr } 183178825Sdfr for(i = 0; i < ent.entry.keys.len; i++){ 184178825Sdfr key = &ent.entry.keys.val[i]; 18555682Smarkm kd = &out->key_data[i]; 18655682Smarkm kd->key_data_ver = 2; 187178825Sdfr kd->key_data_kvno = ent.entry.kvno; 18855682Smarkm kd->key_data_type[0] = key->key.keytype; 18955682Smarkm if(key->salt) 19055682Smarkm kd->key_data_type[1] = key->salt->type; 19155682Smarkm else 19272445Sassar kd->key_data_type[1] = KRB5_PADATA_PW_SALT; 19355682Smarkm /* setup key */ 19455682Smarkm kd->key_data_length[0] = key->key.keyvalue.length; 19555682Smarkm kd->key_data_contents[0] = malloc(kd->key_data_length[0]); 196233294Sstas if(kd->key_data_contents[0] == NULL && kd->key_data_length[0] != 0){ 19755682Smarkm ret = ENOMEM; 19855682Smarkm break; 19955682Smarkm } 200233294Sstas memcpy(kd->key_data_contents[0], key->key.keyvalue.data, 20155682Smarkm kd->key_data_length[0]); 20255682Smarkm /* setup salt */ 20355682Smarkm if(key->salt) 20455682Smarkm sp = &key->salt->salt; 20555682Smarkm else 20655682Smarkm sp = &salt.saltvalue; 20755682Smarkm kd->key_data_length[1] = sp->length; 20855682Smarkm kd->key_data_contents[1] = malloc(kd->key_data_length[1]); 20955682Smarkm if(kd->key_data_length[1] != 0 21055682Smarkm && kd->key_data_contents[1] == NULL) { 21155682Smarkm memset(kd->key_data_contents[0], 0, kd->key_data_length[0]); 21255682Smarkm ret = ENOMEM; 21355682Smarkm break; 21455682Smarkm } 21555682Smarkm memcpy(kd->key_data_contents[1], sp->data, kd->key_data_length[1]); 21655682Smarkm out->n_key_data = i + 1; 21755682Smarkm } 21855682Smarkm krb5_free_salt(context->context, salt); 21955682Smarkm } 22055682Smarkm if(ret){ 22155682Smarkm kadm5_free_principal_ent(context, out); 22255682Smarkm goto out; 22355682Smarkm } 224178825Sdfr if(mask & KADM5_TL_DATA) { 225178825Sdfr time_t last_pw_expire; 226233294Sstas const HDB_Ext_PKINIT_acl *acl; 227178825Sdfr const HDB_Ext_Aliases *aliases; 228178825Sdfr 229178825Sdfr ret = hdb_entry_get_pw_change_time(&ent.entry, &last_pw_expire); 230178825Sdfr if (ret == 0 && last_pw_expire) { 231178825Sdfr unsigned char buf[4]; 232178825Sdfr _krb5_put_int(buf, last_pw_expire, sizeof(buf)); 233178825Sdfr ret = add_tl_data(out, KRB5_TL_LAST_PWD_CHANGE, buf, sizeof(buf)); 234178825Sdfr } 235178825Sdfr if(ret){ 236178825Sdfr kadm5_free_principal_ent(context, out); 237178825Sdfr goto out; 238178825Sdfr } 239233294Sstas /* 240178825Sdfr * If the client was allowed to get key data, let it have the 241178825Sdfr * password too. 242178825Sdfr */ 243178825Sdfr if(mask & KADM5_KEY_DATA) { 244178825Sdfr heim_utf8_string pw; 245178825Sdfr 246233294Sstas ret = hdb_entry_get_password(context->context, 247178825Sdfr context->db, &ent.entry, &pw); 248178825Sdfr if (ret == 0) { 249178825Sdfr ret = add_tl_data(out, KRB5_TL_PASSWORD, pw, strlen(pw) + 1); 250178825Sdfr free(pw); 251178825Sdfr } 252233294Sstas krb5_clear_error_message(context->context); 253178825Sdfr } 254178825Sdfr 255233294Sstas ret = hdb_entry_get_pkinit_acl(&ent.entry, &acl); 256233294Sstas if (ret == 0 && acl) { 257233294Sstas krb5_data buf; 258233294Sstas size_t len; 259233294Sstas 260233294Sstas ASN1_MALLOC_ENCODE(HDB_Ext_PKINIT_acl, buf.data, buf.length, 261233294Sstas acl, &len, ret); 262233294Sstas if (ret) { 263233294Sstas kadm5_free_principal_ent(context, out); 264233294Sstas goto out; 265233294Sstas } 266233294Sstas if (len != buf.length) 267233294Sstas krb5_abortx(context->context, 268233294Sstas "internal ASN.1 encoder error"); 269233294Sstas ret = add_tl_data(out, KRB5_TL_PKINIT_ACL, buf.data, buf.length); 270233294Sstas free(buf.data); 271233294Sstas if (ret) { 272233294Sstas kadm5_free_principal_ent(context, out); 273233294Sstas goto out; 274233294Sstas } 275233294Sstas } 276233294Sstas if(ret){ 277233294Sstas kadm5_free_principal_ent(context, out); 278233294Sstas goto out; 279233294Sstas } 280233294Sstas 281178825Sdfr ret = hdb_entry_get_aliases(&ent.entry, &aliases); 282178825Sdfr if (ret == 0 && aliases) { 283178825Sdfr krb5_data buf; 284178825Sdfr size_t len; 285178825Sdfr 286178825Sdfr ASN1_MALLOC_ENCODE(HDB_Ext_Aliases, buf.data, buf.length, 287178825Sdfr aliases, &len, ret); 288178825Sdfr if (ret) { 289178825Sdfr kadm5_free_principal_ent(context, out); 290178825Sdfr goto out; 291178825Sdfr } 292178825Sdfr if (len != buf.length) 293178825Sdfr krb5_abortx(context->context, 294178825Sdfr "internal ASN.1 encoder error"); 295178825Sdfr ret = add_tl_data(out, KRB5_TL_ALIASES, buf.data, buf.length); 296178825Sdfr free(buf.data); 297178825Sdfr if (ret) { 298178825Sdfr kadm5_free_principal_ent(context, out); 299178825Sdfr goto out; 300178825Sdfr } 301178825Sdfr } 302178825Sdfr if(ret){ 303178825Sdfr kadm5_free_principal_ent(context, out); 304178825Sdfr goto out; 305178825Sdfr } 306178825Sdfr 307178825Sdfr } 30855682Smarkmout: 30955682Smarkm hdb_free_entry(context->context, &ent); 31055682Smarkm 31155682Smarkm return _kadm5_error_code(ret); 31255682Smarkm} 313