1 /* 2 * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. 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("$Id$"); 39 40 #define set_value(X, V) do { if((X) == NULL) (X) = malloc(sizeof(*(X))); *(X) = V; } while(0) 41 #define set_null(X) do { if((X) != NULL) free((X)); (X) = NULL; } while (0) 42 43 static void 44 attr_to_flags(unsigned attr, HDBFlags *flags) 45 { 46 flags->postdate = !(attr & KRB5_KDB_DISALLOW_POSTDATED); 47 flags->forwardable = !(attr & KRB5_KDB_DISALLOW_FORWARDABLE); 48 flags->initial = !!(attr & KRB5_KDB_DISALLOW_TGT_BASED); 49 flags->renewable = !(attr & KRB5_KDB_DISALLOW_RENEWABLE); 50 flags->proxiable = !(attr & KRB5_KDB_DISALLOW_PROXIABLE); 51 /* DUP_SKEY */ 52 flags->invalid = !!(attr & KRB5_KDB_DISALLOW_ALL_TIX); 53 flags->require_preauth = !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH); 54 /* HW_AUTH */ 55 flags->server = !(attr & KRB5_KDB_DISALLOW_SVR); 56 flags->change_pw = !!(attr & KRB5_KDB_PWCHANGE_SERVICE); 57 flags->client = 1; /* XXX */ 58 flags->ok_as_delegate = !!(attr & KRB5_KDB_OK_AS_DELEGATE); 59 flags->trusted_for_delegation = !!(attr & KRB5_KDB_TRUSTED_FOR_DELEGATION); 60 flags->allow_kerberos4 = !!(attr & KRB5_KDB_ALLOW_KERBEROS4); 61 flags->allow_digest = !!(attr & KRB5_KDB_ALLOW_DIGEST); 62 } 63 64 /* 65 * Modify the `ent' according to `tl_data'. 66 */ 67 68 static kadm5_ret_t 69 perform_tl_data(krb5_context context, 70 HDB *db, 71 hdb_entry_ex *ent, 72 const krb5_tl_data *tl_data) 73 { 74 kadm5_ret_t ret = 0; 75 76 if (tl_data->tl_data_type == KRB5_TL_PASSWORD) { 77 heim_utf8_string pw = tl_data->tl_data_contents; 78 79 if (pw[tl_data->tl_data_length] != '\0') 80 return KADM5_BAD_TL_TYPE; 81 82 ret = hdb_entry_set_password(context, db, &ent->entry, pw); 83 84 } else if (tl_data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE) { 85 unsigned char *s; 86 time_t t; 87 88 if (tl_data->tl_data_length != 4) 89 return KADM5_BAD_TL_TYPE; 90 91 s = tl_data->tl_data_contents; 92 93 t = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 94 95 ret = hdb_entry_set_pw_change_time(context, &ent->entry, t); 96 97 } else if (tl_data->tl_data_type == KRB5_TL_EXTENSION) { 98 HDB_extension ext; 99 100 ret = decode_HDB_extension(tl_data->tl_data_contents, 101 tl_data->tl_data_length, 102 &ext, 103 NULL); 104 if (ret) 105 return KADM5_BAD_TL_TYPE; 106 107 ret = hdb_replace_extension(context, &ent->entry, &ext); 108 free_HDB_extension(&ext); 109 } else { 110 return KADM5_BAD_TL_TYPE; 111 } 112 return ret; 113 } 114 115 static void 116 default_flags(hdb_entry_ex *ent, int server) 117 { 118 ent->entry.flags.client = 1; 119 ent->entry.flags.server = !!server; 120 ent->entry.flags.forwardable = 1; 121 ent->entry.flags.proxiable = 1; 122 ent->entry.flags.renewable = 1; 123 ent->entry.flags.postdate = 1; 124 } 125 126 127 /* 128 * Create the hdb entry `ent' based on data from `princ' with 129 * `princ_mask' specifying what fields to be gotten from there and 130 * `mask' specifying what fields we want filled in. 131 */ 132 133 kadm5_ret_t 134 _kadm5_setup_entry(kadm5_server_context *context, 135 hdb_entry_ex *ent, 136 uint32_t mask, 137 kadm5_principal_ent_t princ, 138 uint32_t princ_mask, 139 kadm5_principal_ent_t def, 140 uint32_t def_mask) 141 { 142 if(mask & KADM5_PRINC_EXPIRE_TIME 143 && princ_mask & KADM5_PRINC_EXPIRE_TIME) { 144 if (princ->princ_expire_time) 145 set_value(ent->entry.valid_end, princ->princ_expire_time); 146 else 147 set_null(ent->entry.valid_end); 148 } 149 if(mask & KADM5_PW_EXPIRATION 150 && princ_mask & KADM5_PW_EXPIRATION) { 151 if (princ->pw_expiration) 152 set_value(ent->entry.pw_end, princ->pw_expiration); 153 else 154 set_null(ent->entry.pw_end); 155 } 156 if(mask & KADM5_ATTRIBUTES) { 157 if (princ_mask & KADM5_ATTRIBUTES) { 158 attr_to_flags(princ->attributes, &ent->entry.flags); 159 } else if(def_mask & KADM5_ATTRIBUTES) { 160 attr_to_flags(def->attributes, &ent->entry.flags); 161 ent->entry.flags.invalid = 0; 162 } else { 163 default_flags(ent, 1); 164 } 165 } 166 167 if(mask & KADM5_MAX_LIFE) { 168 if(princ_mask & KADM5_MAX_LIFE) { 169 if(princ->max_life) 170 set_value(ent->entry.max_life, princ->max_life); 171 else 172 set_null(ent->entry.max_life); 173 } else if(def_mask & KADM5_MAX_LIFE) { 174 if(def->max_life) 175 set_value(ent->entry.max_life, def->max_life); 176 else 177 set_null(ent->entry.max_life); 178 } 179 } 180 if(mask & KADM5_KVNO 181 && princ_mask & KADM5_KVNO) 182 ent->entry.kvno = princ->kvno; 183 if(mask & KADM5_MAX_RLIFE) { 184 if(princ_mask & KADM5_MAX_RLIFE) { 185 if(princ->max_renewable_life) 186 set_value(ent->entry.max_renew, princ->max_renewable_life); 187 else 188 set_null(ent->entry.max_renew); 189 } else if(def_mask & KADM5_MAX_RLIFE) { 190 if(def->max_renewable_life) 191 set_value(ent->entry.max_renew, def->max_renewable_life); 192 else 193 set_null(ent->entry.max_renew); 194 } 195 } 196 if(mask & KADM5_KEY_DATA 197 && princ_mask & KADM5_KEY_DATA) { 198 _kadm5_set_keys2(context, &ent->entry, 199 princ->n_key_data, princ->key_data); 200 } 201 if(mask & KADM5_TL_DATA) { 202 krb5_tl_data *tl; 203 204 for (tl = princ->tl_data; tl != NULL; tl = tl->tl_data_next) { 205 kadm5_ret_t ret; 206 ret = perform_tl_data(context->context, context->db, ent, tl); 207 if (ret) 208 return ret; 209 } 210 } 211 if(mask & KADM5_FAIL_AUTH_COUNT) { 212 /* XXX */ 213 } 214 return 0; 215 } 216