1/* 2 * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "kadm5_locl.h" 35 36RCSID("$Id$"); 37 38#define __CALL(F, P) (*((kadm5_common_context*)server_handle)->funcs.F)P; 39 40kadm5_ret_t 41kadm5_chpass_principal(void *server_handle, 42 krb5_principal princ, 43 const char *password) 44{ 45 return kadm5_chpass_principal_3(server_handle, princ, 0, 0, NULL, password); 46} 47 48kadm5_ret_t 49kadm5_chpass_principal2(void *server_handle, 50 krb5_principal princ, 51 const char *password, 52 krb5_enctype *enctypes) 53{ 54 return __CALL(chpass_principal, (server_handle, princ, 0, password, 55 0, NULL)); 56} 57 58kadm5_ret_t 59kadm5_chpass_principal_3(void *server_handle, 60 krb5_principal princ, 61 krb5_boolean keepold, 62 int n_ks_tuple, 63 krb5_key_salt_tuple *ks_tuple, 64 const char *password) 65{ 66 return __CALL(chpass_principal, (server_handle, princ, keepold, password, 67 n_ks_tuple, ks_tuple)); 68} 69 70kadm5_ret_t 71kadm5_chpass_principal_with_key(void *server_handle, 72 krb5_principal princ, 73 int n_key_data, 74 krb5_key_data *key_data) 75{ 76 return __CALL(chpass_principal_with_key, 77 (server_handle, princ, 0, n_key_data, key_data)); 78} 79 80kadm5_ret_t 81kadm5_chpass_principal_with_key_3(void *server_handle, 82 krb5_principal princ, 83 int keepold, 84 int n_key_data, 85 krb5_key_data *key_data) 86{ 87 return __CALL(chpass_principal_with_key, 88 (server_handle, princ, keepold, n_key_data, key_data)); 89} 90 91kadm5_ret_t 92kadm5_create_principal(void *server_handle, 93 kadm5_principal_ent_t princ, 94 uint32_t mask, 95 const char *password) 96{ 97 return kadm5_create_principal_2(server_handle, princ, mask, 0, NULL, password); 98} 99 100kadm5_ret_t 101kadm5_create_principal_2(void *server_handle, 102 kadm5_principal_ent_t princ, 103 uint32_t mask, 104 int n_ks_tuple, 105 krb5_key_salt_tuple *ks_tuple, 106 const char *password) 107{ 108 return __CALL(create_principal, (server_handle, princ, mask, password, 109 n_ks_tuple, ks_tuple)); 110} 111 112kadm5_ret_t 113kadm5_delete_principal(void *server_handle, 114 krb5_principal princ) 115{ 116 return __CALL(delete_principal, (server_handle, princ)); 117} 118 119kadm5_ret_t 120kadm5_destroy (void *server_handle) 121{ 122 return __CALL(destroy, (server_handle)); 123} 124 125kadm5_ret_t 126kadm5_flush (void *server_handle) 127{ 128 return __CALL(flush, (server_handle)); 129} 130 131kadm5_ret_t 132kadm5_get_principal(void *server_handle, 133 krb5_principal princ, 134 kadm5_principal_ent_t out, 135 uint32_t mask) 136{ 137 return __CALL(get_principal, (server_handle, princ, out, mask)); 138} 139 140/** 141 * Extract decrypted keys from kadm5_principal_ent_t object. Mostly a 142 * no-op for Heimdal because we fetch the entry with decrypted keys. 143 * Sadly this is not fully a no-op, as we have to allocate a copy. 144 * 145 * @server_handle is the kadm5 handle 146 * @entry is the HDB entry for the principal in question 147 * @ktype is the enctype to get a key for, or -1 to get the first one 148 * @stype is the salttype to get a key for, or -1 to get the first match 149 * @kvno is the kvno to search for, or -1 to get the first match (highest kvno) 150 * @keyblock is where the key will be placed 151 * @keysalt, if not NULL, is where the salt will be placed 152 * @kvnop, if not NULL, is where the selected kvno will be placed 153 */ 154kadm5_ret_t 155kadm5_decrypt_key(void *server_handle, 156 kadm5_principal_ent_t entry, 157 int32_t ktype, int32_t stype, 158 int32_t kvno, krb5_keyblock *keyblock, 159 krb5_keysalt *keysalt, int *kvnop) 160{ 161 size_t i; 162 163 if (kvno < 1 || stype != -1) 164 return KADM5_DECRYPT_USAGE_NOSUPP; 165 166 for (i = 0; i < (size_t)entry->n_key_data; i++) { 167 if (ktype != entry->key_data[i].key_data_kvno) 168 continue; 169 170 keyblock->keytype = ktype; 171 keyblock->keyvalue.length = entry->key_data[i].key_data_length[0]; 172 keyblock->keyvalue.data = malloc(keyblock->keyvalue.length); 173 if (keyblock->keyvalue.data == NULL) 174 return ENOMEM; 175 memcpy(keyblock->keyvalue.data, 176 entry->key_data[i].key_data_contents[0], 177 keyblock->keyvalue.length); 178 } 179 180 return 0; 181} 182 183kadm5_ret_t 184kadm5_modify_principal(void *server_handle, 185 kadm5_principal_ent_t princ, 186 uint32_t mask) 187{ 188 return __CALL(modify_principal, (server_handle, princ, mask)); 189} 190 191kadm5_ret_t 192kadm5_randkey_principal(void *server_handle, 193 krb5_principal princ, 194 krb5_keyblock **new_keys, 195 int *n_keys) 196{ 197 return kadm5_randkey_principal_3(server_handle, princ, 0, 0, NULL, new_keys, n_keys); 198} 199 200kadm5_ret_t 201kadm5_randkey_principal2(void *server_handle, 202 krb5_principal princ, 203 krb5_keyblock **new_keys, 204 int *n_keys) 205{ 206 return __CALL(randkey_principal, (server_handle, princ, FALSE, 0, NULL, 207 new_keys, n_keys)); 208} 209 210kadm5_ret_t 211kadm5_randkey_principal_3(void *server_handle, 212 krb5_principal princ, 213 krb5_boolean keepold, 214 int n_ks_tuple, 215 krb5_key_salt_tuple *ks_tuple, 216 krb5_keyblock **new_keys, 217 int *n_keys) 218{ 219 return __CALL(randkey_principal, (server_handle, princ, keepold, 220 n_ks_tuple, ks_tuple, new_keys, n_keys)); 221} 222 223kadm5_ret_t 224kadm5_rename_principal(void *server_handle, 225 krb5_principal source, 226 krb5_principal target) 227{ 228 return __CALL(rename_principal, (server_handle, source, target)); 229} 230 231kadm5_ret_t 232kadm5_get_principals(void *server_handle, 233 const char *expression, 234 char ***princs, 235 int *count) 236{ 237 return __CALL(get_principals, (server_handle, expression, princs, count)); 238} 239 240kadm5_ret_t 241kadm5_get_privs(void *server_handle, 242 uint32_t *privs) 243{ 244 return __CALL(get_privs, (server_handle, privs)); 245} 246 247 248/** 249 * This function is allows the caller to set new keys for a principal. 250 * This is a trivial wrapper around kadm5_setkey_principal_3(). 251 */ 252kadm5_ret_t 253kadm5_setkey_principal(void *server_handle, 254 krb5_principal princ, 255 krb5_keyblock *new_keys, 256 int n_keys) 257{ 258 return kadm5_setkey_principal_3(server_handle, princ, 0, 0, NULL, 259 new_keys, n_keys); 260} 261 262/** 263 * This function is allows the caller to set new keys for a principal. 264 * This is a simple wrapper around kadm5_get_principal() and 265 * kadm5_modify_principal(). 266 */ 267kadm5_ret_t 268kadm5_setkey_principal_3(void *server_handle, 269 krb5_principal princ, 270 krb5_boolean keepold, 271 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, 272 krb5_keyblock *keyblocks, 273 int n_keys) 274{ 275 kadm5_principal_ent_rec princ_ent; 276 kadm5_ret_t ret; 277 krb5_key_data *new_key_data = NULL; 278 size_t i; 279 280 if (n_keys < 1) 281 return EINVAL; 282 if (n_ks_tuple > 0 && n_ks_tuple != n_keys) 283 return KADM5_SETKEY3_ETYPE_MISMATCH; 284 285 ret = kadm5_get_principal(server_handle, princ, &princ_ent, 286 KADM5_KVNO | KADM5_PRINCIPAL | KADM5_KEY_DATA); 287 if (ret) 288 return ret; 289 290 if (keepold) { 291 new_key_data = malloc((n_keys + princ_ent.n_key_data) * sizeof(*new_key_data)); 292 if (new_key_data == NULL) { 293 ret = ENOMEM; 294 goto out; 295 } 296 297 memcpy(&new_key_data[n_keys], &princ_ent.key_data[0], 298 princ_ent.n_key_data * sizeof (princ_ent.key_data[0])); 299 } else { 300 new_key_data = malloc(n_keys * sizeof(*new_key_data)); 301 if (new_key_data == NULL) { 302 ret = ENOMEM; 303 goto out; 304 } 305 } 306 307 princ_ent.kvno++; 308 for (i = 0; i < (size_t)n_keys; i++) { 309 new_key_data[i].key_data_ver = 2; 310 311 /* Key */ 312 new_key_data[i].key_data_kvno = princ_ent.kvno; 313 new_key_data[i].key_data_type[0] = keyblocks[i].keytype; 314 new_key_data[i].key_data_length[0] = keyblocks[i].keyvalue.length; 315 new_key_data[i].key_data_contents[0] = 316 malloc(keyblocks[i].keyvalue.length); 317 if (new_key_data[i].key_data_contents[0] == NULL) { 318 ret = ENOMEM; 319 goto out; 320 } 321 memcpy(new_key_data[i].key_data_contents[0], 322 keyblocks[i].keyvalue.data, 323 keyblocks[i].keyvalue.length); 324 325 /* 326 * Salt (but there's no salt, just salttype, which is kinda 327 * silly -- what's the point of setkey_3() then, besides 328 * keepold?!) 329 */ 330 new_key_data[i].key_data_type[1] = 0; 331 if (n_ks_tuple > 0) { 332 if (ks_tuple[i].ks_enctype != keyblocks[i].keytype) 333 return KADM5_SETKEY3_ETYPE_MISMATCH; 334 new_key_data[i].key_data_type[1] = ks_tuple[i].ks_salttype; 335 } 336 new_key_data[i].key_data_length[1] = 0; 337 new_key_data[i].key_data_contents[1] = NULL; 338 } 339 340 /* Free old keys */ 341 if (!keepold) { 342 for (i = 0; i < (size_t)princ_ent.n_key_data; i++) { 343 free(princ_ent.key_data[i].key_data_contents[0]); 344 free(princ_ent.key_data[i].key_data_contents[1]); 345 } 346 } 347 free(princ_ent.key_data); 348 princ_ent.key_data = new_key_data; 349 princ_ent.n_key_data = n_keys + (keepold ? princ_ent.n_key_data : 0); 350 new_key_data = NULL; 351 352 /* Modify the principal */ 353 ret = kadm5_modify_principal(server_handle, &princ_ent, KADM5_KVNO | KADM5_KEY_DATA); 354 355out: 356 if (new_key_data != NULL) { 357 for (i = 0; i < (size_t)n_keys; i++) { 358 free(new_key_data[i].key_data_contents[0]); 359 free(new_key_data[i].key_data_contents[1]); 360 } 361 free(new_key_data); 362 } 363 kadm5_free_principal_ent(server_handle, &princ_ent); 364 return ret; 365} 366 367 368kadm5_ret_t 369kadm5_lock(void *server_handle) 370{ 371 return __CALL(lock, (server_handle)); 372} 373 374kadm5_ret_t 375kadm5_unlock(void *server_handle) 376{ 377 return __CALL(unlock, (server_handle)); 378} 379 380 381kadm5_ret_t 382kadm5_create_policy(void *server_handle, 383 kadm5_policy_ent_t policy, long mask) 384{ 385 return KADM5_POLICY_OP_NOSUPP; 386} 387 388kadm5_ret_t 389kadm5_delete_policy(void *server_handle, char *name) 390{ 391 return KADM5_POLICY_OP_NOSUPP; 392} 393 394 395kadm5_ret_t 396kadm5_modify_policy(void *server_handle, kadm5_policy_ent_t policy, 397 uint32_t mask) 398{ 399 return KADM5_POLICY_OP_NOSUPP; 400} 401 402kadm5_ret_t 403kadm5_get_policy(void *server_handle, char *policy, kadm5_policy_ent_t ent) 404{ 405 memset(ent, 0, sizeof (*ent)); 406 return KADM5_POLICY_OP_NOSUPP; 407} 408 409 410kadm5_ret_t 411kadm5_get_policies(void *server_handle, char *exp, char ***pols, int *count) 412{ 413 *count = 0; 414 *pols = NULL; 415 416 return KADM5_POLICY_OP_NOSUPP; 417} 418 419kadm5_ret_t 420kadm5_free_policy_ent(kadm5_policy_ent_t ent) 421{ 422 if (ent->policy) 423 free(ent->policy); 424 /* 425 * Not clear if we should free ent or not. It might be an automatic 426 * struct, so we don't free it for now, just in case. 427 */ 428 return 0; 429} 430 431