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