Home | History | Annotate | Line # | Download | only in kadm5
get_s.c revision 1.1.1.1.4.1
      1 /*	$NetBSD: get_s.c,v 1.1.1.1.4.1 2014/05/22 13:21:27 yamt Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 - 2006 Kungliga Tekniska Hgskolan
      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 static kadm5_ret_t
     41 add_tl_data(kadm5_principal_ent_t ent, int16_t type,
     42 	    const void *data, size_t size)
     43 {
     44     krb5_tl_data *tl;
     45 
     46     tl = calloc(1, sizeof(*tl));
     47     if (tl == NULL)
     48 	return _kadm5_error_code(ENOMEM);
     49 
     50     tl->tl_data_type = type;
     51     tl->tl_data_length = size;
     52     tl->tl_data_contents = malloc(size);
     53     if (tl->tl_data_contents == NULL && size != 0) {
     54 	free(tl);
     55 	return _kadm5_error_code(ENOMEM);
     56     }
     57     memcpy(tl->tl_data_contents, data, size);
     58 
     59     tl->tl_data_next = ent->tl_data;
     60     ent->tl_data = tl;
     61     ent->n_tl_data++;
     62 
     63     return 0;
     64 }
     65 
     66 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
     67 _krb5_put_int(void *buffer, unsigned long value, size_t size); /* XXX */
     68 
     69 kadm5_ret_t
     70 kadm5_s_get_principal(void *server_handle,
     71 		      krb5_principal princ,
     72 		      kadm5_principal_ent_t out,
     73 		      uint32_t mask)
     74 {
     75     kadm5_server_context *context = server_handle;
     76     kadm5_ret_t ret;
     77     hdb_entry_ex ent;
     78 
     79     memset(&ent, 0, sizeof(ent));
     80     ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
     81     if(ret)
     82 	return ret;
     83     ret = context->db->hdb_fetch_kvno(context->context, context->db, princ,
     84 				      HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent);
     85     context->db->hdb_close(context->context, context->db);
     86     if(ret)
     87 	return _kadm5_error_code(ret);
     88 
     89     memset(out, 0, sizeof(*out));
     90     if(mask & KADM5_PRINCIPAL)
     91 	ret  = krb5_copy_principal(context->context, ent.entry.principal,
     92 				   &out->principal);
     93     if(ret)
     94 	goto out;
     95     if(mask & KADM5_PRINC_EXPIRE_TIME && ent.entry.valid_end)
     96 	out->princ_expire_time = *ent.entry.valid_end;
     97     if(mask & KADM5_PW_EXPIRATION && ent.entry.pw_end)
     98 	out->pw_expiration = *ent.entry.pw_end;
     99     if(mask & KADM5_LAST_PWD_CHANGE)
    100 	hdb_entry_get_pw_change_time(&ent.entry, &out->last_pwd_change);
    101     if(mask & KADM5_ATTRIBUTES){
    102 	out->attributes |= ent.entry.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED;
    103 	out->attributes |= ent.entry.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE;
    104 	out->attributes |= ent.entry.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0;
    105 	out->attributes |= ent.entry.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE;
    106 	out->attributes |= ent.entry.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE;
    107 	out->attributes |= ent.entry.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0;
    108 	out->attributes |= ent.entry.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0;
    109 	out->attributes |= ent.entry.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR;
    110 	out->attributes |= ent.entry.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0;
    111 	out->attributes |= ent.entry.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0;
    112 	out->attributes |= ent.entry.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0;
    113 	out->attributes |= ent.entry.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0;
    114 	out->attributes |= ent.entry.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0;
    115     }
    116     if(mask & KADM5_MAX_LIFE) {
    117 	if(ent.entry.max_life)
    118 	    out->max_life = *ent.entry.max_life;
    119 	else
    120 	    out->max_life = INT_MAX;
    121     }
    122     if(mask & KADM5_MOD_TIME) {
    123 	if(ent.entry.modified_by)
    124 	    out->mod_date = ent.entry.modified_by->time;
    125 	else
    126 	    out->mod_date = ent.entry.created_by.time;
    127     }
    128     if(mask & KADM5_MOD_NAME) {
    129 	if(ent.entry.modified_by) {
    130 	    if (ent.entry.modified_by->principal != NULL)
    131 		ret = krb5_copy_principal(context->context,
    132 					  ent.entry.modified_by->principal,
    133 					  &out->mod_name);
    134 	} else if(ent.entry.created_by.principal != NULL)
    135 	    ret = krb5_copy_principal(context->context,
    136 				      ent.entry.created_by.principal,
    137 				      &out->mod_name);
    138 	else
    139 	    out->mod_name = NULL;
    140     }
    141     if(ret)
    142 	goto out;
    143 
    144     if(mask & KADM5_KVNO)
    145 	out->kvno = ent.entry.kvno;
    146     if(mask & KADM5_MKVNO) {
    147 	size_t n;
    148 	out->mkvno = 0; /* XXX */
    149 	for(n = 0; n < ent.entry.keys.len; n++)
    150 	    if(ent.entry.keys.val[n].mkvno) {
    151 		out->mkvno = *ent.entry.keys.val[n].mkvno; /* XXX this isn't right */
    152 		break;
    153 	    }
    154     }
    155 #if 0 /* XXX implement */
    156     if(mask & KADM5_AUX_ATTRIBUTES)
    157 	;
    158     if(mask & KADM5_LAST_SUCCESS)
    159 	;
    160     if(mask & KADM5_LAST_FAILED)
    161 	;
    162     if(mask & KADM5_FAIL_AUTH_COUNT)
    163 	;
    164 #endif
    165     if(mask & KADM5_POLICY)
    166 	out->policy = NULL;
    167     if(mask & KADM5_MAX_RLIFE) {
    168 	if(ent.entry.max_renew)
    169 	    out->max_renewable_life = *ent.entry.max_renew;
    170 	else
    171 	    out->max_renewable_life = INT_MAX;
    172     }
    173     if(mask & KADM5_KEY_DATA){
    174 	size_t i;
    175 	Key *key;
    176 	krb5_key_data *kd;
    177 	krb5_salt salt;
    178 	krb5_data *sp;
    179 	krb5_get_pw_salt(context->context, ent.entry.principal, &salt);
    180 	out->key_data = malloc(ent.entry.keys.len * sizeof(*out->key_data));
    181 	if (out->key_data == NULL && ent.entry.keys.len != 0) {
    182 	    ret = ENOMEM;
    183 	    goto out;
    184 	}
    185 	for(i = 0; i < ent.entry.keys.len; i++){
    186 	    key = &ent.entry.keys.val[i];
    187 	    kd = &out->key_data[i];
    188 	    kd->key_data_ver = 2;
    189 	    kd->key_data_kvno = ent.entry.kvno;
    190 	    kd->key_data_type[0] = key->key.keytype;
    191 	    if(key->salt)
    192 		kd->key_data_type[1] = key->salt->type;
    193 	    else
    194 		kd->key_data_type[1] = KRB5_PADATA_PW_SALT;
    195 	    /* setup key */
    196 	    kd->key_data_length[0] = key->key.keyvalue.length;
    197 	    kd->key_data_contents[0] = malloc(kd->key_data_length[0]);
    198 	    if(kd->key_data_contents[0] == NULL && kd->key_data_length[0] != 0){
    199 		ret = ENOMEM;
    200 		break;
    201 	    }
    202 	    memcpy(kd->key_data_contents[0], key->key.keyvalue.data,
    203 		   kd->key_data_length[0]);
    204 	    /* setup salt */
    205 	    if(key->salt)
    206 		sp = &key->salt->salt;
    207 	    else
    208 		sp = &salt.saltvalue;
    209 	    kd->key_data_length[1] = sp->length;
    210 	    kd->key_data_contents[1] = malloc(kd->key_data_length[1]);
    211 	    if(kd->key_data_length[1] != 0
    212 	       && kd->key_data_contents[1] == NULL) {
    213 		memset(kd->key_data_contents[0], 0, kd->key_data_length[0]);
    214 		ret = ENOMEM;
    215 		break;
    216 	    }
    217 	    memcpy(kd->key_data_contents[1], sp->data, kd->key_data_length[1]);
    218 	    out->n_key_data = i + 1;
    219 	}
    220 	krb5_free_salt(context->context, salt);
    221     }
    222     if(ret){
    223 	kadm5_free_principal_ent(context, out);
    224 	goto out;
    225     }
    226     if(mask & KADM5_TL_DATA) {
    227 	time_t last_pw_expire;
    228 	const HDB_Ext_PKINIT_acl *acl;
    229 	const HDB_Ext_Aliases *aliases;
    230 
    231 	ret = hdb_entry_get_pw_change_time(&ent.entry, &last_pw_expire);
    232 	if (ret == 0 && last_pw_expire) {
    233 	    unsigned char buf[4];
    234 	    _krb5_put_int(buf, last_pw_expire, sizeof(buf));
    235 	    ret = add_tl_data(out, KRB5_TL_LAST_PWD_CHANGE, buf, sizeof(buf));
    236 	}
    237 	if(ret){
    238 	    kadm5_free_principal_ent(context, out);
    239 	    goto out;
    240 	}
    241 	/*
    242 	 * If the client was allowed to get key data, let it have the
    243 	 * password too.
    244 	 */
    245 	if(mask & KADM5_KEY_DATA) {
    246 	    heim_utf8_string pw;
    247 
    248 	    ret = hdb_entry_get_password(context->context,
    249 					 context->db, &ent.entry, &pw);
    250 	    if (ret == 0) {
    251 		ret = add_tl_data(out, KRB5_TL_PASSWORD, pw, strlen(pw) + 1);
    252 		free(pw);
    253 	    }
    254 	    krb5_clear_error_message(context->context);
    255 	}
    256 
    257 	ret = hdb_entry_get_pkinit_acl(&ent.entry, &acl);
    258 	if (ret == 0 && acl) {
    259 	    krb5_data buf;
    260 	    size_t len;
    261 
    262 	    ASN1_MALLOC_ENCODE(HDB_Ext_PKINIT_acl, buf.data, buf.length,
    263 				acl, &len, ret);
    264 	    if (ret) {
    265 		kadm5_free_principal_ent(context, out);
    266 		goto out;
    267 	    }
    268 	    if (len != buf.length)
    269 		krb5_abortx(context->context,
    270 			    "internal ASN.1 encoder error");
    271 	    ret = add_tl_data(out, KRB5_TL_PKINIT_ACL, buf.data, buf.length);
    272 	    free(buf.data);
    273 	    if (ret) {
    274 		kadm5_free_principal_ent(context, out);
    275 		goto out;
    276 	    }
    277 	}
    278 	if(ret){
    279 	    kadm5_free_principal_ent(context, out);
    280 	    goto out;
    281 	}
    282 
    283 	ret = hdb_entry_get_aliases(&ent.entry, &aliases);
    284 	if (ret == 0 && aliases) {
    285 	    krb5_data buf;
    286 	    size_t len;
    287 
    288 	    ASN1_MALLOC_ENCODE(HDB_Ext_Aliases, buf.data, buf.length,
    289 			       aliases, &len, ret);
    290 	    if (ret) {
    291 		kadm5_free_principal_ent(context, out);
    292 		goto out;
    293 	    }
    294 	    if (len != buf.length)
    295 		krb5_abortx(context->context,
    296 			    "internal ASN.1 encoder error");
    297 	    ret = add_tl_data(out, KRB5_TL_ALIASES, buf.data, buf.length);
    298 	    free(buf.data);
    299 	    if (ret) {
    300 		kadm5_free_principal_ent(context, out);
    301 		goto out;
    302 	    }
    303 	}
    304 	if(ret){
    305 	    kadm5_free_principal_ent(context, out);
    306 	    goto out;
    307 	}
    308 
    309     }
    310 out:
    311     hdb_free_entry(context->context, &ent);
    312 
    313     return _kadm5_error_code(ret);
    314 }
    315