1 /* $NetBSD: common_glue.c,v 1.2 2017/01/28 21:31:49 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan 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: common_glue.c,v 1.2 2017/01/28 21:31:49 christos Exp $"); 39 40 #define __CALL(F, P) (*((kadm5_common_context*)server_handle)->funcs.F)P 41 #define __CALLABLE(F) (((kadm5_common_context*)server_handle)->funcs.F != 0) 42 43 kadm5_ret_t 44 kadm5_chpass_principal(void *server_handle, 45 krb5_principal princ, 46 const char *password) 47 { 48 return __CALL(chpass_principal, (server_handle, princ, 0, 49 0, NULL, password)); 50 } 51 52 kadm5_ret_t 53 kadm5_chpass_principal_3(void *server_handle, 54 krb5_principal princ, 55 krb5_boolean keepold, 56 int n_ks_tuple, 57 krb5_key_salt_tuple *ks_tuple, 58 const char *password) 59 { 60 return __CALL(chpass_principal, (server_handle, princ, keepold, 61 n_ks_tuple, ks_tuple, password)); 62 } 63 64 kadm5_ret_t 65 kadm5_chpass_principal_with_key(void *server_handle, 66 krb5_principal princ, 67 int n_key_data, 68 krb5_key_data *key_data) 69 { 70 return __CALL(chpass_principal_with_key, 71 (server_handle, princ, 0, n_key_data, key_data)); 72 } 73 74 kadm5_ret_t 75 kadm5_chpass_principal_with_key_3(void *server_handle, 76 krb5_principal princ, 77 int keepold, 78 int n_key_data, 79 krb5_key_data *key_data) 80 { 81 return __CALL(chpass_principal_with_key, 82 (server_handle, princ, keepold, n_key_data, key_data)); 83 } 84 85 kadm5_ret_t 86 kadm5_create_principal_3(void *server_handle, 87 kadm5_principal_ent_t princ, 88 uint32_t mask, 89 int n_ks_tuple, 90 krb5_key_salt_tuple *ks_tuple, 91 char *password) 92 { 93 return __CALL(create_principal, 94 (server_handle, princ, mask, n_ks_tuple, ks_tuple, password)); 95 } 96 97 kadm5_ret_t 98 kadm5_create_principal(void *server_handle, 99 kadm5_principal_ent_t princ, 100 uint32_t mask, 101 const char *password) 102 { 103 return __CALL(create_principal, 104 (server_handle, princ, mask, 0, NULL, password)); 105 } 106 107 kadm5_ret_t 108 kadm5_delete_principal(void *server_handle, 109 krb5_principal princ) 110 { 111 return __CALL(delete_principal, (server_handle, princ)); 112 } 113 114 kadm5_ret_t 115 kadm5_destroy (void *server_handle) 116 { 117 return __CALL(destroy, (server_handle)); 118 } 119 120 kadm5_ret_t 121 kadm5_flush (void *server_handle) 122 { 123 return __CALL(flush, (server_handle)); 124 } 125 126 kadm5_ret_t 127 kadm5_get_principal(void *server_handle, 128 krb5_principal princ, 129 kadm5_principal_ent_t out, 130 uint32_t mask) 131 { 132 return __CALL(get_principal, (server_handle, princ, out, mask)); 133 } 134 135 /** 136 * Extract decrypted keys from kadm5_principal_ent_t object. Mostly a 137 * no-op for Heimdal because we fetch the entry with decrypted keys. 138 * Sadly this is not fully a no-op, as we have to allocate a copy. 139 * 140 * @server_handle is the kadm5 handle 141 * @entry is the HDB entry for the principal in question 142 * @ktype is the enctype to get a key for, or -1 to get the first one 143 * @stype is the salttype to get a key for, or -1 to get the first match 144 * @kvno is the kvno to search for, or -1 to get the first match (highest kvno) 145 * @keyblock is where the key will be placed 146 * @keysalt, if not NULL, is where the salt will be placed 147 * @kvnop, if not NULL, is where the selected kvno will be placed 148 */ 149 kadm5_ret_t 150 kadm5_decrypt_key(void *server_handle, 151 kadm5_principal_ent_t entry, 152 int32_t ktype, int32_t stype, 153 int32_t kvno, krb5_keyblock *keyblock, 154 krb5_keysalt *keysalt, int *kvnop) 155 { 156 size_t i; 157 158 if (kvno < 1 || stype != -1) 159 return KADM5_DECRYPT_USAGE_NOSUPP; 160 161 for (i = 0; i < entry->n_key_data; i++) { 162 if (ktype != entry->key_data[i].key_data_kvno) 163 continue; 164 165 keyblock->keytype = ktype; 166 keyblock->keyvalue.length = entry->key_data[i].key_data_length[0]; 167 keyblock->keyvalue.data = malloc(keyblock->keyvalue.length); 168 if (keyblock->keyvalue.data == NULL) 169 return ENOMEM; 170 memcpy(keyblock->keyvalue.data, 171 entry->key_data[i].key_data_contents[0], 172 keyblock->keyvalue.length); 173 } 174 175 return 0; 176 } 177 178 kadm5_ret_t 179 kadm5_modify_principal(void *server_handle, 180 kadm5_principal_ent_t princ, 181 uint32_t mask) 182 { 183 return __CALL(modify_principal, (server_handle, princ, mask)); 184 } 185 186 kadm5_ret_t 187 kadm5_randkey_principal(void *server_handle, 188 krb5_principal princ, 189 krb5_keyblock **new_keys, 190 int *n_keys) 191 { 192 return __CALL(randkey_principal, (server_handle, princ, FALSE, 0, NULL, 193 new_keys, n_keys)); 194 } 195 196 kadm5_ret_t 197 kadm5_randkey_principal_3(void *server_handle, 198 krb5_principal princ, 199 krb5_boolean keepold, 200 int n_ks_tuple, 201 krb5_key_salt_tuple *ks_tuple, 202 krb5_keyblock **new_keys, 203 int *n_keys) 204 { 205 return __CALL(randkey_principal, (server_handle, princ, keepold, 206 n_ks_tuple, ks_tuple, new_keys, n_keys)); 207 } 208 209 kadm5_ret_t 210 kadm5_rename_principal(void *server_handle, 211 krb5_principal source, 212 krb5_principal target) 213 { 214 return __CALL(rename_principal, (server_handle, source, target)); 215 } 216 217 kadm5_ret_t 218 kadm5_get_principals(void *server_handle, 219 const char *expression, 220 char ***princs, 221 int *count) 222 { 223 return __CALL(get_principals, (server_handle, expression, princs, count)); 224 } 225 226 kadm5_ret_t 227 kadm5_get_privs(void *server_handle, 228 uint32_t *privs) 229 { 230 return __CALL(get_privs, (server_handle, privs)); 231 } 232 233 234 /** 235 * This function is allows the caller to set new keys for a principal. 236 * This is a trivial wrapper around kadm5_setkey_principal_3(). 237 */ 238 kadm5_ret_t 239 kadm5_setkey_principal(void *server_handle, 240 krb5_principal princ, 241 krb5_keyblock *new_keys, 242 int n_keys) 243 { 244 return kadm5_setkey_principal_3(server_handle, princ, 0, 0, NULL, 245 new_keys, n_keys); 246 } 247 248 /** 249 * This function is allows the caller to set new keys for a principal. 250 * This is a simple wrapper around kadm5_get_principal() and 251 * kadm5_modify_principal(). 252 */ 253 kadm5_ret_t 254 kadm5_setkey_principal_3(void *server_handle, 255 krb5_principal princ, 256 krb5_boolean keepold, 257 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, 258 krb5_keyblock *keyblocks, 259 int n_keys) 260 { 261 kadm5_principal_ent_rec princ_ent; 262 kadm5_ret_t ret; 263 krb5_key_data *new_key_data = NULL; 264 size_t i; 265 266 if (n_keys < 1) 267 return EINVAL; 268 if (n_ks_tuple > 0 && n_ks_tuple != n_keys) 269 return KADM5_SETKEY3_ETYPE_MISMATCH; 270 271 /* 272 * If setkey_principal_3 is defined in the server handle, use that. 273 */ 274 if (__CALLABLE(setkey_principal_3)) 275 return __CALL(setkey_principal_3, 276 (server_handle, princ, keepold, n_ks_tuple, ks_tuple, 277 keyblocks, n_keys)); 278 279 /* 280 * Otherwise, simulate it via a get, update, modify sequence. 281 */ 282 ret = kadm5_get_principal(server_handle, princ, &princ_ent, 283 KADM5_KVNO | KADM5_PRINCIPAL | KADM5_KEY_DATA); 284 if (ret) 285 return ret; 286 287 if (keepold) { 288 new_key_data = calloc((n_keys + princ_ent.n_key_data), 289 sizeof(*new_key_data)); 290 if (new_key_data == NULL) { 291 ret = ENOMEM; 292 goto out; 293 } 294 295 memcpy(&new_key_data[n_keys], &princ_ent.key_data[0], 296 princ_ent.n_key_data * sizeof (princ_ent.key_data[0])); 297 } else { 298 new_key_data = calloc(n_keys, sizeof(*new_key_data)); 299 if (new_key_data == NULL) { 300 ret = ENOMEM; 301 goto out; 302 } 303 } 304 305 princ_ent.kvno++; 306 for (i = 0; i < n_keys; i++) { 307 new_key_data[i].key_data_ver = 2; 308 309 /* Key */ 310 new_key_data[i].key_data_kvno = princ_ent.kvno; 311 new_key_data[i].key_data_type[0] = keyblocks[i].keytype; 312 new_key_data[i].key_data_length[0] = keyblocks[i].keyvalue.length; 313 new_key_data[i].key_data_contents[0] = 314 malloc(keyblocks[i].keyvalue.length); 315 if (new_key_data[i].key_data_contents[0] == NULL) { 316 ret = ENOMEM; 317 goto out; 318 } 319 memcpy(new_key_data[i].key_data_contents[0], 320 keyblocks[i].keyvalue.data, 321 keyblocks[i].keyvalue.length); 322 323 /* 324 * Salt (but there's no salt, just salttype, which is kinda 325 * silly -- what's the point of setkey_3() then, besides 326 * keepold?!) 327 */ 328 new_key_data[i].key_data_type[1] = 0; 329 if (n_ks_tuple > 0) { 330 if (ks_tuple[i].ks_enctype != keyblocks[i].keytype) { 331 ret = KADM5_SETKEY3_ETYPE_MISMATCH; 332 goto out; 333 } 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 < 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 355 out: 356 if (new_key_data != NULL) { 357 for (i = 0; i < 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 368 kadm5_ret_t 369 kadm5_lock(void *server_handle) 370 { 371 return __CALL(lock, (server_handle)); 372 } 373 374 kadm5_ret_t 375 kadm5_unlock(void *server_handle) 376 { 377 return __CALL(unlock, (server_handle)); 378 } 379 380 381 kadm5_ret_t 382 kadm5_create_policy(void *server_handle, 383 kadm5_policy_ent_t policy, long mask) 384 { 385 return KADM5_POLICY_OP_NOSUPP; 386 } 387 388 kadm5_ret_t 389 kadm5_delete_policy(void *server_handle, char *name) 390 { 391 return KADM5_POLICY_OP_NOSUPP; 392 } 393 394 395 kadm5_ret_t 396 kadm5_modify_policy(void *server_handle, kadm5_policy_ent_t policy, 397 uint32_t mask) 398 { 399 return KADM5_POLICY_OP_NOSUPP; 400 } 401 402 kadm5_ret_t 403 kadm5_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 410 kadm5_ret_t 411 kadm5_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 419 kadm5_ret_t 420 kadm5_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