1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 10 * 11 * Openvision retains the copyright to derivative works of 12 * this source code. Do *NOT* create a derivative of this 13 * source code before consulting with your legal department. 14 * Do *NOT* integrate *ANY* of this source code into another 15 * product before consulting with your legal department. 16 * 17 * For further information, read the top-level Openvision 18 * copyright which is contained in the top-level MIT Kerberos 19 * copyright. 20 * 21 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 22 * 23 */ 24 25 26 /* 27 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved 28 * 29 * $Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_principal.c,v 1.8 2000/02/27 22:18:15 tlyu Exp $ 30 */ 31 32 #if !defined(lint) && !defined(__CODECENTER__) 33 static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_principal.c,v 1.8 2000/02/27 22:18:15 tlyu Exp $"; 34 #endif 35 36 #include <rpc/rpc.h> /* SUNWresync121 XXX */ 37 #include <kadm5/admin.h> 38 #include <kadm5/kadm_rpc.h> 39 #include <memory.h> 40 #include "client_internal.h" 41 42 kadm5_ret_t 43 kadm5_create_principal(void *server_handle, 44 kadm5_principal_ent_t princ, long mask, 45 char *pw) 46 { 47 generic_ret *r; 48 cprinc_arg arg; 49 kadm5_server_handle_t handle = server_handle; 50 51 CHECK_HANDLE(server_handle); 52 53 memset(&arg, 0, sizeof(arg)); 54 arg.mask = mask; 55 arg.passwd = pw; 56 arg.api_version = handle->api_version; 57 58 if(princ == NULL) 59 return EINVAL; 60 61 if (handle->api_version == KADM5_API_VERSION_1) { 62 memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1)); 63 } else { 64 memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec)); 65 } 66 if (handle->api_version == KADM5_API_VERSION_1) { 67 /* 68 * hack hack cough cough. 69 * krb5_unparse name dumps core if we pass it in garbage 70 * or null. So, since the client is not allowed to set mod_name 71 * anyway, we just fill it in with a dummy principal. The server of 72 * course ignores this. 73 */ 74 /* krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name); */ 75 arg.rec.mod_name = NULL; 76 } else 77 arg.rec.mod_name = NULL; 78 79 if(!(mask & KADM5_POLICY)) 80 arg.rec.policy = NULL; 81 if (! (mask & KADM5_KEY_DATA)) { 82 arg.rec.n_key_data = 0; 83 arg.rec.key_data = NULL; 84 } 85 if (! (mask & KADM5_TL_DATA)) { 86 arg.rec.n_tl_data = 0; 87 arg.rec.tl_data = NULL; 88 } 89 90 r = create_principal_1(&arg, handle->clnt); 91 92 if (handle->api_version == KADM5_API_VERSION_1) 93 krb5_free_principal(handle->context, arg.rec.mod_name); 94 95 if(r == NULL) 96 return KADM5_RPC_ERROR; 97 return r->code; 98 } 99 100 kadm5_ret_t 101 kadm5_create_principal_3(void *server_handle, 102 kadm5_principal_ent_t princ, long mask, 103 int n_ks_tuple, 104 krb5_key_salt_tuple *ks_tuple, 105 char *pw) 106 { 107 generic_ret *r; 108 cprinc3_arg arg; 109 kadm5_server_handle_t handle = server_handle; 110 111 CHECK_HANDLE(server_handle); 112 113 memset(&arg, 0, sizeof(arg)); 114 arg.mask = mask; 115 arg.passwd = pw; 116 arg.api_version = handle->api_version; 117 arg.n_ks_tuple = n_ks_tuple; 118 arg.ks_tuple = ks_tuple; 119 120 if(princ == NULL) 121 return EINVAL; 122 123 if (handle->api_version == KADM5_API_VERSION_1) { 124 memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1)); 125 } else { 126 memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec)); 127 } 128 if (handle->api_version == KADM5_API_VERSION_1) { 129 /* 130 * hack hack cough cough. 131 * krb5_unparse name dumps core if we pass it in garbage 132 * or null. So, since the client is not allowed to set mod_name 133 * anyway, we just fill it in with a dummy principal. The server of 134 * course ignores this. 135 */ 136 krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name); 137 } else 138 arg.rec.mod_name = NULL; 139 140 if(!(mask & KADM5_POLICY)) 141 arg.rec.policy = NULL; 142 if (! (mask & KADM5_KEY_DATA)) { 143 arg.rec.n_key_data = 0; 144 arg.rec.key_data = NULL; 145 } 146 if (! (mask & KADM5_TL_DATA)) { 147 arg.rec.n_tl_data = 0; 148 arg.rec.tl_data = NULL; 149 } 150 151 r = create_principal3_1(&arg, handle->clnt); 152 153 if (handle->api_version == KADM5_API_VERSION_1) 154 krb5_free_principal(handle->context, arg.rec.mod_name); 155 156 if(r == NULL) 157 return KADM5_RPC_ERROR; 158 return r->code; 159 } 160 161 kadm5_ret_t 162 kadm5_delete_principal(void *server_handle, krb5_principal principal) 163 { 164 dprinc_arg arg; 165 generic_ret *r; 166 kadm5_server_handle_t handle = server_handle; 167 168 CHECK_HANDLE(server_handle); 169 170 if(principal == NULL) 171 return EINVAL; 172 arg.princ = principal; 173 arg.api_version = handle->api_version; 174 r = delete_principal_1(&arg, handle->clnt); 175 if(r == NULL) 176 return KADM5_RPC_ERROR; 177 return r->code; 178 } 179 180 kadm5_ret_t 181 kadm5_modify_principal(void *server_handle, 182 kadm5_principal_ent_t princ, long mask) 183 { 184 mprinc_arg arg; 185 generic_ret *r; 186 kadm5_server_handle_t handle = server_handle; 187 188 CHECK_HANDLE(server_handle); 189 190 memset(&arg, 0, sizeof(arg)); 191 arg.mask = mask; 192 arg.api_version = handle->api_version; 193 /* 194 * cough cough gag gag 195 * see comment in create_principal. 196 */ 197 if(princ == NULL) 198 return EINVAL; 199 if (handle->api_version == KADM5_API_VERSION_1) { 200 memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec_v1)); 201 } else { 202 memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec)); 203 } 204 if(!(mask & KADM5_POLICY)) 205 arg.rec.policy = NULL; 206 if (! (mask & KADM5_KEY_DATA)) { 207 arg.rec.n_key_data = 0; 208 arg.rec.key_data = NULL; 209 } 210 if (! (mask & KADM5_TL_DATA)) { 211 arg.rec.n_tl_data = 0; 212 arg.rec.tl_data = NULL; 213 } 214 215 if (handle->api_version == KADM5_API_VERSION_1) { 216 /* 217 * See comment in create_principal 218 */ 219 krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name); 220 } else 221 arg.rec.mod_name = NULL; 222 223 r = modify_principal_1(&arg, handle->clnt); 224 225 if (handle->api_version == KADM5_API_VERSION_1) 226 krb5_free_principal(handle->context, arg.rec.mod_name); 227 228 if(r == NULL) 229 return KADM5_RPC_ERROR; 230 return r->code; 231 } 232 233 kadm5_ret_t 234 kadm5_get_principal(void *server_handle, 235 krb5_principal princ, kadm5_principal_ent_t ent, 236 long mask) 237 { 238 gprinc_arg arg; 239 gprinc_ret *r; 240 kadm5_server_handle_t handle = server_handle; 241 242 CHECK_HANDLE(server_handle); 243 244 if(princ == NULL) 245 return EINVAL; 246 arg.princ = princ; 247 if (handle->api_version == KADM5_API_VERSION_1) 248 arg.mask = KADM5_PRINCIPAL_NORMAL_MASK; 249 else 250 arg.mask = mask; 251 arg.api_version = handle->api_version; 252 r = get_principal_1(&arg, handle->clnt); 253 if(r == NULL) 254 return KADM5_RPC_ERROR; 255 if (handle->api_version == KADM5_API_VERSION_1) { 256 kadm5_principal_ent_t_v1 *entp; 257 258 entp = (kadm5_principal_ent_t_v1 *) ent; 259 if (r->code == 0) { 260 if (!(*entp = (kadm5_principal_ent_t_v1) 261 malloc(sizeof(kadm5_principal_ent_rec_v1)))) 262 return ENOMEM; 263 /* this memcpy works because the v1 structure is an initial 264 subset of the v2 struct. C guarantees that this will 265 result in the same layout in memory */ 266 memcpy(*entp, &r->rec, sizeof(**entp)); 267 } else { 268 *entp = NULL; 269 } 270 } else { 271 if (r->code == 0) 272 memcpy(ent, &r->rec, sizeof(r->rec)); 273 } 274 275 return r->code; 276 } 277 278 kadm5_ret_t 279 kadm5_get_principals(void *server_handle, 280 char *exp, char ***princs, int *count) 281 { 282 gprincs_arg arg; 283 gprincs_ret *r; 284 kadm5_server_handle_t handle = server_handle; 285 286 CHECK_HANDLE(server_handle); 287 288 if(princs == NULL || count == NULL) 289 return EINVAL; 290 arg.exp = exp; 291 arg.api_version = handle->api_version; 292 r = get_princs_1(&arg, handle->clnt); 293 if(r == NULL) 294 return KADM5_RPC_ERROR; 295 if(r->code == 0) { 296 *count = r->count; 297 *princs = r->princs; 298 } else { 299 *count = 0; 300 *princs = NULL; 301 } 302 303 return r->code; 304 } 305 306 kadm5_ret_t 307 kadm5_rename_principal(void *server_handle, 308 krb5_principal source, krb5_principal dest) 309 { 310 rprinc_arg arg; 311 generic_ret *r; 312 kadm5_server_handle_t handle = server_handle; 313 314 CHECK_HANDLE(server_handle); 315 316 arg.src = source; 317 arg.dest = dest; 318 arg.api_version = handle->api_version; 319 if (source == NULL || dest == NULL) 320 return EINVAL; 321 r = rename_principal_1(&arg, handle->clnt); 322 if(r == NULL) 323 return KADM5_RPC_ERROR; 324 return r->code; 325 } 326 327 kadm5_ret_t 328 kadm5_chpass_principal(void *server_handle, 329 krb5_principal princ, char *password) 330 { 331 chpass_arg arg; 332 generic_ret *r; 333 kadm5_server_handle_t handle = server_handle; 334 335 CHECK_HANDLE(server_handle); 336 337 arg.princ = princ; 338 arg.pass = password; 339 arg.api_version = handle->api_version; 340 341 if(princ == NULL) 342 return EINVAL; 343 r = chpass_principal_1(&arg, handle->clnt); 344 if(r == NULL) 345 return KADM5_RPC_ERROR; 346 return r->code; 347 } 348 349 kadm5_ret_t 350 kadm5_chpass_principal_3(void *server_handle, 351 krb5_principal princ, krb5_boolean keepold, 352 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, 353 char *password) 354 { 355 chpass3_arg arg; 356 generic_ret *r; 357 kadm5_server_handle_t handle = server_handle; 358 359 CHECK_HANDLE(server_handle); 360 361 arg.princ = princ; 362 arg.pass = password; 363 arg.api_version = handle->api_version; 364 arg.keepold = keepold; 365 arg.n_ks_tuple = n_ks_tuple; 366 arg.ks_tuple = ks_tuple; 367 368 if(princ == NULL) 369 return EINVAL; 370 r = chpass_principal3_1(&arg, handle->clnt); 371 if(r == NULL) 372 return KADM5_RPC_ERROR; 373 return r->code; 374 } 375 376 kadm5_ret_t 377 kadm5_setv4key_principal(void *server_handle, 378 krb5_principal princ, 379 krb5_keyblock *keyblock) 380 { 381 setv4key_arg arg; 382 generic_ret *r; 383 kadm5_server_handle_t handle = server_handle; 384 385 CHECK_HANDLE(server_handle); 386 387 arg.princ = princ; 388 arg.keyblock = keyblock; 389 arg.api_version = handle->api_version; 390 391 if(princ == NULL || keyblock == NULL) 392 return EINVAL; 393 r = setv4key_principal_1(&arg, handle->clnt); 394 if(r == NULL) 395 return KADM5_RPC_ERROR; 396 return r->code; 397 } 398 399 kadm5_ret_t 400 kadm5_setkey_principal(void *server_handle, 401 krb5_principal princ, 402 krb5_keyblock *keyblocks, 403 int n_keys) 404 { 405 406 setkey_arg arg; 407 generic_ret *r; 408 kadm5_server_handle_t handle = server_handle; 409 410 CHECK_HANDLE(server_handle); 411 412 arg.princ = princ; 413 arg.keyblocks = keyblocks; 414 arg.n_keys = n_keys; 415 arg.api_version = handle->api_version; 416 417 if(princ == NULL || keyblocks == NULL) 418 return EINVAL; 419 r = setkey_principal_1(&arg, handle->clnt); 420 if(r == NULL) 421 return KADM5_RPC_ERROR; 422 return r->code; 423 } 424 425 kadm5_ret_t 426 kadm5_setkey_principal_3(void *server_handle, 427 krb5_principal princ, 428 krb5_boolean keepold, int n_ks_tuple, 429 krb5_key_salt_tuple *ks_tuple, 430 krb5_keyblock *keyblocks, 431 int n_keys) 432 { 433 setkey3_arg arg; 434 generic_ret *r; 435 kadm5_server_handle_t handle = server_handle; 436 437 CHECK_HANDLE(server_handle); 438 439 arg.princ = princ; 440 arg.keyblocks = keyblocks; 441 arg.n_keys = n_keys; 442 arg.api_version = handle->api_version; 443 arg.keepold = keepold; 444 arg.n_ks_tuple = n_ks_tuple; 445 arg.ks_tuple = ks_tuple; 446 447 if(princ == NULL || keyblocks == NULL) 448 return EINVAL; 449 r = setkey_principal3_1(&arg, handle->clnt); 450 if(r == NULL) 451 return KADM5_RPC_ERROR; 452 return r->code; 453 } 454 455 /* 456 * Solaris Kerberos: 457 * This routine implements just the "old" randkey_principal code. 458 * The code in the kadmin client sometimes needs to call this 459 * directly when the kadm5_randkey_principal_3 call fails. 460 * 461 * The kadmin client utility uses a specific set of key/salt tuples, 462 * so the standard fallback in kadm5_randkey_principal (see below) 463 * will not work because it would result in kadm5_randkey_principal_3 464 * being called twice - once with the specific key/salts specified by 465 * kadmin and once with the NULL set (used to indicate that the server 466 * should use the full set of supported enctypes). Making this 467 * routine separate makes the code simpler and avoids making the 468 * kadm5_randkey_principal_3 twice from kadmin. 469 */ 470 kadm5_ret_t 471 kadm5_randkey_principal_old(void *server_handle, 472 krb5_principal princ, 473 krb5_keyblock **key, 474 int *n_keys) 475 { 476 chrand_arg arg; 477 chrand_ret *r; 478 kadm5_server_handle_t handle = server_handle; 479 int i, ret; 480 481 /* For safety */ 482 if (n_keys) 483 *n_keys = 0; 484 if (key) 485 *key = NULL; 486 CHECK_HANDLE(server_handle); 487 488 arg.princ = princ; 489 arg.api_version = handle->api_version; 490 491 if(princ == NULL) 492 return EINVAL; 493 r = chrand_principal_1(&arg, handle->clnt); 494 if (r == NULL) 495 return KADM5_RPC_ERROR; 496 if (handle->api_version == KADM5_API_VERSION_1) { 497 if (key) 498 krb5_copy_keyblock(handle->context, &r->key, key); 499 } else if (key && (r->n_keys > 0)) { 500 *key = (krb5_keyblock *) malloc( 501 r->n_keys*sizeof(krb5_keyblock)); 502 if (*key == NULL) 503 return ENOMEM; 504 for (i = 0; i < r->n_keys; i++) { 505 ret = krb5_copy_keyblock_contents( 506 handle->context, 507 &r->keys[i], 508 &(*key)[i]); 509 if (ret) { 510 free(*key); 511 *key = NULL; 512 return ENOMEM; 513 } 514 } 515 if (n_keys) 516 *n_keys = r->n_keys; 517 } 518 return (r->code); 519 } 520 521 kadm5_ret_t 522 kadm5_randkey_principal_3(void *server_handle, 523 krb5_principal princ, 524 krb5_boolean keepold, int n_ks_tuple, 525 krb5_key_salt_tuple *ks_tuple, 526 krb5_keyblock **key, int *n_keys) 527 { 528 chrand3_arg arg; 529 chrand_ret *r; 530 krb5_keyblock new; 531 kadm5_server_handle_t handle = server_handle; 532 int i, ret; 533 534 /* For safety */ 535 if (n_keys) 536 *n_keys = 0; 537 if (key) 538 *key = NULL; 539 540 CHECK_HANDLE(server_handle); 541 542 arg.princ = princ; 543 arg.api_version = handle->api_version; 544 arg.keepold = keepold; 545 arg.n_ks_tuple = n_ks_tuple; 546 arg.ks_tuple = ks_tuple; 547 548 if(princ == NULL) 549 return EINVAL; 550 r = chrand_principal3_1(&arg, handle->clnt); 551 if(r == NULL) 552 return KADM5_RPC_ERROR; 553 if (handle->api_version == KADM5_API_VERSION_1) { 554 if (key) 555 krb5_copy_keyblock(handle->context, &r->key, key); 556 } else if (key && (r->n_keys > 0)) { 557 *key = (krb5_keyblock *) 558 malloc(r->n_keys*sizeof(krb5_keyblock)); 559 if (*key == NULL) 560 return ENOMEM; 561 for (i = 0; i < r->n_keys; i++) { 562 ret = krb5_copy_keyblock_contents(handle->context, 563 &r->keys[i], 564 &(*key)[i]); 565 if (ret) { 566 free(*key); 567 *key = NULL; 568 return ENOMEM; 569 } 570 } 571 if (n_keys) 572 *n_keys = r->n_keys; 573 } 574 575 return r->code; 576 } 577 578 kadm5_ret_t 579 kadm5_randkey_principal(void *server_handle, 580 krb5_principal princ, 581 krb5_keyblock **key, int *n_keys) 582 { 583 584 kadm5_ret_t kret; 585 586 /* 587 * Default to trying the newest API to insure that the full 588 * set of enctypes is created. 589 */ 590 kret = kadm5_randkey_principal_3(server_handle, princ, FALSE, 591 0, NULL, key, n_keys); 592 593 /* 594 * We will get an RPC error if the RPC call failed which 595 * will normally indicate that the remote procedure did not 596 * exist on the server, so try the older API. 597 */ 598 if (kret == KADM5_RPC_ERROR) { 599 kret = kadm5_randkey_principal_old(server_handle, princ, 600 key, n_keys); 601 } 602 return (kret); 603 } 604 605 /* not supported on client side */ 606 kadm5_ret_t kadm5_decrypt_key(void *server_handle, 607 kadm5_principal_ent_t entry, krb5_int32 608 ktype, krb5_int32 stype, krb5_int32 609 kvno, krb5_keyblock *keyblock, 610 krb5_keysalt *keysalt, int *kvnop) 611 { 612 return EINVAL; 613 } 614