1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved 4 * 5 */ 6 7 #include <k5-int.h> 8 #include <socket-utils.h> 9 #include <gssapi/gssapi.h> 10 #include <gssapi/gssapi_krb5.h> /* for gss_nt_krb5_name */ 11 #include <krb5.h> 12 #include <kadm5/admin.h> 13 #include <kadm5/kadm_rpc.h> 14 #include <kadm5/server_internal.h> 15 #include <syslog.h> 16 #include <adm_proto.h> /* krb5_klog_syslog */ 17 #include "misc.h" 18 #include "auth.h" 19 20 /* A principal changing its own keys may retain at most this many key 21 * versions. */ 22 #define MAX_SELF_KEEPOLD 5 23 24 extern gss_name_t gss_changepw_name; 25 extern gss_name_t gss_oldchangepw_name; 26 extern void * global_server_handle; 27 28 #define CHANGEPW_SERVICE(rqstp) \ 29 (cmp_gss_names_rel_1(acceptor_name(rqstp->rq_svccred), gss_changepw_name) | \ 30 (gss_oldchangepw_name && \ 31 cmp_gss_names_rel_1(acceptor_name(rqstp->rq_svccred), \ 32 gss_oldchangepw_name))) 33 34 35 static int gss_to_krb5_name(kadm5_server_handle_t handle, 36 gss_name_t gss_name, krb5_principal *princ); 37 38 static int gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str); 39 40 static gss_name_t acceptor_name(gss_ctx_id_t context); 41 42 gss_name_t rqst2name(struct svc_req *rqstp); 43 44 static int cmp_gss_names(gss_name_t n1, gss_name_t n2) 45 { 46 OM_uint32 emin; 47 int equal; 48 49 if (GSS_ERROR(gss_compare_name(&emin, n1, n2, &equal))) 50 return(0); 51 52 return(equal); 53 } 54 55 /* Does a comparison of the names and then releases the first entity */ 56 /* For use above in CHANGEPW_SERVICE */ 57 static int cmp_gss_names_rel_1(gss_name_t n1, gss_name_t n2) 58 { 59 OM_uint32 min_stat; 60 int ret; 61 62 ret = cmp_gss_names(n1, n2); 63 if (n1) (void) gss_release_name(&min_stat, &n1); 64 return ret; 65 } 66 67 /* 68 * Function check_handle 69 * 70 * Purpose: Check a server handle and return a com_err code if it is 71 * invalid or 0 if it is valid. 72 * 73 * Arguments: 74 * 75 * handle The server handle. 76 */ 77 78 static int check_handle(void *handle) 79 { 80 CHECK_HANDLE(handle); 81 return 0; 82 } 83 84 /* 85 * Function: new_server_handle 86 * 87 * Purpose: Constructs a server handle suitable for passing into the 88 * server library API functions, by folding the client's API version 89 * and calling principal into the server handle returned by 90 * kadm5_init. 91 * 92 * Arguments: 93 * api_version (input) The API version specified by the client 94 * rqstp (input) The RPC request 95 * handle (output) The returned handle 96 * <return value> (output) An error code, or 0 if no error occurred 97 * 98 * Effects: 99 * Returns a pointer to allocated storage containing the server 100 * handle. If an error occurs, then no allocated storage is 101 * returned, and the return value of the function will be a 102 * non-zero com_err code. 103 * 104 * The allocated storage for the handle should be freed with 105 * free_server_handle (see below) when it is no longer needed. 106 */ 107 108 static kadm5_ret_t new_server_handle(krb5_ui_4 api_version, 109 struct svc_req *rqstp, 110 kadm5_server_handle_t 111 *out_handle) 112 { 113 kadm5_server_handle_t handle; 114 115 *out_handle = NULL; 116 117 if (! (handle = (kadm5_server_handle_t) 118 malloc(sizeof(*handle)))) 119 return ENOMEM; 120 121 *handle = *(kadm5_server_handle_t)global_server_handle; 122 handle->api_version = api_version; 123 124 if (! gss_to_krb5_name(handle, rqst2name(rqstp), 125 &handle->current_caller)) { 126 free(handle); 127 return KADM5_FAILURE; 128 } 129 130 *out_handle = handle; 131 return 0; 132 } 133 134 /* 135 * Function: free_server_handle 136 * 137 * Purpose: Free handle memory allocated by new_server_handle 138 * 139 * Arguments: 140 * handle (input/output) The handle to free 141 */ 142 static void free_server_handle(kadm5_server_handle_t handle) 143 { 144 if (!handle) 145 return; 146 krb5_free_principal(handle->context, handle->current_caller); 147 free(handle); 148 } 149 150 /* Result is stored in a static buffer and is invalidated by the next call. */ 151 const char * 152 client_addr(SVCXPRT *xprt) 153 { 154 static char abuf[128]; 155 struct sockaddr_storage ss; 156 socklen_t len = sizeof(ss); 157 158 if (getpeername(xprt->xp_sock, ss2sa(&ss), &len) != 0) 159 return "(unknown)"; 160 k5_print_addr(ss2sa(&ss), abuf, sizeof(abuf)); 161 return abuf; 162 } 163 164 /* 165 * Function: setup_gss_names 166 * 167 * Purpose: Create printable representations of the client and server 168 * names. 169 * 170 * Arguments: 171 * rqstp (r) the RPC request 172 * client_name (w) the gss_buffer_t for the client name 173 * server_name (w) the gss_buffer_t for the server name 174 * 175 * Effects: 176 * 177 * Unparses the client and server names into client_name and 178 * server_name, both of which must be freed by the caller. Returns 0 179 * on success and -1 on failure. 180 */ 181 int setup_gss_names(struct svc_req *rqstp, 182 gss_buffer_desc *client_name, 183 gss_buffer_desc *server_name) 184 { 185 OM_uint32 maj_stat, min_stat; 186 gss_name_t server_gss_name; 187 188 if (gss_name_to_string(rqst2name(rqstp), client_name) != 0) 189 return -1; 190 maj_stat = gss_inquire_context(&min_stat, rqstp->rq_svccred, NULL, 191 &server_gss_name, NULL, NULL, NULL, 192 NULL, NULL); 193 if (maj_stat != GSS_S_COMPLETE) { 194 gss_release_buffer(&min_stat, client_name); 195 gss_release_name(&min_stat, &server_gss_name); 196 return -1; 197 } 198 if (gss_name_to_string(server_gss_name, server_name) != 0) { 199 gss_release_buffer(&min_stat, client_name); 200 gss_release_name(&min_stat, &server_gss_name); 201 return -1; 202 } 203 gss_release_name(&min_stat, &server_gss_name); 204 return 0; 205 } 206 207 static gss_name_t acceptor_name(gss_ctx_id_t context) 208 { 209 OM_uint32 maj_stat, min_stat; 210 gss_name_t name; 211 212 maj_stat = gss_inquire_context(&min_stat, context, NULL, &name, 213 NULL, NULL, NULL, NULL, NULL); 214 if (maj_stat != GSS_S_COMPLETE) 215 return NULL; 216 return name; 217 } 218 219 static int gss_to_krb5_name(kadm5_server_handle_t handle, 220 gss_name_t gss_name, krb5_principal *princ) 221 { 222 krb5_error_code ret; 223 OM_uint32 minor_stat; 224 gss_buffer_desc gss_str; 225 int success; 226 char *s; 227 228 if (gss_name_to_string(gss_name, &gss_str) != 0) 229 return 0; 230 s = k5memdup0(gss_str.value, gss_str.length, &ret); 231 if (s == NULL) { 232 gss_release_buffer(&minor_stat, &gss_str); 233 return 0; 234 } 235 success = (krb5_parse_name(handle->context, s, princ) == 0); 236 free(s); 237 gss_release_buffer(&minor_stat, &gss_str); 238 return success; 239 } 240 241 static int 242 gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str) 243 { 244 OM_uint32 status, minor_stat; 245 gss_OID gss_type; 246 const char pref[] = KRB5_WELLKNOWN_NAMESTR "/" KRB5_ANONYMOUS_PRINCSTR "@"; 247 const size_t preflen = sizeof(pref) - 1; 248 249 status = gss_display_name(&minor_stat, gss_name, str, &gss_type); 250 if (status != GSS_S_COMPLETE) 251 return 1; 252 if (gss_oid_equal(gss_type, GSS_C_NT_ANONYMOUS)) { 253 /* Guard against non-krb5 mechs with different anonymous displays. */ 254 if (str->length < preflen || memcmp(str->value, pref, preflen) != 0) 255 return 1; 256 } else if (!gss_oid_equal(gss_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { 257 return 1; 258 } 259 return 0; 260 } 261 262 /* 263 * Perform common initialization for server stub functions. A subset of the 264 * output arguments may be set on failure; the caller is responsible for 265 * initializing outputs and calling stub_cleanup() on success or failure. 266 * princ and princ_str_out may be NULL to omit unparsing a principal name. 267 */ 268 static kadm5_ret_t 269 stub_setup(krb5_ui_4 api_version, struct svc_req *rqstp, krb5_principal princ, 270 kadm5_server_handle_t *handle_out, krb5_ui_4 *api_version_out, 271 gss_buffer_t client_name_out, gss_buffer_t service_name_out, 272 char **princ_str_out, kadm5_principal_ent_rec *rec_out) 273 { 274 kadm5_ret_t ret; 275 276 ret = new_server_handle(api_version, rqstp, handle_out); 277 if (ret) 278 return ret; 279 280 ret = check_handle(*handle_out); 281 if (ret) 282 return ret; 283 284 *api_version_out = (*handle_out)->api_version; 285 286 if (setup_gss_names(rqstp, client_name_out, service_name_out) < 0) 287 return KADM5_FAILURE; 288 289 if (princ_str_out != NULL) { 290 if (princ == NULL) 291 return KADM5_BAD_PRINCIPAL; 292 if (krb5_unparse_name((*handle_out)->context, princ, princ_str_out)) 293 return KADM5_BAD_PRINCIPAL; 294 } 295 296 if (rec_out != NULL) { 297 if (princ == NULL) 298 return KADM5_BAD_PRINCIPAL; 299 return kadm5_get_principal(*handle_out, princ, rec_out, 300 KADM5_PRINCIPAL | KADM5_ATTRIBUTES); 301 } 302 303 return KADM5_OK; 304 } 305 306 /* Perform common cleanup for server stub functions. */ 307 static void 308 stub_cleanup(kadm5_server_handle_t handle, char *princ_str, 309 gss_buffer_t client_name, gss_buffer_t service_name) 310 { 311 OM_uint32 minor_stat; 312 313 auth_end(handle->context); 314 free_server_handle(handle); 315 free(princ_str); 316 gss_release_buffer(&minor_stat, client_name); 317 gss_release_buffer(&minor_stat, service_name); 318 } 319 320 static krb5_boolean 321 stub_auth(kadm5_server_handle_t handle, int opcode, krb5_const_principal p1, 322 krb5_const_principal p2, const char *s1, const char *s2) 323 { 324 return auth(handle->context, opcode, handle->current_caller, p1, p2, 325 s1, s2, NULL, 0); 326 } 327 328 static krb5_boolean 329 stub_auth_pol(kadm5_server_handle_t handle, int opcode, const char *policy, 330 const kadm5_policy_ent_rec *polent, long mask) 331 { 332 return auth(handle->context, opcode, handle->current_caller, NULL, NULL, 333 policy, NULL, polent, mask); 334 } 335 336 static krb5_boolean 337 stub_auth_restrict(kadm5_server_handle_t handle, int opcode, 338 krb5_const_principal princ, kadm5_principal_ent_t ent, 339 long *mask) 340 { 341 return auth_restrict(handle->context, opcode, handle->current_caller, 342 princ, ent, mask); 343 } 344 345 /* Return true if the client authenticated to kadmin/changepw and princ is not 346 * the client principal. */ 347 static krb5_boolean 348 changepw_not_self(kadm5_server_handle_t handle, struct svc_req *rqstp, 349 krb5_const_principal princ) 350 { 351 return CHANGEPW_SERVICE(rqstp) && 352 !krb5_principal_compare(handle->context, handle->current_caller, 353 princ); 354 } 355 356 static krb5_boolean 357 ticket_is_initial(struct svc_req *rqstp) 358 { 359 OM_uint32 status, minor_stat; 360 krb5_flags flags; 361 362 status = gss_krb5_get_tkt_flags(&minor_stat, rqstp->rq_svccred, &flags); 363 if (status != GSS_S_COMPLETE) 364 return 0; 365 return (flags & TKT_FLG_INITIAL) != 0; 366 } 367 368 /* If a key change request is for the client's own principal, verify that the 369 * client used an initial ticket and enforce the policy min_life. */ 370 static kadm5_ret_t 371 check_self_keychange(kadm5_server_handle_t handle, struct svc_req *rqstp, 372 krb5_principal princ) 373 { 374 if (!krb5_principal_compare(handle->context, handle->current_caller, 375 princ)) 376 return 0; 377 378 if (!ticket_is_initial(rqstp)) 379 return KADM5_AUTH_INITIAL; 380 381 return check_min_life(handle, princ, NULL, 0); 382 } 383 384 /* 385 * Return the appropriate libkadm5 keepold value for a key change request, 386 * given the boolean keepold input from the client. 0 means discard all old 387 * keys, 1 means retain all old keys, and a greater value means to retain that 388 * many key versions including the new one. A principal modifying its own keys 389 * is allowed to retain only a limited number of key versions. 390 */ 391 static unsigned int 392 clamp_self_keepold(kadm5_server_handle_t handle, krb5_principal princ, 393 krb5_boolean keepold) 394 { 395 if (!keepold) 396 return 0; 397 if (krb5_principal_compare(handle->context, handle->current_caller, princ)) 398 return MAX_SELF_KEEPOLD; 399 return 1; 400 } 401 402 static int 403 log_unauth( 404 char *op, 405 char *target, 406 gss_buffer_t client, 407 gss_buffer_t server, 408 struct svc_req *rqstp) 409 { 410 size_t tlen, clen, slen; 411 char *tdots, *cdots, *sdots; 412 413 tlen = strlen(target); 414 trunc_name(&tlen, &tdots); 415 clen = client->length; 416 trunc_name(&clen, &cdots); 417 slen = server->length; 418 trunc_name(&slen, &sdots); 419 420 /* okay to cast lengths to int because trunc_name limits max value */ 421 return krb5_klog_syslog(LOG_NOTICE, 422 _("Unauthorized request: %s, %.*s%s, " 423 "client=%.*s%s, service=%.*s%s, addr=%s"), 424 op, (int)tlen, target, tdots, 425 (int)clen, (char *)client->value, cdots, 426 (int)slen, (char *)server->value, sdots, 427 client_addr(rqstp->rq_xprt)); 428 } 429 430 static int 431 log_done( 432 char *op, 433 char *target, 434 const char *errmsg, 435 gss_buffer_t client, 436 gss_buffer_t server, 437 struct svc_req *rqstp) 438 { 439 size_t tlen, clen, slen; 440 char *tdots, *cdots, *sdots; 441 442 if (errmsg == NULL) 443 errmsg = _("success"); 444 tlen = strlen(target); 445 trunc_name(&tlen, &tdots); 446 clen = client->length; 447 trunc_name(&clen, &cdots); 448 slen = server->length; 449 trunc_name(&slen, &sdots); 450 451 /* okay to cast lengths to int because trunc_name limits max value */ 452 return krb5_klog_syslog(LOG_NOTICE, 453 _("Request: %s, %.*s%s, %s, " 454 "client=%.*s%s, service=%.*s%s, addr=%s"), 455 op, (int)tlen, target, tdots, errmsg, 456 (int)clen, (char *)client->value, cdots, 457 (int)slen, (char *)server->value, sdots, 458 client_addr(rqstp->rq_xprt)); 459 } 460 461 bool_t 462 create_principal_2_svc(cprinc_arg *arg, generic_ret *ret, 463 struct svc_req *rqstp) 464 { 465 char *prime_arg = NULL; 466 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 467 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 468 kadm5_server_handle_t handle; 469 const char *errmsg = NULL; 470 471 ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, 472 &handle, &ret->api_version, &client_name, 473 &service_name, &prime_arg, NULL); 474 if (ret->code) 475 goto exit_func; 476 477 if (CHANGEPW_SERVICE(rqstp) || 478 !stub_auth_restrict(handle, OP_ADDPRINC, arg->rec.principal, 479 &arg->rec, &arg->mask)) { 480 ret->code = KADM5_AUTH_ADD; 481 log_unauth("kadm5_create_principal", prime_arg, 482 &client_name, &service_name, rqstp); 483 } else { 484 ret->code = kadm5_create_principal(handle, &arg->rec, arg->mask, 485 arg->passwd); 486 487 if (ret->code != 0) 488 errmsg = krb5_get_error_message(handle->context, ret->code); 489 490 log_done("kadm5_create_principal", prime_arg, errmsg, 491 &client_name, &service_name, rqstp); 492 493 if (errmsg != NULL) 494 krb5_free_error_message(handle->context, errmsg); 495 } 496 497 exit_func: 498 stub_cleanup(handle, prime_arg, &client_name, &service_name); 499 return TRUE; 500 } 501 502 bool_t 503 create_principal3_2_svc(cprinc3_arg *arg, generic_ret *ret, 504 struct svc_req *rqstp) 505 { 506 char *prime_arg = NULL; 507 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 508 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 509 kadm5_server_handle_t handle; 510 const char *errmsg = NULL; 511 512 ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, 513 &handle, &ret->api_version, &client_name, 514 &service_name, &prime_arg, NULL); 515 if (ret->code) 516 goto exit_func; 517 518 if (CHANGEPW_SERVICE(rqstp) || 519 !stub_auth_restrict(handle, OP_ADDPRINC, arg->rec.principal, &arg->rec, 520 &arg->mask)) { 521 ret->code = KADM5_AUTH_ADD; 522 log_unauth("kadm5_create_principal", prime_arg, 523 &client_name, &service_name, rqstp); 524 } else { 525 ret->code = kadm5_create_principal_3(handle, &arg->rec, arg->mask, 526 arg->n_ks_tuple, arg->ks_tuple, 527 arg->passwd); 528 if (ret->code != 0) 529 errmsg = krb5_get_error_message(handle->context, ret->code); 530 531 log_done("kadm5_create_principal", prime_arg, errmsg, 532 &client_name, &service_name, rqstp); 533 534 if (errmsg != NULL) 535 krb5_free_error_message(handle->context, errmsg); 536 } 537 538 exit_func: 539 stub_cleanup(handle, prime_arg, &client_name, &service_name); 540 return TRUE; 541 } 542 543 /* Return KADM5_PROTECT_KEYS if KRB5_KDB_LOCKDOWN_KEYS is set for rec. */ 544 static inline kadm5_ret_t 545 check_lockdown(kadm5_principal_ent_t rec) 546 { 547 return (rec->attributes & KRB5_KDB_LOCKDOWN_KEYS) ? KADM5_PROTECT_KEYS : 0; 548 } 549 550 static kadm5_ret_t 551 check_lockdown_by_princ(kadm5_server_handle_t handle, krb5_principal princ) 552 { 553 kadm5_principal_ent_rec rec; 554 kadm5_ret_t ret; 555 556 ret = kadm5_get_principal(handle, princ, &rec, KADM5_ATTRIBUTES); 557 if (ret) 558 return ret; 559 ret = check_lockdown(&rec); 560 kadm5_free_principal_ent(handle, &rec); 561 return ret; 562 } 563 564 bool_t 565 delete_principal_2_svc(dprinc_arg *arg, generic_ret *ret, 566 struct svc_req *rqstp) 567 { 568 char *prime_arg = NULL; 569 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 570 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 571 kadm5_server_handle_t handle; 572 const char *errmsg = NULL; 573 574 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 575 &ret->api_version, &client_name, &service_name, 576 &prime_arg, NULL); 577 if (ret->code) 578 goto exit_func; 579 580 if (CHANGEPW_SERVICE(rqstp) || 581 !stub_auth(handle, OP_DELPRINC, arg->princ, NULL, NULL, NULL)) { 582 ret->code = KADM5_AUTH_DELETE; 583 log_unauth("kadm5_delete_principal", prime_arg, 584 &client_name, &service_name, rqstp); 585 } else { 586 ret->code = check_lockdown_by_princ(handle, arg->princ); 587 if (ret->code == KADM5_PROTECT_KEYS) { 588 log_unauth("kadm5_delete_principal", prime_arg, &client_name, 589 &service_name, rqstp); 590 ret->code = KADM5_AUTH_DELETE; 591 } 592 } 593 594 if (ret->code == KADM5_OK) 595 ret->code = kadm5_delete_principal(handle, arg->princ); 596 if (ret->code != KADM5_AUTH_DELETE) { 597 if (ret->code != 0) 598 errmsg = krb5_get_error_message(handle->context, ret->code); 599 600 log_done("kadm5_delete_principal", prime_arg, errmsg, 601 &client_name, &service_name, rqstp); 602 603 if (errmsg != NULL) 604 krb5_free_error_message(handle->context, errmsg); 605 606 } 607 608 exit_func: 609 stub_cleanup(handle, prime_arg, &client_name, &service_name); 610 return TRUE; 611 } 612 613 bool_t 614 modify_principal_2_svc(mprinc_arg *arg, generic_ret *ret, 615 struct svc_req *rqstp) 616 { 617 char *prime_arg = NULL; 618 kadm5_principal_ent_rec rec = { 0 }, rec_copy; 619 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 620 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 621 kadm5_server_handle_t handle; 622 const char *errmsg = NULL; 623 624 ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, 625 &handle, &ret->api_version, &client_name, 626 &service_name, &prime_arg, &rec); 627 if (ret->code) 628 goto exit_func; 629 630 if (CHANGEPW_SERVICE(rqstp) || 631 !stub_auth_restrict(handle, OP_MODPRINC, rec.principal, &arg->rec, 632 &arg->mask)) { 633 ret->code = KADM5_AUTH_MODIFY; 634 log_unauth("kadm5_modify_principal", prime_arg, 635 &client_name, &service_name, rqstp); 636 } else if ((arg->mask & KADM5_ATTRIBUTES) && 637 (!(arg->rec.attributes & KRB5_KDB_LOCKDOWN_KEYS))) { 638 ret->code = check_lockdown(&rec); 639 if (ret->code == KADM5_PROTECT_KEYS) { 640 log_unauth("kadm5_modify_principal", prime_arg, &client_name, 641 &service_name, rqstp); 642 ret->code = KADM5_AUTH_MODIFY; 643 } 644 } 645 646 if (ret->code == KADM5_OK) { 647 /* Modify via the canonicalized principal name using a shallow copy of 648 * arg->rec, to ensure consistency with the ACL check. */ 649 rec_copy = arg->rec; 650 rec_copy.principal = rec.principal; 651 ret->code = kadm5_modify_principal(handle, &rec_copy, arg->mask); 652 if (ret->code != 0) 653 errmsg = krb5_get_error_message(handle->context, ret->code); 654 655 log_done("kadm5_modify_principal", prime_arg, errmsg, 656 &client_name, &service_name, rqstp); 657 658 if (errmsg != NULL) 659 krb5_free_error_message(handle->context, errmsg); 660 } 661 662 exit_func: 663 kadm5_free_principal_ent(handle, &rec); 664 stub_cleanup(handle, prime_arg, &client_name, &service_name); 665 return TRUE; 666 } 667 668 bool_t 669 rename_principal_2_svc(rprinc_arg *arg, generic_ret *ret, 670 struct svc_req *rqstp) 671 { 672 char *prime_arg1 = NULL, *prime_arg2 = NULL; 673 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 674 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 675 kadm5_server_handle_t handle; 676 const char *errmsg = NULL; 677 size_t tlen1, tlen2, clen, slen; 678 char *tdots1, *tdots2, *cdots, *sdots; 679 680 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, 681 &ret->api_version, &client_name, &service_name, 682 NULL, NULL); 683 if (ret->code) 684 goto exit_func; 685 686 if (krb5_unparse_name(handle->context, arg->src, &prime_arg1) || 687 krb5_unparse_name(handle->context, arg->dest, &prime_arg2)) { 688 ret->code = KADM5_BAD_PRINCIPAL; 689 goto exit_func; 690 } 691 tlen1 = strlen(prime_arg1); 692 trunc_name(&tlen1, &tdots1); 693 tlen2 = strlen(prime_arg2); 694 trunc_name(&tlen2, &tdots2); 695 clen = client_name.length; 696 trunc_name(&clen, &cdots); 697 slen = service_name.length; 698 trunc_name(&slen, &sdots); 699 700 if (CHANGEPW_SERVICE(rqstp) || 701 !stub_auth(handle, OP_RENPRINC, arg->src, arg->dest, NULL, NULL)) { 702 ret->code = KADM5_AUTH_INSUFFICIENT; 703 log_unauth("kadm5_rename_principal", prime_arg1, &client_name, 704 &service_name, rqstp); 705 } else { 706 ret->code = check_lockdown_by_princ(handle, arg->src); 707 if (ret->code == KADM5_PROTECT_KEYS) { 708 log_unauth("kadm5_rename_principal", prime_arg1, &client_name, 709 &service_name, rqstp); 710 ret->code = KADM5_AUTH_DELETE; 711 } 712 } 713 if (ret->code != KADM5_OK) { 714 /* okay to cast lengths to int because trunc_name limits max value */ 715 krb5_klog_syslog(LOG_NOTICE, 716 _("Unauthorized request: kadm5_rename_principal, " 717 "%.*s%s to %.*s%s, " 718 "client=%.*s%s, service=%.*s%s, addr=%s"), 719 (int)tlen1, prime_arg1, tdots1, 720 (int)tlen2, prime_arg2, tdots2, 721 (int)clen, (char *)client_name.value, cdots, 722 (int)slen, (char *)service_name.value, sdots, 723 client_addr(rqstp->rq_xprt)); 724 } else { 725 ret->code = kadm5_rename_principal(handle, arg->src, arg->dest); 726 if (ret->code != 0) 727 errmsg = krb5_get_error_message(handle->context, ret->code); 728 729 /* okay to cast lengths to int because trunc_name limits max value */ 730 krb5_klog_syslog(LOG_NOTICE, 731 _("Request: kadm5_rename_principal, " 732 "%.*s%s to %.*s%s, %s, " 733 "client=%.*s%s, service=%.*s%s, addr=%s"), 734 (int)tlen1, prime_arg1, tdots1, 735 (int)tlen2, prime_arg2, tdots2, 736 errmsg ? errmsg : _("success"), 737 (int)clen, (char *)client_name.value, cdots, 738 (int)slen, (char *)service_name.value, sdots, 739 client_addr(rqstp->rq_xprt)); 740 741 if (errmsg != NULL) 742 krb5_free_error_message(handle->context, errmsg); 743 744 } 745 exit_func: 746 free(prime_arg1); 747 free(prime_arg2); 748 stub_cleanup(handle, NULL, &client_name, &service_name); 749 return TRUE; 750 } 751 752 bool_t 753 get_principal_2_svc(gprinc_arg *arg, gprinc_ret *ret, struct svc_req *rqstp) 754 { 755 char *funcname, *prime_arg = NULL; 756 kadm5_principal_ent_rec rec = { 0 }; 757 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 758 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 759 kadm5_server_handle_t handle; 760 const char *errmsg = NULL; 761 762 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 763 &ret->api_version, &client_name, &service_name, 764 &prime_arg, &rec); 765 if (ret->code) 766 goto exit_func; 767 768 funcname = "kadm5_get_principal"; 769 770 if (changepw_not_self(handle, rqstp, rec.principal) || 771 !stub_auth(handle, OP_GETPRINC, rec.principal, NULL, NULL, NULL)) { 772 ret->code = KADM5_AUTH_GET; 773 log_unauth(funcname, prime_arg, 774 &client_name, &service_name, rqstp); 775 } else { 776 ret->code = kadm5_get_principal(handle, rec.principal, &ret->rec, 777 arg->mask); 778 779 if (ret->code != 0) 780 errmsg = krb5_get_error_message(handle->context, ret->code); 781 782 log_done(funcname, prime_arg, errmsg, 783 &client_name, &service_name, rqstp); 784 785 if (errmsg != NULL) 786 krb5_free_error_message(handle->context, errmsg); 787 } 788 789 exit_func: 790 kadm5_free_principal_ent(handle, &rec); 791 stub_cleanup(handle, prime_arg, &client_name, &service_name); 792 return TRUE; 793 } 794 795 bool_t 796 get_princs_2_svc(gprincs_arg *arg, gprincs_ret *ret, struct svc_req *rqstp) 797 { 798 char *prime_arg = NULL; 799 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 800 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 801 kadm5_server_handle_t handle; 802 const char *errmsg = NULL; 803 804 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, 805 &ret->api_version, &client_name, &service_name, 806 NULL, NULL); 807 if (ret->code) 808 goto exit_func; 809 810 prime_arg = arg->exp; 811 if (prime_arg == NULL) 812 prime_arg = "*"; 813 814 if (CHANGEPW_SERVICE(rqstp) || 815 !stub_auth(handle, OP_LISTPRINCS, NULL, NULL, NULL, NULL)) { 816 ret->code = KADM5_AUTH_LIST; 817 log_unauth("kadm5_get_principals", prime_arg, 818 &client_name, &service_name, rqstp); 819 } else { 820 ret->code = kadm5_get_principals(handle, arg->exp, &ret->princs, 821 &ret->count); 822 if (ret->code != 0) 823 errmsg = krb5_get_error_message(handle->context, ret->code); 824 825 log_done("kadm5_get_principals", prime_arg, errmsg, 826 &client_name, &service_name, rqstp); 827 828 if (errmsg != NULL) 829 krb5_free_error_message(handle->context, errmsg); 830 831 } 832 833 exit_func: 834 stub_cleanup(handle, NULL, &client_name, &service_name); 835 return TRUE; 836 } 837 838 bool_t 839 chpass_principal_2_svc(chpass_arg *arg, generic_ret *ret, 840 struct svc_req *rqstp) 841 { 842 char *prime_arg = NULL; 843 kadm5_principal_ent_rec rec = { 0 }; 844 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 845 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 846 kadm5_server_handle_t handle; 847 const char *errmsg = NULL; 848 849 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 850 &ret->api_version, &client_name, &service_name, 851 &prime_arg, &rec); 852 if (ret->code) 853 goto exit_func; 854 855 ret->code = check_lockdown(&rec); 856 if (ret->code != KADM5_OK) { 857 if (ret->code == KADM5_PROTECT_KEYS) { 858 log_unauth("kadm5_chpass_principal", prime_arg, &client_name, 859 &service_name, rqstp); 860 ret->code = KADM5_AUTH_CHANGEPW; 861 } 862 } else if (changepw_not_self(handle, rqstp, rec.principal) || 863 !stub_auth(handle, OP_CPW, rec.principal, NULL, NULL, NULL)) { 864 ret->code = KADM5_AUTH_CHANGEPW; 865 log_unauth("kadm5_chpass_principal", prime_arg, 866 &client_name, &service_name, rqstp); 867 } else { 868 ret->code = check_self_keychange(handle, rqstp, rec.principal); 869 if (!ret->code) { 870 ret->code = kadm5_chpass_principal(handle, rec.principal, 871 arg->pass); 872 } 873 } 874 875 if (ret->code != KADM5_AUTH_CHANGEPW) { 876 if (ret->code != 0) 877 errmsg = krb5_get_error_message(handle->context, ret->code); 878 879 log_done("kadm5_chpass_principal", prime_arg, errmsg, 880 &client_name, &service_name, rqstp); 881 882 if (errmsg != NULL) 883 krb5_free_error_message(handle->context, errmsg); 884 } 885 886 exit_func: 887 kadm5_free_principal_ent(handle, &rec); 888 stub_cleanup(handle, prime_arg, &client_name, &service_name); 889 return TRUE; 890 } 891 892 bool_t 893 chpass_principal3_2_svc(chpass3_arg *arg, generic_ret *ret, 894 struct svc_req *rqstp) 895 { 896 char *prime_arg = NULL; 897 kadm5_principal_ent_rec rec = { 0 }; 898 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 899 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 900 unsigned int keepold; 901 kadm5_server_handle_t handle; 902 const char *errmsg = NULL; 903 904 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 905 &ret->api_version, &client_name, &service_name, 906 &prime_arg, &rec); 907 if (ret->code) 908 goto exit_func; 909 910 ret->code = check_lockdown(&rec); 911 if (ret->code != KADM5_OK) { 912 if (ret->code == KADM5_PROTECT_KEYS) { 913 log_unauth("kadm5_chpass_principal", prime_arg, &client_name, 914 &service_name, rqstp); 915 ret->code = KADM5_AUTH_CHANGEPW; 916 } 917 } else if (changepw_not_self(handle, rqstp, rec.principal) || 918 !stub_auth(handle, OP_CPW, rec.principal, NULL, NULL, NULL)) { 919 ret->code = KADM5_AUTH_CHANGEPW; 920 log_unauth("kadm5_chpass_principal", prime_arg, 921 &client_name, &service_name, rqstp); 922 } else { 923 ret->code = check_self_keychange(handle, rqstp, rec.principal); 924 if (!ret->code) { 925 keepold = clamp_self_keepold(handle, rec.principal, arg->keepold); 926 ret->code = kadm5_chpass_principal_3(handle, rec.principal, 927 keepold, arg->n_ks_tuple, 928 arg->ks_tuple, arg->pass); 929 } 930 } 931 932 if (ret->code != KADM5_AUTH_CHANGEPW) { 933 if (ret->code != 0) 934 errmsg = krb5_get_error_message(handle->context, ret->code); 935 936 log_done("kadm5_chpass_principal", prime_arg, errmsg, 937 &client_name, &service_name, rqstp); 938 939 if (errmsg != NULL) 940 krb5_free_error_message(handle->context, errmsg); 941 } 942 943 exit_func: 944 kadm5_free_principal_ent(handle, &rec); 945 stub_cleanup(handle, prime_arg, &client_name, &service_name); 946 return TRUE; 947 } 948 949 bool_t 950 setkey_principal_2_svc(setkey_arg *arg, generic_ret *ret, 951 struct svc_req *rqstp) 952 { 953 char *prime_arg = NULL; 954 kadm5_principal_ent_rec rec = { 0 }; 955 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 956 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 957 kadm5_server_handle_t handle; 958 const char *errmsg = NULL; 959 960 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 961 &ret->api_version, &client_name, &service_name, 962 &prime_arg, &rec); 963 if (ret->code) 964 goto exit_func; 965 966 ret->code = check_lockdown(&rec); 967 if (ret->code != KADM5_OK) { 968 if (ret->code == KADM5_PROTECT_KEYS) { 969 log_unauth("kadm5_setkey_principal", prime_arg, &client_name, 970 &service_name, rqstp); 971 ret->code = KADM5_AUTH_SETKEY; 972 } 973 } else if (!(CHANGEPW_SERVICE(rqstp)) && 974 stub_auth(handle, OP_SETKEY, rec.principal, NULL, NULL, NULL)) { 975 ret->code = kadm5_setkey_principal(handle, rec.principal, 976 arg->keyblocks, arg->n_keys); 977 } else { 978 log_unauth("kadm5_setkey_principal", prime_arg, 979 &client_name, &service_name, rqstp); 980 ret->code = KADM5_AUTH_SETKEY; 981 } 982 983 if (ret->code != KADM5_AUTH_SETKEY) { 984 if (ret->code != 0) 985 errmsg = krb5_get_error_message(handle->context, ret->code); 986 987 log_done("kadm5_setkey_principal", prime_arg, errmsg, 988 &client_name, &service_name, rqstp); 989 990 if (errmsg != NULL) 991 krb5_free_error_message(handle->context, errmsg); 992 } 993 994 exit_func: 995 kadm5_free_principal_ent(handle, &rec); 996 stub_cleanup(handle, prime_arg, &client_name, &service_name); 997 return TRUE; 998 } 999 1000 bool_t 1001 setkey_principal3_2_svc(setkey3_arg *arg, generic_ret *ret, 1002 struct svc_req *rqstp) 1003 { 1004 char *prime_arg = NULL; 1005 kadm5_principal_ent_rec rec = { 0 }; 1006 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1007 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1008 unsigned int keepold; 1009 kadm5_server_handle_t handle; 1010 const char *errmsg = NULL; 1011 1012 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 1013 &ret->api_version, &client_name, &service_name, 1014 &prime_arg, &rec); 1015 if (ret->code) 1016 goto exit_func; 1017 1018 ret->code = check_lockdown(&rec); 1019 if (ret->code != KADM5_OK) { 1020 if (ret->code == KADM5_PROTECT_KEYS) { 1021 log_unauth("kadm5_setkey_principal", prime_arg, &client_name, 1022 &service_name, rqstp); 1023 ret->code = KADM5_AUTH_SETKEY; 1024 } 1025 } else if (!(CHANGEPW_SERVICE(rqstp)) && 1026 stub_auth(handle, OP_SETKEY, rec.principal, NULL, NULL, NULL)) { 1027 keepold = clamp_self_keepold(handle, rec.principal, arg->keepold); 1028 ret->code = kadm5_setkey_principal_3(handle, rec.principal, keepold, 1029 arg->n_ks_tuple, arg->ks_tuple, 1030 arg->keyblocks, arg->n_keys); 1031 } else { 1032 log_unauth("kadm5_setkey_principal", prime_arg, 1033 &client_name, &service_name, rqstp); 1034 ret->code = KADM5_AUTH_SETKEY; 1035 } 1036 1037 if (ret->code != KADM5_AUTH_SETKEY) { 1038 if (ret->code != 0) 1039 errmsg = krb5_get_error_message(handle->context, ret->code); 1040 1041 log_done("kadm5_setkey_principal", prime_arg, errmsg, 1042 &client_name, &service_name, rqstp); 1043 1044 if (errmsg != NULL) 1045 krb5_free_error_message(handle->context, errmsg); 1046 } 1047 1048 exit_func: 1049 kadm5_free_principal_ent(handle, &rec); 1050 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1051 return TRUE; 1052 } 1053 1054 bool_t 1055 setkey_principal4_2_svc(setkey4_arg *arg, generic_ret *ret, 1056 struct svc_req *rqstp) 1057 { 1058 char *prime_arg = NULL; 1059 kadm5_principal_ent_rec rec = { 0 }; 1060 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1061 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1062 unsigned int keepold; 1063 kadm5_server_handle_t handle; 1064 const char *errmsg = NULL; 1065 1066 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 1067 &ret->api_version, &client_name, &service_name, 1068 &prime_arg, &rec); 1069 if (ret->code) 1070 goto exit_func; 1071 1072 ret->code = check_lockdown(&rec); 1073 if (ret->code != KADM5_OK) { 1074 if (ret->code == KADM5_PROTECT_KEYS) { 1075 log_unauth("kadm5_setkey_principal", prime_arg, &client_name, 1076 &service_name, rqstp); 1077 ret->code = KADM5_AUTH_SETKEY; 1078 } 1079 } else if (!(CHANGEPW_SERVICE(rqstp)) && 1080 stub_auth(handle, OP_SETKEY, rec.principal, NULL, NULL, NULL)) { 1081 keepold = clamp_self_keepold(handle, rec.principal, arg->keepold); 1082 ret->code = kadm5_setkey_principal_4(handle, rec.principal, keepold, 1083 arg->key_data, arg->n_key_data); 1084 } else { 1085 log_unauth("kadm5_setkey_principal", prime_arg, &client_name, 1086 &service_name, rqstp); 1087 ret->code = KADM5_AUTH_SETKEY; 1088 } 1089 1090 if (ret->code != KADM5_AUTH_SETKEY) { 1091 if (ret->code != 0) 1092 errmsg = krb5_get_error_message(handle->context, ret->code); 1093 1094 log_done("kadm5_setkey_principal", prime_arg, errmsg, &client_name, 1095 &service_name, rqstp); 1096 1097 if (errmsg != NULL) 1098 krb5_free_error_message(handle->context, errmsg); 1099 } 1100 1101 exit_func: 1102 kadm5_free_principal_ent(handle, &rec); 1103 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1104 return TRUE; 1105 } 1106 1107 /* Empty out *keys / *nkeys if princ is protected with the lockdown 1108 * attribute, or if we fail to check. */ 1109 static kadm5_ret_t 1110 chrand_check_lockdown(kadm5_server_handle_t handle, kadm5_principal_ent_t rec, 1111 krb5_keyblock **keys, int *nkeys) 1112 { 1113 kadm5_ret_t ret; 1114 int i; 1115 1116 ret = check_lockdown(rec); 1117 if (!ret) 1118 return 0; 1119 1120 for (i = 0; i < *nkeys; i++) 1121 krb5_free_keyblock_contents(handle->context, &((*keys)[i])); 1122 free(*keys); 1123 *keys = NULL; 1124 *nkeys = 0; 1125 return (ret == KADM5_PROTECT_KEYS) ? KADM5_OK : ret; 1126 } 1127 1128 bool_t 1129 chrand_principal_2_svc(chrand_arg *arg, chrand_ret *ret, struct svc_req *rqstp) 1130 { 1131 char *funcname, *prime_arg = NULL; 1132 kadm5_principal_ent_rec rec = { 0 }; 1133 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1134 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1135 krb5_keyblock *k; 1136 int nkeys; 1137 kadm5_server_handle_t handle; 1138 const char *errmsg = NULL; 1139 1140 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 1141 &ret->api_version, &client_name, &service_name, 1142 &prime_arg, &rec); 1143 if (ret->code) 1144 goto exit_func; 1145 1146 funcname = "kadm5_randkey_principal"; 1147 1148 if (changepw_not_self(handle, rqstp, rec.principal) || 1149 !stub_auth(handle, OP_CHRAND, rec.principal, NULL, NULL, NULL)) { 1150 ret->code = KADM5_AUTH_CHANGEPW; 1151 log_unauth(funcname, prime_arg, 1152 &client_name, &service_name, rqstp); 1153 } else { 1154 ret->code = check_self_keychange(handle, rqstp, rec.principal); 1155 if (!ret->code) { 1156 ret->code = kadm5_randkey_principal(handle, rec.principal, 1157 &k, &nkeys); 1158 } 1159 } 1160 1161 if (ret->code == KADM5_OK) { 1162 ret->code = chrand_check_lockdown(handle, &rec, &k, &nkeys); 1163 if (ret->code == KADM5_PROTECT_KEYS) 1164 ret->code = KADM5_OK; 1165 ret->keys = k; 1166 ret->n_keys = nkeys; 1167 } 1168 1169 if (ret->code != KADM5_AUTH_CHANGEPW) { 1170 if (ret->code != 0) 1171 errmsg = krb5_get_error_message(handle->context, ret->code); 1172 1173 log_done(funcname, prime_arg, errmsg, 1174 &client_name, &service_name, rqstp); 1175 1176 if (errmsg != NULL) 1177 krb5_free_error_message(handle->context, errmsg); 1178 } 1179 1180 exit_func: 1181 kadm5_free_principal_ent(handle, &rec); 1182 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1183 return TRUE; 1184 } 1185 1186 bool_t 1187 chrand_principal3_2_svc(chrand3_arg *arg, chrand_ret *ret, 1188 struct svc_req *rqstp) 1189 { 1190 char *funcname, *prime_arg = NULL; 1191 kadm5_principal_ent_rec rec = { 0 }; 1192 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1193 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1194 krb5_keyblock *k; 1195 int nkeys; 1196 unsigned int keepold; 1197 kadm5_server_handle_t handle; 1198 const char *errmsg = NULL; 1199 1200 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 1201 &ret->api_version, &client_name, &service_name, 1202 &prime_arg, &rec); 1203 if (ret->code) 1204 goto exit_func; 1205 1206 funcname = "kadm5_randkey_principal"; 1207 1208 if (changepw_not_self(handle, rqstp, rec.principal) || 1209 !stub_auth(handle, OP_CHRAND, rec.principal, NULL, NULL, NULL)) { 1210 ret->code = KADM5_AUTH_CHANGEPW; 1211 log_unauth(funcname, prime_arg, 1212 &client_name, &service_name, rqstp); 1213 } else { 1214 ret->code = check_self_keychange(handle, rqstp, rec.principal); 1215 if (!ret->code) { 1216 keepold = clamp_self_keepold(handle, rec.principal, arg->keepold); 1217 ret->code = kadm5_randkey_principal_3(handle, rec.principal, 1218 keepold, arg->n_ks_tuple, 1219 arg->ks_tuple, &k, &nkeys); 1220 } 1221 } 1222 1223 if (ret->code == KADM5_OK) { 1224 ret->code = chrand_check_lockdown(handle, &rec, &k, &nkeys); 1225 if (ret->code == KADM5_PROTECT_KEYS) 1226 ret->code = KADM5_OK; 1227 ret->keys = k; 1228 ret->n_keys = nkeys; 1229 } 1230 1231 if (ret->code != KADM5_AUTH_CHANGEPW) { 1232 if (ret->code != 0) 1233 errmsg = krb5_get_error_message(handle->context, ret->code); 1234 1235 log_done(funcname, prime_arg, errmsg, 1236 &client_name, &service_name, rqstp); 1237 1238 if (errmsg != NULL) 1239 krb5_free_error_message(handle->context, errmsg); 1240 } 1241 1242 exit_func: 1243 kadm5_free_principal_ent(handle, &rec); 1244 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1245 return TRUE; 1246 } 1247 1248 bool_t 1249 create_policy_2_svc(cpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) 1250 { 1251 char *prime_arg = NULL; 1252 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1253 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1254 kadm5_server_handle_t handle; 1255 const char *errmsg = NULL; 1256 1257 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, 1258 &ret->api_version, &client_name, &service_name, 1259 NULL, NULL); 1260 if (ret->code) 1261 goto exit_func; 1262 1263 prime_arg = arg->rec.policy; 1264 1265 if (CHANGEPW_SERVICE(rqstp) || 1266 !stub_auth_pol(handle, OP_ADDPOL, arg->rec.policy, 1267 &arg->rec, arg->mask)) { 1268 ret->code = KADM5_AUTH_ADD; 1269 log_unauth("kadm5_create_policy", prime_arg, 1270 &client_name, &service_name, rqstp); 1271 1272 } else { 1273 ret->code = kadm5_create_policy(handle, &arg->rec, arg->mask); 1274 if (ret->code != 0) 1275 errmsg = krb5_get_error_message(handle->context, ret->code); 1276 1277 log_done("kadm5_create_policy", 1278 ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg, 1279 &client_name, &service_name, rqstp); 1280 1281 if (errmsg != NULL) 1282 krb5_free_error_message(handle->context, errmsg); 1283 } 1284 1285 exit_func: 1286 stub_cleanup(handle, NULL, &client_name, &service_name); 1287 return TRUE; 1288 } 1289 1290 bool_t 1291 delete_policy_2_svc(dpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) 1292 { 1293 char *prime_arg = NULL; 1294 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1295 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1296 kadm5_server_handle_t handle; 1297 const char *errmsg = NULL; 1298 1299 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, 1300 &ret->api_version, &client_name, &service_name, 1301 NULL, NULL); 1302 if (ret->code) 1303 goto exit_func; 1304 1305 prime_arg = arg->name; 1306 1307 if (CHANGEPW_SERVICE(rqstp) || 1308 !stub_auth(handle, OP_DELPOL, NULL, NULL, arg->name, NULL)) { 1309 log_unauth("kadm5_delete_policy", prime_arg, 1310 &client_name, &service_name, rqstp); 1311 ret->code = KADM5_AUTH_DELETE; 1312 } else { 1313 ret->code = kadm5_delete_policy(handle, arg->name); 1314 if (ret->code != 0) 1315 errmsg = krb5_get_error_message(handle->context, ret->code); 1316 1317 log_done("kadm5_delete_policy", 1318 ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg, 1319 &client_name, &service_name, rqstp); 1320 1321 if (errmsg != NULL) 1322 krb5_free_error_message(handle->context, errmsg); 1323 } 1324 1325 exit_func: 1326 stub_cleanup(handle, NULL, &client_name, &service_name); 1327 return TRUE; 1328 } 1329 1330 bool_t 1331 modify_policy_2_svc(mpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) 1332 { 1333 char *prime_arg = NULL; 1334 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1335 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1336 kadm5_server_handle_t handle; 1337 const char *errmsg = NULL; 1338 1339 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, 1340 &ret->api_version, &client_name, &service_name, 1341 NULL, NULL); 1342 if (ret->code) 1343 goto exit_func; 1344 1345 prime_arg = arg->rec.policy; 1346 1347 if (CHANGEPW_SERVICE(rqstp) || 1348 !stub_auth_pol(handle, OP_MODPOL, arg->rec.policy, 1349 &arg->rec, arg->mask)) { 1350 log_unauth("kadm5_modify_policy", prime_arg, 1351 &client_name, &service_name, rqstp); 1352 ret->code = KADM5_AUTH_MODIFY; 1353 } else { 1354 ret->code = kadm5_modify_policy(handle, &arg->rec, arg->mask); 1355 if (ret->code != 0) 1356 errmsg = krb5_get_error_message(handle->context, ret->code); 1357 1358 log_done("kadm5_modify_policy", 1359 ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg, 1360 &client_name, &service_name, rqstp); 1361 1362 if (errmsg != NULL) 1363 krb5_free_error_message(handle->context, errmsg); 1364 } 1365 1366 exit_func: 1367 stub_cleanup(handle, NULL, &client_name, &service_name); 1368 return TRUE; 1369 } 1370 1371 bool_t 1372 get_policy_2_svc(gpol_arg *arg, gpol_ret *ret, struct svc_req *rqstp) 1373 { 1374 char *funcname, *prime_arg = NULL; 1375 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1376 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1377 kadm5_ret_t ret2; 1378 kadm5_principal_ent_rec caller_ent; 1379 kadm5_server_handle_t handle; 1380 const char *errmsg = NULL, *cpolicy = NULL; 1381 1382 memset(&caller_ent, 0, sizeof(caller_ent)); 1383 1384 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, 1385 &ret->api_version, &client_name, &service_name, 1386 NULL, NULL); 1387 if (ret->code) 1388 goto exit_func; 1389 1390 funcname = "kadm5_get_policy"; 1391 1392 prime_arg = arg->name; 1393 1394 /* Look up the client principal's policy value. */ 1395 ret2 = kadm5_get_principal(handle->lhandle, handle->current_caller, 1396 &caller_ent, KADM5_PRINCIPAL_NORMAL_MASK); 1397 if (ret2 == KADM5_OK && (caller_ent.aux_attributes & KADM5_POLICY)) 1398 cpolicy = caller_ent.policy; 1399 1400 ret->code = KADM5_AUTH_GET; 1401 if ((CHANGEPW_SERVICE(rqstp) && 1402 (cpolicy == NULL || strcmp(cpolicy, arg->name) != 0)) || 1403 !stub_auth(handle, OP_GETPOL, NULL, NULL, arg->name, cpolicy)) { 1404 ret->code = KADM5_AUTH_GET; 1405 log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); 1406 } else { 1407 ret->code = kadm5_get_policy(handle, arg->name, &ret->rec); 1408 if (ret->code != 0) 1409 errmsg = krb5_get_error_message(handle->context, ret->code); 1410 1411 log_done(funcname, 1412 ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg, 1413 &client_name, &service_name, rqstp); 1414 if (errmsg != NULL) 1415 krb5_free_error_message(handle->context, errmsg); 1416 } 1417 1418 exit_func: 1419 (void)kadm5_free_principal_ent(handle->lhandle, &caller_ent); 1420 stub_cleanup(handle, NULL, &client_name, &service_name); 1421 return TRUE; 1422 } 1423 1424 bool_t 1425 get_pols_2_svc(gpols_arg *arg, gpols_ret *ret, struct svc_req *rqstp) 1426 { 1427 char *prime_arg = NULL; 1428 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1429 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1430 kadm5_server_handle_t handle; 1431 const char *errmsg = NULL; 1432 1433 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, 1434 &ret->api_version, &client_name, &service_name, 1435 NULL, NULL); 1436 if (ret->code) 1437 goto exit_func; 1438 1439 prime_arg = arg->exp; 1440 if (prime_arg == NULL) 1441 prime_arg = "*"; 1442 1443 if (CHANGEPW_SERVICE(rqstp) || 1444 !stub_auth(handle, OP_LISTPOLS, NULL, NULL, NULL, NULL)) { 1445 ret->code = KADM5_AUTH_LIST; 1446 log_unauth("kadm5_get_policies", prime_arg, 1447 &client_name, &service_name, rqstp); 1448 } else { 1449 ret->code = kadm5_get_policies(handle, arg->exp, &ret->pols, 1450 &ret->count); 1451 if (ret->code != 0) 1452 errmsg = krb5_get_error_message(handle->context, ret->code); 1453 1454 log_done("kadm5_get_policies", prime_arg, errmsg, 1455 &client_name, &service_name, rqstp); 1456 1457 if (errmsg != NULL) 1458 krb5_free_error_message(handle->context, errmsg); 1459 } 1460 1461 exit_func: 1462 stub_cleanup(handle, NULL, &client_name, &service_name); 1463 return TRUE; 1464 } 1465 1466 bool_t 1467 get_privs_2_svc(krb5_ui_4 *arg, getprivs_ret *ret, struct svc_req *rqstp) 1468 { 1469 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1470 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1471 kadm5_server_handle_t handle; 1472 const char *errmsg = NULL; 1473 1474 ret->code = stub_setup(*arg, rqstp, NULL, &handle, &ret->api_version, 1475 &client_name, &service_name, NULL, NULL); 1476 if (ret->code) 1477 goto exit_func; 1478 1479 ret->code = kadm5_get_privs(handle, &ret->privs); 1480 if (ret->code != 0) 1481 errmsg = krb5_get_error_message(handle->context, ret->code); 1482 1483 log_done("kadm5_get_privs", client_name.value, errmsg, 1484 &client_name, &service_name, rqstp); 1485 1486 if (errmsg != NULL) 1487 krb5_free_error_message(handle->context, errmsg); 1488 1489 exit_func: 1490 stub_cleanup(handle, NULL, &client_name, &service_name); 1491 return TRUE; 1492 } 1493 1494 bool_t 1495 purgekeys_2_svc(purgekeys_arg *arg, generic_ret *ret, struct svc_req *rqstp) 1496 { 1497 char *funcname, *prime_arg = NULL; 1498 kadm5_principal_ent_rec rec = { 0 }; 1499 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1500 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1501 kadm5_server_handle_t handle; 1502 1503 const char *errmsg = NULL; 1504 1505 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 1506 &ret->api_version, &client_name, &service_name, 1507 &prime_arg, &rec); 1508 if (ret->code) 1509 goto exit_func; 1510 1511 funcname = "kadm5_purgekeys"; 1512 1513 if (CHANGEPW_SERVICE(rqstp) || 1514 !stub_auth(handle, OP_PURGEKEYS, rec.principal, NULL, NULL, NULL)) { 1515 ret->code = KADM5_AUTH_MODIFY; 1516 log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); 1517 } else { 1518 ret->code = kadm5_purgekeys(handle, rec.principal, arg->keepkvno); 1519 if (ret->code != 0) 1520 errmsg = krb5_get_error_message(handle->context, ret->code); 1521 1522 log_done(funcname, prime_arg, errmsg, 1523 &client_name, &service_name, rqstp); 1524 1525 if (errmsg != NULL) 1526 krb5_free_error_message(handle->context, errmsg); 1527 } 1528 1529 exit_func: 1530 kadm5_free_principal_ent(handle, &rec); 1531 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1532 return TRUE; 1533 } 1534 1535 bool_t 1536 get_strings_2_svc(gstrings_arg *arg, gstrings_ret *ret, struct svc_req *rqstp) 1537 { 1538 char *prime_arg = NULL; 1539 kadm5_principal_ent_rec rec = { 0 }; 1540 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1541 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1542 kadm5_server_handle_t handle; 1543 const char *errmsg = NULL; 1544 1545 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 1546 &ret->api_version, &client_name, &service_name, 1547 &prime_arg, &rec); 1548 if (ret->code) 1549 goto exit_func; 1550 1551 if (CHANGEPW_SERVICE(rqstp) || 1552 !stub_auth(handle, OP_GETSTRS, rec.principal, NULL, NULL, NULL)) { 1553 ret->code = KADM5_AUTH_GET; 1554 log_unauth("kadm5_get_strings", prime_arg, 1555 &client_name, &service_name, rqstp); 1556 } else { 1557 ret->code = kadm5_get_strings(handle, rec.principal, &ret->strings, 1558 &ret->count); 1559 if (ret->code != 0) 1560 errmsg = krb5_get_error_message(handle->context, ret->code); 1561 1562 log_done("kadm5_get_strings", prime_arg, errmsg, 1563 &client_name, &service_name, rqstp); 1564 1565 if (errmsg != NULL) 1566 krb5_free_error_message(handle->context, errmsg); 1567 } 1568 1569 exit_func: 1570 kadm5_free_principal_ent(handle, &rec); 1571 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1572 return TRUE; 1573 } 1574 1575 bool_t 1576 set_string_2_svc(sstring_arg *arg, generic_ret *ret, struct svc_req *rqstp) 1577 { 1578 char *prime_arg = NULL; 1579 kadm5_principal_ent_rec rec = { 0 }; 1580 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1581 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1582 kadm5_server_handle_t handle; 1583 const char *errmsg = NULL; 1584 1585 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 1586 &ret->api_version, &client_name, &service_name, 1587 &prime_arg, &rec); 1588 if (ret->code) 1589 goto exit_func; 1590 1591 if (CHANGEPW_SERVICE(rqstp) || 1592 !stub_auth(handle, OP_SETSTR, rec.principal, NULL, 1593 arg->key, arg->value)) { 1594 ret->code = KADM5_AUTH_MODIFY; 1595 log_unauth("kadm5_mod_strings", prime_arg, 1596 &client_name, &service_name, rqstp); 1597 } else { 1598 ret->code = kadm5_set_string(handle, rec.principal, 1599 arg->key, arg->value); 1600 if (ret->code != 0) 1601 errmsg = krb5_get_error_message(handle->context, ret->code); 1602 1603 log_done("kadm5_mod_strings", prime_arg, errmsg, 1604 &client_name, &service_name, rqstp); 1605 1606 if (errmsg != NULL) 1607 krb5_free_error_message(handle->context, errmsg); 1608 } 1609 1610 exit_func: 1611 kadm5_free_principal_ent(handle, &rec); 1612 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1613 return TRUE; 1614 } 1615 1616 bool_t 1617 init_2_svc(krb5_ui_4 *arg, generic_ret *ret, struct svc_req *rqstp) 1618 { 1619 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1620 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1621 kadm5_server_handle_t handle; 1622 const char *errmsg = NULL; 1623 size_t clen, slen; 1624 char *cdots, *sdots; 1625 1626 ret->code = stub_setup(*arg, rqstp, NULL, &handle, &ret->api_version, 1627 &client_name, &service_name, NULL, NULL); 1628 if (ret->code) 1629 goto exit_func; 1630 1631 if (ret->code != 0) 1632 errmsg = krb5_get_error_message(handle->context, ret->code); 1633 1634 clen = client_name.length; 1635 trunc_name(&clen, &cdots); 1636 slen = service_name.length; 1637 trunc_name(&slen, &sdots); 1638 /* okay to cast lengths to int because trunc_name limits max value */ 1639 krb5_klog_syslog(LOG_NOTICE, _("Request: kadm5_init, %.*s%s, %s, " 1640 "client=%.*s%s, service=%.*s%s, addr=%s, " 1641 "vers=%d, flavor=%d"), 1642 (int)clen, (char *)client_name.value, cdots, 1643 errmsg ? errmsg : _("success"), 1644 (int)clen, (char *)client_name.value, cdots, 1645 (int)slen, (char *)service_name.value, sdots, 1646 client_addr(rqstp->rq_xprt), 1647 ret->api_version & ~(KADM5_API_VERSION_MASK), 1648 rqstp->rq_cred.oa_flavor); 1649 if (errmsg != NULL) 1650 krb5_free_error_message(handle->context, errmsg); 1651 1652 exit_func: 1653 stub_cleanup(handle, NULL, &client_name, &service_name); 1654 return TRUE; 1655 } 1656 1657 gss_name_t 1658 rqst2name(struct svc_req *rqstp) 1659 { 1660 1661 if (rqstp->rq_cred.oa_flavor == RPCSEC_GSS) 1662 return rqstp->rq_clntname; 1663 else 1664 return rqstp->rq_clntcred; 1665 } 1666 1667 bool_t 1668 get_principal_keys_2_svc(getpkeys_arg *arg, getpkeys_ret *ret, 1669 struct svc_req *rqstp) 1670 { 1671 char *prime_arg = NULL; 1672 kadm5_principal_ent_rec rec = { 0 }; 1673 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1674 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1675 kadm5_server_handle_t handle; 1676 const char *errmsg = NULL; 1677 1678 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, 1679 &ret->api_version, &client_name, &service_name, 1680 &prime_arg, &rec); 1681 if (ret->code) 1682 goto exit_func; 1683 1684 if (!(CHANGEPW_SERVICE(rqstp)) && 1685 stub_auth(handle, OP_EXTRACT, rec.principal, NULL, NULL, NULL)) { 1686 ret->code = kadm5_get_principal_keys(handle, rec.principal, arg->kvno, 1687 &ret->key_data, &ret->n_key_data); 1688 } else { 1689 log_unauth("kadm5_get_principal_keys", prime_arg, 1690 &client_name, &service_name, rqstp); 1691 ret->code = KADM5_AUTH_EXTRACT; 1692 } 1693 1694 if (ret->code == KADM5_OK) { 1695 ret->code = check_lockdown(&rec); 1696 if (ret->code != KADM5_OK) { 1697 kadm5_free_kadm5_key_data(handle->context, ret->n_key_data, 1698 ret->key_data); 1699 ret->key_data = NULL; 1700 ret->n_key_data = 0; 1701 } 1702 if (ret->code == KADM5_PROTECT_KEYS) { 1703 log_unauth("kadm5_get_principal_keys", prime_arg, 1704 &client_name, &service_name, rqstp); 1705 ret->code = KADM5_AUTH_EXTRACT; 1706 } 1707 } 1708 1709 if (ret->code != KADM5_AUTH_EXTRACT) { 1710 if (ret->code != 0) 1711 errmsg = krb5_get_error_message(handle->context, ret->code); 1712 1713 log_done("kadm5_get_principal_keys", prime_arg, errmsg, 1714 &client_name, &service_name, rqstp); 1715 1716 if (errmsg != NULL) 1717 krb5_free_error_message(handle->context, errmsg); 1718 } 1719 1720 exit_func: 1721 kadm5_free_principal_ent(handle, &rec); 1722 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1723 return TRUE; 1724 } 1725 1726 bool_t 1727 create_alias_2_svc(calias_arg *arg, generic_ret *ret, struct svc_req *rqstp) 1728 { 1729 char *prime_arg = NULL; 1730 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; 1731 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; 1732 kadm5_server_handle_t handle; 1733 const char *errmsg = NULL; 1734 1735 ret->code = stub_setup(arg->api_version, rqstp, arg->alias, &handle, 1736 &ret->api_version, &client_name, &service_name, 1737 &prime_arg, NULL); 1738 if (ret->code) 1739 goto exit_func; 1740 1741 if (CHANGEPW_SERVICE(rqstp) || 1742 !stub_auth(handle, OP_ADDALIAS, arg->alias, arg->target, NULL, NULL)) { 1743 ret->code = KADM5_AUTH_INSUFFICIENT; 1744 log_unauth("kadm5_create_alias", prime_arg, &client_name, 1745 &service_name, rqstp); 1746 } else { 1747 ret->code = kadm5_create_alias(handle, arg->alias, arg->target); 1748 if (ret->code) 1749 errmsg = krb5_get_error_message(handle->context, ret->code); 1750 log_done("kadm5_create_alias", prime_arg, errmsg, &client_name, 1751 &service_name, rqstp); 1752 if (errmsg != NULL) 1753 krb5_free_error_message(handle->context, errmsg); 1754 } 1755 1756 exit_func: 1757 stub_cleanup(handle, prime_arg, &client_name, &service_name); 1758 return TRUE; 1759 } 1760