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