1 1.1 elric /* $NetBSD: chpass_s.c,v 1.2 2017/01/28 21:31:49 christos Exp $ */ 2 1.1 elric 3 1.1 elric /* 4 1.1 elric * Copyright (c) 1997-2006 Kungliga Tekniska Hgskolan 5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden). 6 1.1 elric * All rights reserved. 7 1.1 elric * 8 1.1 elric * Redistribution and use in source and binary forms, with or without 9 1.1 elric * modification, are permitted provided that the following conditions 10 1.1 elric * are met: 11 1.1 elric * 12 1.1 elric * 1. Redistributions of source code must retain the above copyright 13 1.1 elric * notice, this list of conditions and the following disclaimer. 14 1.1 elric * 15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 elric * notice, this list of conditions and the following disclaimer in the 17 1.1 elric * documentation and/or other materials provided with the distribution. 18 1.1 elric * 19 1.1 elric * 3. Neither the name of the Institute nor the names of its contributors 20 1.1 elric * may be used to endorse or promote products derived from this software 21 1.1 elric * without specific prior written permission. 22 1.1 elric * 23 1.1 elric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 1.1 elric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.1 elric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 1.1 elric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 1.1 elric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 1.1 elric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 1.1 elric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 1.1 elric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 1.1 elric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 1.1 elric * SUCH DAMAGE. 34 1.1 elric */ 35 1.1 elric 36 1.1 elric #include "kadm5_locl.h" 37 1.1 elric 38 1.1 elric __RCSID("$NetBSD: chpass_s.c,v 1.2 2017/01/28 21:31:49 christos Exp $"); 39 1.1 elric 40 1.1 elric static kadm5_ret_t 41 1.1 elric change(void *server_handle, 42 1.1 elric krb5_principal princ, 43 1.2 christos int keepold, 44 1.2 christos int n_ks_tuple, 45 1.2 christos krb5_key_salt_tuple *ks_tuple, 46 1.1 elric const char *password, 47 1.1 elric int cond) 48 1.1 elric { 49 1.1 elric kadm5_server_context *context = server_handle; 50 1.1 elric hdb_entry_ex ent; 51 1.1 elric kadm5_ret_t ret; 52 1.1 elric Key *keys; 53 1.1 elric size_t num_keys; 54 1.1 elric int existsp = 0; 55 1.1 elric 56 1.1 elric memset(&ent, 0, sizeof(ent)); 57 1.2 christos if (!context->keep_open) { 58 1.2 christos ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); 59 1.2 christos if(ret) 60 1.2 christos return ret; 61 1.2 christos } 62 1.2 christos 63 1.2 christos ret = kadm5_log_init(context); 64 1.2 christos if (ret) 65 1.2 christos goto out; 66 1.1 elric 67 1.1 elric ret = context->db->hdb_fetch_kvno(context->context, context->db, princ, 68 1.1 elric HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent); 69 1.2 christos if (ret) 70 1.2 christos goto out2; 71 1.2 christos 72 1.2 christos if (keepold || cond) { 73 1.2 christos /* 74 1.2 christos * We save these for now so we can handle password history checking; 75 1.2 christos * we handle keepold further below. 76 1.2 christos */ 77 1.2 christos ret = hdb_add_current_keys_to_history(context->context, &ent.entry); 78 1.2 christos if (ret) 79 1.2 christos goto out3; 80 1.2 christos } 81 1.1 elric 82 1.1 elric if (context->db->hdb_capability_flags & HDB_CAP_F_HANDLE_PASSWORDS) { 83 1.1 elric ret = context->db->hdb_password(context->context, context->db, 84 1.1 elric &ent, password, cond); 85 1.1 elric if (ret) 86 1.2 christos goto out3; 87 1.1 elric } else { 88 1.1 elric 89 1.1 elric num_keys = ent.entry.keys.len; 90 1.1 elric keys = ent.entry.keys.val; 91 1.2 christos 92 1.1 elric ent.entry.keys.len = 0; 93 1.1 elric ent.entry.keys.val = NULL; 94 1.2 christos 95 1.2 christos ret = _kadm5_set_keys(context, &ent.entry, n_ks_tuple, ks_tuple, 96 1.2 christos password); 97 1.1 elric if(ret) { 98 1.2 christos _kadm5_free_keys(context->context, num_keys, keys); 99 1.2 christos goto out3; 100 1.2 christos } 101 1.2 christos _kadm5_free_keys(context->context, num_keys, keys); 102 1.2 christos 103 1.2 christos if (cond) { 104 1.2 christos HDB_extension *ext; 105 1.2 christos 106 1.2 christos ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_hist_keys); 107 1.2 christos if (ext != NULL) 108 1.2 christos existsp = _kadm5_exists_keys_hist(ent.entry.keys.val, 109 1.2 christos ent.entry.keys.len, 110 1.2 christos &ext->data.u.hist_keys); 111 1.1 elric } 112 1.2 christos 113 1.1 elric if (existsp) { 114 1.1 elric ret = KADM5_PASS_REUSE; 115 1.1 elric krb5_set_error_message(context->context, ret, 116 1.1 elric "Password reuse forbidden"); 117 1.2 christos goto out3; 118 1.1 elric } 119 1.2 christos } 120 1.2 christos ent.entry.kvno++; 121 1.1 elric 122 1.2 christos ent.entry.flags.require_pwchange = 0; 123 1.2 christos 124 1.2 christos if (!keepold) { 125 1.2 christos HDB_extension ext; 126 1.2 christos 127 1.2 christos memset(&ext, 0, sizeof (ext)); 128 1.2 christos ext.mandatory = FALSE; 129 1.2 christos ext.data.element = choice_HDB_extension_data_hist_keys; 130 1.2 christos ret = hdb_replace_extension(context->context, &ent.entry, &ext); 131 1.1 elric if (ret) 132 1.2 christos goto out3; 133 1.1 elric } 134 1.2 christos 135 1.2 christos ret = hdb_seal_keys(context->context, context->db, &ent.entry); 136 1.2 christos if (ret) 137 1.2 christos goto out3; 138 1.1 elric 139 1.1 elric ret = _kadm5_set_modifier(context, &ent.entry); 140 1.1 elric if(ret) 141 1.2 christos goto out3; 142 1.1 elric 143 1.1 elric ret = _kadm5_bump_pw_expire(context, &ent.entry); 144 1.1 elric if (ret) 145 1.2 christos goto out3; 146 1.1 elric 147 1.2 christos /* This logs the change for iprop and writes to the HDB */ 148 1.2 christos ret = kadm5_log_modify(context, &ent.entry, 149 1.2 christos KADM5_ATTRIBUTES | KADM5_PRINCIPAL | 150 1.2 christos KADM5_MOD_NAME | KADM5_MOD_TIME | 151 1.2 christos KADM5_KEY_DATA | KADM5_KVNO | 152 1.2 christos KADM5_PW_EXPIRATION | KADM5_TL_DATA); 153 1.1 elric 154 1.2 christos out3: 155 1.1 elric hdb_free_entry(context->context, &ent); 156 1.2 christos out2: 157 1.2 christos (void) kadm5_log_end(context); 158 1.2 christos out: 159 1.2 christos if (!context->keep_open) { 160 1.2 christos kadm5_ret_t ret2; 161 1.2 christos ret2 = context->db->hdb_close(context->context, context->db); 162 1.2 christos if (ret == 0 && ret2 != 0) 163 1.2 christos ret = ret2; 164 1.2 christos } 165 1.1 elric return _kadm5_error_code(ret); 166 1.1 elric } 167 1.1 elric 168 1.1 elric 169 1.1 elric 170 1.1 elric /* 171 1.1 elric * change the password of `princ' to `password' if it's not already that. 172 1.1 elric */ 173 1.1 elric 174 1.1 elric kadm5_ret_t 175 1.1 elric kadm5_s_chpass_principal_cond(void *server_handle, 176 1.1 elric krb5_principal princ, 177 1.2 christos int keepold, 178 1.1 elric const char *password) 179 1.1 elric { 180 1.2 christos return change (server_handle, princ, keepold, 0, NULL, password, 1); 181 1.1 elric } 182 1.1 elric 183 1.1 elric /* 184 1.1 elric * change the password of `princ' to `password' 185 1.1 elric */ 186 1.1 elric 187 1.1 elric kadm5_ret_t 188 1.1 elric kadm5_s_chpass_principal(void *server_handle, 189 1.1 elric krb5_principal princ, 190 1.2 christos int keepold, 191 1.2 christos int n_ks_tuple, 192 1.2 christos krb5_key_salt_tuple *ks_tuple, 193 1.1 elric const char *password) 194 1.1 elric { 195 1.2 christos return change (server_handle, princ, keepold, 196 1.2 christos n_ks_tuple, ks_tuple, password, 0); 197 1.1 elric } 198 1.1 elric 199 1.1 elric /* 200 1.1 elric * change keys for `princ' to `keys' 201 1.1 elric */ 202 1.1 elric 203 1.1 elric kadm5_ret_t 204 1.1 elric kadm5_s_chpass_principal_with_key(void *server_handle, 205 1.1 elric krb5_principal princ, 206 1.2 christos int keepold, 207 1.1 elric int n_key_data, 208 1.1 elric krb5_key_data *key_data) 209 1.1 elric { 210 1.1 elric kadm5_server_context *context = server_handle; 211 1.1 elric hdb_entry_ex ent; 212 1.1 elric kadm5_ret_t ret; 213 1.1 elric 214 1.1 elric memset(&ent, 0, sizeof(ent)); 215 1.2 christos if (!context->keep_open) { 216 1.2 christos ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); 217 1.2 christos if(ret) 218 1.2 christos return ret; 219 1.2 christos } 220 1.2 christos 221 1.2 christos ret = kadm5_log_init(context); 222 1.2 christos if (ret) 223 1.2 christos goto out; 224 1.2 christos 225 1.1 elric ret = context->db->hdb_fetch_kvno(context->context, context->db, princ, 0, 226 1.1 elric HDB_F_GET_ANY|HDB_F_ADMIN_DATA, &ent); 227 1.2 christos if (ret == HDB_ERR_NOENTRY) 228 1.2 christos goto out2; 229 1.2 christos if (keepold) { 230 1.2 christos ret = hdb_add_current_keys_to_history(context->context, &ent.entry); 231 1.2 christos if (ret) 232 1.2 christos goto out3; 233 1.2 christos } 234 1.1 elric ret = _kadm5_set_keys2(context, &ent.entry, n_key_data, key_data); 235 1.2 christos if (ret) 236 1.2 christos goto out3; 237 1.1 elric ent.entry.kvno++; 238 1.1 elric ret = _kadm5_set_modifier(context, &ent.entry); 239 1.2 christos if (ret) 240 1.2 christos goto out3; 241 1.1 elric ret = _kadm5_bump_pw_expire(context, &ent.entry); 242 1.1 elric if (ret) 243 1.2 christos goto out3; 244 1.1 elric 245 1.2 christos if (keepold) { 246 1.2 christos ret = hdb_seal_keys(context->context, context->db, &ent.entry); 247 1.2 christos if (ret) 248 1.2 christos goto out3; 249 1.2 christos } else { 250 1.2 christos HDB_extension ext; 251 1.1 elric 252 1.2 christos memset(&ext, 0, sizeof (ext)); 253 1.2 christos ext.mandatory = FALSE; 254 1.2 christos ext.data.element = choice_HDB_extension_data_hist_keys; 255 1.2 christos ext.data.u.hist_keys.len = 0; 256 1.2 christos ext.data.u.hist_keys.val = NULL; 257 1.2 christos hdb_replace_extension(context->context, &ent.entry, &ext); 258 1.2 christos } 259 1.1 elric 260 1.2 christos /* This logs the change for iprop and writes to the HDB */ 261 1.2 christos ret = kadm5_log_modify(context, &ent.entry, 262 1.2 christos KADM5_PRINCIPAL | KADM5_MOD_NAME | 263 1.2 christos KADM5_MOD_TIME | KADM5_KEY_DATA | KADM5_KVNO | 264 1.2 christos KADM5_PW_EXPIRATION | KADM5_TL_DATA); 265 1.1 elric 266 1.2 christos out3: 267 1.1 elric hdb_free_entry(context->context, &ent); 268 1.2 christos out2: 269 1.2 christos (void) kadm5_log_end(context); 270 1.2 christos out: 271 1.2 christos if (!context->keep_open) { 272 1.2 christos kadm5_ret_t ret2; 273 1.2 christos ret2 = context->db->hdb_close(context->context, context->db); 274 1.2 christos if (ret == 0 && ret2 != 0) 275 1.2 christos ret = ret2; 276 1.2 christos } 277 1.1 elric return _kadm5_error_code(ret); 278 1.1 elric } 279