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 * Copyright (C) 1998 by the FundsXpress, INC. 8 * 9 * All rights reserved. 10 * 11 * Export of this software from the United States of America may require 12 * a specific license from the United States Government. It is the 13 * responsibility of any person or organization contemplating export to 14 * obtain such a license before exporting. 15 * 16 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 17 * distribute this software and its documentation for any purpose and 18 * without fee is hereby granted, provided that the above copyright 19 * notice appear in all copies and that both that copyright notice and 20 * this permission notice appear in supporting documentation, and that 21 * the name of FundsXpress. not be used in advertising or publicity pertaining 22 * to distribution of the software without specific, written prior 23 * permission. FundsXpress makes no representations about the suitability of 24 * this software for any purpose. It is provided "as is" without express 25 * or implied warranty. 26 * 27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 28 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 29 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 30 */ 31 32 #include <k5-int.h> 33 #include <netdb.h> 34 #include <com_err.h> 35 #include <sys/types.h> 36 #include <sys/socket.h> 37 #include <netinet/in.h> 38 #include <fake-addrinfo.h> 39 #include <krb5.h> 40 41 #include <kadm5/admin.h> 42 #include <kadm5/kadm_rpc.h> 43 #include "client_internal.h" 44 #include <iprop_hdr.h> 45 #include "iprop.h" 46 47 #include <gssrpc/rpc.h> 48 #include <gssapi/gssapi.h> 49 #include <gssapi/gssapi_krb5.h> 50 #include <gssrpc/auth_gssapi.h> 51 52 #define ADM_CCACHE "/tmp/ovsec_adm.XXXXXX" 53 54 enum init_type { INIT_PASS, INIT_SKEY, INIT_CREDS, INIT_ANONYMOUS }; 55 56 static kadm5_ret_t 57 init_any(krb5_context context, char *client_name, enum init_type init_type, 58 char *pass, krb5_ccache ccache_in, char *service_name, 59 kadm5_config_params *params, krb5_ui_4 struct_version, 60 krb5_ui_4 api_version, char **db_args, void **server_handle); 61 62 static kadm5_ret_t 63 get_init_creds(kadm5_server_handle_t handle, krb5_principal client, 64 enum init_type init_type, char *pass, krb5_ccache ccache_in, 65 char *svcname_in, char *realm, krb5_principal *server_out); 66 67 static kadm5_ret_t 68 gic_iter(kadm5_server_handle_t handle, enum init_type init_type, 69 krb5_ccache ccache, krb5_principal client, char *pass, 70 char *svcname, char *realm, krb5_principal *server_out); 71 72 static kadm5_ret_t 73 connect_to_server(const char *hostname, int port, int *fd); 74 75 static kadm5_ret_t 76 setup_gss(kadm5_server_handle_t handle, kadm5_config_params *params_in, 77 krb5_principal client, krb5_principal server); 78 79 static void 80 rpc_auth(kadm5_server_handle_t handle, kadm5_config_params *params_in, 81 gss_cred_id_t gss_client_creds, gss_name_t gss_target); 82 83 kadm5_ret_t 84 kadm5_init_with_creds(krb5_context context, char *client_name, 85 krb5_ccache ccache, char *service_name, 86 kadm5_config_params *params, krb5_ui_4 struct_version, 87 krb5_ui_4 api_version, char **db_args, 88 void **server_handle) 89 { 90 return init_any(context, client_name, INIT_CREDS, NULL, ccache, 91 service_name, params, struct_version, api_version, db_args, 92 server_handle); 93 } 94 95 kadm5_ret_t 96 kadm5_init_with_password(krb5_context context, char *client_name, 97 char *pass, char *service_name, 98 kadm5_config_params *params, krb5_ui_4 struct_version, 99 krb5_ui_4 api_version, char **db_args, 100 void **server_handle) 101 { 102 return init_any(context, client_name, INIT_PASS, pass, NULL, service_name, 103 params, struct_version, api_version, db_args, 104 server_handle); 105 } 106 107 kadm5_ret_t 108 kadm5_init_anonymous(krb5_context context, char *client_name, 109 char *service_name, kadm5_config_params *params, 110 krb5_ui_4 struct_version, krb5_ui_4 api_version, 111 char **db_args, void **server_handle) 112 { 113 return init_any(context, client_name, INIT_ANONYMOUS, NULL, NULL, 114 service_name, params, struct_version, api_version, 115 db_args, server_handle); 116 } 117 118 kadm5_ret_t 119 kadm5_init(krb5_context context, char *client_name, char *pass, 120 char *service_name, kadm5_config_params *params, 121 krb5_ui_4 struct_version, krb5_ui_4 api_version, char **db_args, 122 void **server_handle) 123 { 124 return init_any(context, client_name, INIT_PASS, pass, NULL, service_name, 125 params, struct_version, api_version, db_args, 126 server_handle); 127 } 128 129 kadm5_ret_t 130 kadm5_init_with_skey(krb5_context context, char *client_name, 131 char *keytab, char *service_name, 132 kadm5_config_params *params, krb5_ui_4 struct_version, 133 krb5_ui_4 api_version, char **db_args, 134 void **server_handle) 135 { 136 return init_any(context, client_name, INIT_SKEY, keytab, NULL, 137 service_name, params, struct_version, api_version, db_args, 138 server_handle); 139 } 140 141 static kadm5_ret_t 142 free_handle(kadm5_server_handle_t handle) 143 { 144 kadm5_ret_t ret = 0; 145 OM_uint32 minor_stat; 146 krb5_ccache ccache; 147 148 if (handle == NULL) 149 return 0; 150 151 if (handle->destroy_cache && handle->cache_name != NULL) { 152 ret = krb5_cc_resolve(handle->context, handle->cache_name, &ccache); 153 if (!ret) 154 ret = krb5_cc_destroy(handle->context, ccache); 155 } 156 free(handle->cache_name); 157 (void)gss_release_cred(&minor_stat, &handle->cred); 158 if (handle->clnt != NULL && handle->clnt->cl_auth != NULL) 159 AUTH_DESTROY(handle->clnt->cl_auth); 160 if (handle->clnt != NULL) 161 clnt_destroy(handle->clnt); 162 if (handle->client_socket != -1) 163 close(handle->client_socket); 164 free(handle->lhandle); 165 kadm5_free_config_params(handle->context, &handle->params); 166 free(handle); 167 168 return ret; 169 } 170 171 static kadm5_ret_t 172 init_any(krb5_context context, char *client_name, enum init_type init_type, 173 char *pass, krb5_ccache ccache_in, char *service_name, 174 kadm5_config_params *params_in, krb5_ui_4 struct_version, 175 krb5_ui_4 api_version, char **db_args, void **server_handle) 176 { 177 int fd = -1; 178 krb5_boolean iprop_enable; 179 int port; 180 rpcprog_t rpc_prog; 181 rpcvers_t rpc_vers; 182 krb5_principal client = NULL, server = NULL; 183 struct timeval timeout; 184 185 kadm5_server_handle_t handle = NULL; 186 kadm5_config_params params_local; 187 188 krb5_error_code code; 189 generic_ret r = { 0, 0 }; 190 191 initialize_ovk_error_table(); 192 initialize_ovku_error_table(); 193 194 if (server_handle == NULL || client_name == NULL) 195 return EINVAL; 196 197 CHECK_VERSIONS(struct_version, api_version, KADM5_OLD_LIB_API_VERSION, 198 KADM5_NEW_LIB_API_VERSION); 199 200 handle = k5alloc(sizeof(*handle), &code); 201 if (handle == NULL) 202 goto cleanup; 203 handle->lhandle = k5alloc(sizeof(*handle), &code); 204 if (handle->lhandle == NULL) 205 goto cleanup; 206 207 handle->magic_number = KADM5_SERVER_HANDLE_MAGIC; 208 handle->struct_version = struct_version; 209 handle->api_version = api_version; 210 handle->clnt = 0; 211 handle->client_socket = -1; 212 handle->cache_name = 0; 213 handle->destroy_cache = 0; 214 handle->context = 0; 215 handle->cred = GSS_C_NO_CREDENTIAL; 216 *handle->lhandle = *handle; 217 handle->lhandle->api_version = KADM5_API_VERSION_4; 218 handle->lhandle->struct_version = KADM5_STRUCT_VERSION; 219 handle->lhandle->lhandle = handle->lhandle; 220 221 handle->context = context; 222 223 memset(¶ms_local, 0, sizeof(params_local)); 224 225 code = kadm5_get_config_params(handle->context, 0, params_in, 226 &handle->params); 227 if (code) 228 goto cleanup; 229 230 #define REQUIRED_PARAMS (KADM5_CONFIG_REALM | \ 231 KADM5_CONFIG_ADMIN_SERVER | \ 232 KADM5_CONFIG_KADMIND_PORT) 233 234 if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) { 235 code = KADM5_MISSING_KRB5_CONF_PARAMS; 236 goto cleanup; 237 } 238 239 /* 240 * Parse the client name. If it has an empty realm, it is almost certainly 241 * a host-based principal using DNS fallback processing or the referral 242 * realm, so give it the appropriate name type for canonicalization. Also 243 * check for iprop client principals as kpropd sets the realm on the 244 * sn2princ result. 245 */ 246 code = krb5_parse_name(handle->context, client_name, &client); 247 if (code) 248 goto cleanup; 249 if ((init_type == INIT_SKEY && client->realm.length == 0) || 250 (client->length == 2 && 251 data_eq_string(client->data[0], KIPROP_SVC_NAME))) 252 client->type = KRB5_NT_SRV_HST; 253 254 /* 255 * Get credentials. Also does some fallbacks in case kadmin/fqdn 256 * principal doesn't exist. 257 */ 258 code = get_init_creds(handle, client, init_type, pass, ccache_in, 259 service_name, handle->params.realm, &server); 260 if (code) 261 goto cleanup; 262 263 /* If the service_name and client_name are iprop-centric, use the iprop 264 * port and RPC identifiers. */ 265 iprop_enable = (service_name != NULL && 266 strstr(service_name, KIPROP_SVC_NAME) != NULL && 267 strstr(client_name, KIPROP_SVC_NAME) != NULL); 268 if (iprop_enable) { 269 port = handle->params.iprop_port; 270 rpc_prog = KRB5_IPROP_PROG; 271 rpc_vers = KRB5_IPROP_VERS; 272 } else { 273 port = handle->params.kadmind_port; 274 rpc_prog = KADM; 275 rpc_vers = KADMVERS; 276 } 277 278 code = connect_to_server(handle->params.admin_server, port, &fd); 279 if (code) 280 goto cleanup; 281 282 handle->clnt = clnttcp_create(NULL, rpc_prog, rpc_vers, &fd, 0, 0); 283 if (handle->clnt == NULL) { 284 code = KADM5_RPC_ERROR; 285 #ifdef DEBUG 286 clnt_pcreateerror("clnttcp_create"); 287 #endif 288 goto cleanup; 289 } 290 291 /* Set a one-hour timeout. */ 292 timeout.tv_sec = 3600; 293 timeout.tv_usec = 0; 294 (void)clnt_control(handle->clnt, CLSET_TIMEOUT, &timeout); 295 296 handle->client_socket = fd; 297 handle->lhandle->clnt = handle->clnt; 298 handle->lhandle->client_socket = fd; 299 300 /* 301 * The RPC connection is open; establish the GSS-API 302 * authentication context. 303 */ 304 code = setup_gss(handle, params_in, 305 (init_type == INIT_CREDS) ? client : NULL, server); 306 if (code) 307 goto cleanup; 308 309 /* 310 * Bypass the remainder of the code and return straight away 311 * if the gss service requested is kiprop 312 */ 313 if (iprop_enable) { 314 code = 0; 315 *server_handle = handle; 316 handle = NULL; 317 goto cleanup; 318 } 319 320 if (init_2(&handle->api_version, &r, handle->clnt)) { 321 code = KADM5_RPC_ERROR; 322 #ifdef DEBUG 323 clnt_perror(handle->clnt, "init_2 null resp"); 324 #endif 325 goto cleanup; 326 } 327 /* Drop down to v3 wire protocol if server does not support v4 */ 328 if (r.code == KADM5_NEW_SERVER_API_VERSION && 329 handle->api_version == KADM5_API_VERSION_4) { 330 handle->api_version = KADM5_API_VERSION_3; 331 memset(&r, 0, sizeof(generic_ret)); 332 if (init_2(&handle->api_version, &r, handle->clnt)) { 333 code = KADM5_RPC_ERROR; 334 goto cleanup; 335 } 336 } 337 /* Drop down to v2 wire protocol if server does not support v3 */ 338 if (r.code == KADM5_NEW_SERVER_API_VERSION && 339 handle->api_version == KADM5_API_VERSION_3) { 340 handle->api_version = KADM5_API_VERSION_2; 341 memset(&r, 0, sizeof(generic_ret)); 342 if (init_2(&handle->api_version, &r, handle->clnt)) { 343 code = KADM5_RPC_ERROR; 344 goto cleanup; 345 } 346 } 347 if (r.code) { 348 code = r.code; 349 goto cleanup; 350 } 351 352 *server_handle = handle; 353 handle = NULL; 354 355 cleanup: 356 krb5_free_principal(context, client); 357 krb5_free_principal(context, server); 358 (void)free_handle(handle); 359 360 return code; 361 } 362 363 /* Get initial credentials for authenticating to server. Perform fallback from 364 * kadmin/fqdn to kadmin/admin if svcname_in is NULL. */ 365 static kadm5_ret_t 366 get_init_creds(kadm5_server_handle_t handle, krb5_principal client, 367 enum init_type init_type, char *pass, krb5_ccache ccache_in, 368 char *svcname_in, char *realm, krb5_principal *server_out) 369 { 370 kadm5_ret_t code; 371 krb5_ccache ccache = NULL; 372 char *svcname, svcbuf[BUFSIZ]; 373 374 *server_out = NULL; 375 376 /* 377 * Acquire a service ticket for svcname@realm for client, using password 378 * pass (which could be NULL), and create a ccache to store them in. If 379 * INIT_CREDS, use the ccache we were provided instead. 380 */ 381 if (init_type == INIT_CREDS) { 382 ccache = ccache_in; 383 if (asprintf(&handle->cache_name, "%s:%s", 384 krb5_cc_get_type(handle->context, ccache), 385 krb5_cc_get_name(handle->context, ccache)) < 0) { 386 handle->cache_name = NULL; 387 code = ENOMEM; 388 goto error; 389 } 390 } else { 391 static int counter = 0; 392 393 if (asprintf(&handle->cache_name, "MEMORY:kadm5_%u", counter++) < 0) { 394 handle->cache_name = NULL; 395 code = ENOMEM; 396 goto error; 397 } 398 code = krb5_cc_resolve(handle->context, handle->cache_name, 399 &ccache); 400 if (code) 401 goto error; 402 403 code = krb5_cc_initialize (handle->context, ccache, client); 404 if (code) 405 goto error; 406 407 handle->destroy_cache = 1; 408 } 409 handle->lhandle->cache_name = handle->cache_name; 410 411 svcname = (svcname_in != NULL) ? svcname_in : KADM5_ADMIN_SERVICE; 412 code = gic_iter(handle, init_type, ccache, client, pass, svcname, realm, 413 server_out); 414 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN 415 || code == KRB5_CC_NOTFOUND) && svcname_in == NULL) { 416 /* Retry with host-based service principal. */ 417 code = kadm5_get_admin_service_name(handle->context, 418 handle->params.realm, 419 svcbuf, sizeof(svcbuf)); 420 if (code) 421 goto error; 422 code = gic_iter(handle, init_type, ccache, client, pass, svcbuf, realm, 423 server_out); 424 } 425 /* Improved error messages */ 426 if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) code = KADM5_BAD_PASSWORD; 427 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) 428 code = KADM5_SECURE_PRINC_MISSING; 429 430 error: 431 if (ccache != NULL && init_type != INIT_CREDS) 432 krb5_cc_close(handle->context, ccache); 433 return code; 434 } 435 436 /* Perform one iteration of attempting to get credentials. This includes 437 * searching existing ccache for requested service if INIT_CREDS. */ 438 static kadm5_ret_t 439 gic_iter(kadm5_server_handle_t handle, enum init_type init_type, 440 krb5_ccache ccache, krb5_principal client, char *pass, char *svcname, 441 char *realm, krb5_principal *server_out) 442 { 443 kadm5_ret_t code; 444 krb5_context ctx; 445 krb5_keytab kt; 446 krb5_get_init_creds_opt *opt = NULL; 447 krb5_creds mcreds, outcreds; 448 449 *server_out = NULL; 450 ctx = handle->context; 451 kt = NULL; 452 memset(&opt, 0, sizeof(opt)); 453 memset(&mcreds, 0, sizeof(mcreds)); 454 memset(&outcreds, 0, sizeof(outcreds)); 455 456 /* Credentials for kadmin don't need to be forwardable or proxiable. */ 457 if (init_type != INIT_CREDS) { 458 code = krb5_get_init_creds_opt_alloc(ctx, &opt); 459 if (code) 460 goto error; 461 462 krb5_get_init_creds_opt_set_forwardable(opt, 0); 463 krb5_get_init_creds_opt_set_proxiable(opt, 0); 464 krb5_get_init_creds_opt_set_out_ccache(ctx, opt, ccache); 465 if (init_type == INIT_ANONYMOUS) 466 krb5_get_init_creds_opt_set_anonymous(opt, 1); 467 } 468 469 if (init_type == INIT_PASS || init_type == INIT_ANONYMOUS) { 470 code = krb5_get_init_creds_password(ctx, &outcreds, client, pass, 471 krb5_prompter_posix, 472 NULL, 0, svcname, opt); 473 if (code) 474 goto error; 475 } else if (init_type == INIT_SKEY) { 476 if (pass) { 477 code = krb5_kt_resolve(ctx, pass, &kt); 478 if (code) 479 goto error; 480 } 481 code = krb5_get_init_creds_keytab(ctx, &outcreds, client, kt, 482 0, svcname, opt); 483 if (pass) 484 krb5_kt_close(ctx, kt); 485 if (code) 486 goto error; 487 } else if (init_type == INIT_CREDS) { 488 mcreds.client = client; 489 code = krb5_parse_name_flags(ctx, svcname, 490 KRB5_PRINCIPAL_PARSE_IGNORE_REALM, 491 &mcreds.server); 492 if (code) 493 goto error; 494 code = krb5_set_principal_realm(ctx, mcreds.server, realm); 495 if (code) 496 goto error; 497 code = krb5_cc_retrieve_cred(ctx, ccache, 0, 498 &mcreds, &outcreds); 499 krb5_free_principal(ctx, mcreds.server); 500 if (code) 501 goto error; 502 } else { 503 code = EINVAL; 504 goto error; 505 } 506 507 /* Steal the server principal of the creds we acquired and return it to the 508 * caller, which needs to knows what service to authenticate to. */ 509 *server_out = outcreds.server; 510 outcreds.server = NULL; 511 512 error: 513 krb5_free_cred_contents(ctx, &outcreds); 514 if (opt) 515 krb5_get_init_creds_opt_free(ctx, opt); 516 return code; 517 } 518 519 /* Set *fd to a socket connected to hostname and port. */ 520 static kadm5_ret_t 521 connect_to_server(const char *hostname, int port, int *fd) 522 { 523 struct addrinfo hint, *addrs, *a; 524 char portbuf[32]; 525 int err, s; 526 kadm5_ret_t code; 527 528 /* Look up the server's addresses. */ 529 (void) snprintf(portbuf, sizeof(portbuf), "%d", port); 530 memset(&hint, 0, sizeof(hint)); 531 hint.ai_socktype = SOCK_STREAM; 532 hint.ai_flags = AI_ADDRCONFIG; 533 #ifdef AI_NUMERICSERV 534 hint.ai_flags |= AI_NUMERICSERV; 535 #endif 536 err = getaddrinfo(hostname, portbuf, &hint, &addrs); 537 if (err != 0) 538 return KADM5_CANT_RESOLVE; 539 540 /* Try to connect to each address until we succeed. */ 541 for (a = addrs; a != NULL; a = a->ai_next) { 542 s = socket(a->ai_family, a->ai_socktype, 0); 543 if (s == -1) { 544 code = KADM5_FAILURE; 545 goto cleanup; 546 } 547 err = connect(s, a->ai_addr, a->ai_addrlen); 548 if (err == 0) { 549 *fd = s; 550 code = 0; 551 goto cleanup; 552 } 553 close(s); 554 } 555 556 /* We didn't succeed on any address. */ 557 code = KADM5_RPC_ERROR; 558 cleanup: 559 freeaddrinfo(addrs); 560 return code; 561 } 562 563 /* Acquire GSSAPI credentials and set up RPC auth flavor. */ 564 static kadm5_ret_t 565 setup_gss(kadm5_server_handle_t handle, kadm5_config_params *params_in, 566 krb5_principal client, krb5_principal server) 567 { 568 OM_uint32 gssstat, minor_stat; 569 gss_buffer_desc buf; 570 gss_name_t gss_client; 571 gss_name_t gss_target; 572 const char *c_ccname_orig; 573 char *ccname_orig; 574 575 ccname_orig = NULL; 576 gss_client = gss_target = GSS_C_NO_NAME; 577 578 /* Temporarily use the kadm5 cache. */ 579 gssstat = gss_krb5_ccache_name(&minor_stat, handle->cache_name, 580 &c_ccname_orig); 581 if (gssstat != GSS_S_COMPLETE) 582 goto error; 583 if (c_ccname_orig) 584 ccname_orig = strdup(c_ccname_orig); 585 else 586 ccname_orig = 0; 587 588 buf.value = &server; 589 buf.length = sizeof(server); 590 gssstat = gss_import_name(&minor_stat, &buf, 591 (gss_OID)gss_nt_krb5_principal, &gss_target); 592 if (gssstat != GSS_S_COMPLETE) 593 goto error; 594 595 if (client != NULL) { 596 buf.value = &client; 597 buf.length = sizeof(client); 598 gssstat = gss_import_name(&minor_stat, &buf, 599 (gss_OID)gss_nt_krb5_principal, &gss_client); 600 } else gss_client = GSS_C_NO_NAME; 601 602 if (gssstat != GSS_S_COMPLETE) 603 goto error; 604 605 gssstat = gss_acquire_cred(&minor_stat, gss_client, 0, 606 GSS_C_NULL_OID_SET, GSS_C_INITIATE, 607 &handle->cred, NULL, NULL); 608 if (gssstat != GSS_S_COMPLETE) 609 goto error; 610 611 /* 612 * Do actual creation of RPC auth handle. Implements auth flavor 613 * fallback. 614 */ 615 rpc_auth(handle, params_in, handle->cred, gss_target); 616 617 error: 618 if (gss_client) 619 gss_release_name(&minor_stat, &gss_client); 620 if (gss_target) 621 gss_release_name(&minor_stat, &gss_target); 622 623 /* Revert to prior gss_krb5 ccache. */ 624 if (ccname_orig) { 625 gssstat = gss_krb5_ccache_name(&minor_stat, ccname_orig, NULL); 626 if (gssstat) { 627 return KADM5_GSS_ERROR; 628 } 629 free(ccname_orig); 630 } else { 631 gssstat = gss_krb5_ccache_name(&minor_stat, NULL, NULL); 632 if (gssstat) { 633 return KADM5_GSS_ERROR; 634 } 635 } 636 637 if (handle->clnt->cl_auth == NULL) { 638 return KADM5_GSS_ERROR; 639 } 640 return 0; 641 } 642 643 /* Create RPC auth handle. Do auth flavor fallback if needed. */ 644 static void 645 rpc_auth(kadm5_server_handle_t handle, kadm5_config_params *params_in, 646 gss_cred_id_t gss_client_creds, gss_name_t gss_target) 647 { 648 OM_uint32 gssstat, minor_stat; 649 struct rpc_gss_sec sec; 650 651 /* Allow unauthenticated option for testing. */ 652 if (params_in != NULL && (params_in->mask & KADM5_CONFIG_NO_AUTH)) 653 return; 654 655 /* Use RPCSEC_GSS by default. */ 656 if (params_in == NULL || 657 !(params_in->mask & KADM5_CONFIG_OLD_AUTH_GSSAPI)) { 658 sec.mech = (gss_OID)gss_mech_krb5; 659 sec.qop = GSS_C_QOP_DEFAULT; 660 sec.svc = RPCSEC_GSS_SVC_PRIVACY; 661 sec.cred = gss_client_creds; 662 sec.req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG; 663 664 handle->clnt->cl_auth = authgss_create(handle->clnt, 665 gss_target, &sec); 666 if (handle->clnt->cl_auth != NULL) 667 return; 668 } 669 670 if (params_in != NULL && (params_in->mask & KADM5_CONFIG_AUTH_NOFALLBACK)) 671 return; 672 673 /* Fall back to old AUTH_GSSAPI. */ 674 handle->clnt->cl_auth = auth_gssapi_create(handle->clnt, 675 &gssstat, 676 &minor_stat, 677 gss_client_creds, 678 gss_target, 679 (gss_OID) gss_mech_krb5, 680 GSS_C_MUTUAL_FLAG 681 | GSS_C_REPLAY_FLAG, 682 0, NULL, NULL, NULL); 683 } 684 685 kadm5_ret_t 686 kadm5_destroy(void *server_handle) 687 { 688 CHECK_HANDLE(server_handle); 689 return free_handle(server_handle); 690 } 691 /* not supported on client */ 692 kadm5_ret_t kadm5_lock(void *server_handle) 693 { 694 return EINVAL; 695 } 696 697 /* not supported on client */ 698 kadm5_ret_t kadm5_unlock(void *server_handle) 699 { 700 return EINVAL; 701 } 702 703 kadm5_ret_t kadm5_flush(void *server_handle) 704 { 705 return KADM5_OK; 706 } 707 708 int _kadm5_check_handle(void *handle) 709 { 710 CHECK_HANDLE(handle); 711 return 0; 712 } 713 714 krb5_error_code kadm5_init_krb5_context (krb5_context *ctx) 715 { 716 return krb5_init_context(ctx); 717 } 718 719 /* 720 * Stub function for kadmin. It was created to eliminate the dependency on 721 * libkdb's ulog functions. The srv equivalent makes the actual calls. 722 */ 723 krb5_error_code 724 kadm5_init_iprop(void *handle, char **db_args) 725 { 726 return (0); 727 } 728