1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. 29 * 30 * $Id: svc_auth_gssapi.c,v 1.19 1994/10/27 12:38:51 jik Exp $ 31 */ 32 33 /* 34 * Server side handling of RPCSEC_GSS flavor. 35 */ 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <strings.h> 40 #include <sys/stat.h> 41 #include <sys/time.h> 42 #include <gssapi/gssapi.h> 43 #include <gssapi/gssapi_ext.h> 44 #include <rpc/rpc.h> 45 #include <rpc/rpcsec_defs.h> 46 #include <sys/file.h> 47 #include <fcntl.h> 48 #include <pwd.h> 49 #include <stdio.h> 50 #include <syslog.h> 51 52 /* 53 * Sequence window definitions. 54 */ 55 #define SEQ_ARR_SIZE 4 56 #define SEQ_WIN (SEQ_ARR_SIZE*32) 57 #define SEQ_HI_BIT 0x80000000 58 #define SEQ_LO_BIT 1 59 #define DIV_BY_32 5 60 #define SEQ_MASK 0x1f 61 #define SEQ_MAX 0x80000000 62 63 64 /* cache retransmit data */ 65 typedef struct _retrans_entry { 66 uint32_t xid; 67 rpc_gss_init_res result; 68 struct _retrans_entry *next, *prev; 69 } retrans_entry; 70 71 /* 72 * Server side RPCSEC_GSS context information. 73 */ 74 typedef struct _svc_rpc_gss_data { 75 struct _svc_rpc_gss_data *next, *prev; 76 struct _svc_rpc_gss_data *lru_next, *lru_prev; 77 bool_t established; 78 gss_ctx_id_t context; 79 gss_name_t client_name; 80 gss_cred_id_t server_creds; 81 uint_t expiration; 82 uint_t seq_num; 83 uint_t seq_bits[SEQ_ARR_SIZE]; 84 uint_t key; 85 OM_uint32 qop; 86 bool_t done_docallback; 87 bool_t locked; 88 rpc_gss_rawcred_t raw_cred; 89 rpc_gss_ucred_t u_cred; 90 bool_t u_cred_set; 91 void *cookie; 92 gss_cred_id_t deleg; 93 mutex_t clm; 94 int ref_cnt; 95 bool_t stale; 96 time_t time_secs_set; 97 retrans_entry *retrans_data; 98 } svc_rpc_gss_data; 99 100 /* 101 * Data structures used for LRU based context management. 102 */ 103 #define HASHMOD 256 104 #define HASHMASK 255 105 106 static svc_rpc_gss_data *clients[HASHMOD]; 107 static svc_rpc_gss_data *lru_first, *lru_last; 108 static int num_gss_contexts = 0; 109 static int max_gss_contexts = 128; 110 static int sweep_interval = 10; 111 static int last_swept = 0; 112 static uint_t max_lifetime = GSS_C_INDEFINITE; 113 static int init_lifetime = 0; 114 static uint_t gid_timeout = 43200; /* 43200 secs = 12 hours */ 115 116 /* 117 * lock used with context/lru variables 118 */ 119 static mutex_t ctx_mutex = DEFAULTMUTEX; 120 121 /* 122 * server credential management data and structures 123 */ 124 typedef struct svc_creds_list_s { 125 struct svc_creds_list_s *next; 126 gss_cred_id_t cred; 127 gss_name_t name; 128 rpcprog_t program; 129 rpcvers_t version; 130 gss_OID_set oid_set; 131 OM_uint32 req_time; 132 char *server_name; 133 mutex_t refresh_mutex; 134 } svc_creds_list_t; 135 136 137 static svc_creds_list_t *svc_creds_list; 138 static int svc_creds_count = 0; 139 140 /* 141 * lock used with server credential variables list 142 * 143 * server cred list locking guidelines: 144 * - Writer's lock holder has exclusive access to the list 145 * - Reader's lock holder(s) must also lock (refresh_mutex) each node 146 * before accessing that node's elements (ie. cred) 147 */ 148 static rwlock_t cred_lock = DEFAULTRWLOCK; 149 150 /* 151 * server callback list 152 */ 153 typedef struct cblist_s { 154 struct cblist_s *next; 155 rpc_gss_callback_t cb; 156 } cblist_t; 157 158 cblist_t *cblist = NULL; 159 160 /* 161 * lock used with callback variables 162 */ 163 static mutex_t cb_mutex = DEFAULTMUTEX; 164 165 /* 166 * forward declarations 167 */ 168 static bool_t svc_rpc_gss_wrap(); 169 static bool_t svc_rpc_gss_unwrap(); 170 static svc_rpc_gss_data *create_client(); 171 static svc_rpc_gss_data *get_client(); 172 static svc_rpc_gss_data *find_client(); 173 static void destroy_client(); 174 static void sweep_clients(); 175 static void drop_lru_client(); 176 static void insert_client(); 177 static bool_t check_verf(); 178 static bool_t rpc_gss_refresh_svc_cred(); 179 static bool_t set_response_verf(); 180 static void retrans_add(svc_rpc_gss_data *, uint32_t, 181 rpc_gss_init_res *); 182 static void retrans_del(struct _svc_rpc_gss_data *); 183 184 185 /* 186 * server side wrap/unwrap routines 187 */ 188 struct svc_auth_ops svc_rpc_gss_ops = { 189 svc_rpc_gss_wrap, 190 svc_rpc_gss_unwrap, 191 }; 192 193 /* 194 * Fetch server side authentication structure. 195 */ 196 extern SVCAUTH *__svc_get_svcauth(); 197 198 /* 199 * Cleanup routine for destroying context, called after service 200 * procedure is executed, for MT safeness. 201 */ 202 extern void *__svc_set_proc_cleanup_cb(); 203 static void (*old_cleanup_cb)() = NULL; 204 static bool_t cleanup_cb_set = FALSE; 205 206 static void 207 ctx_cleanup(SVCXPRT *xprt) 208 { 209 svc_rpc_gss_data *cl; 210 SVCAUTH *svcauth; 211 212 if (old_cleanup_cb != NULL) 213 (*old_cleanup_cb)(xprt); 214 215 /* 216 * First check if current context needs to be cleaned up. 217 */ 218 svcauth = __svc_get_svcauth(xprt); 219 /*LINTED*/ 220 if ((cl = (svc_rpc_gss_data *)svcauth->svc_ah_private) != NULL) { 221 mutex_lock(&cl->clm); 222 if (--cl->ref_cnt == 0 && cl->stale) { 223 mutex_unlock(&cl->clm); 224 mutex_lock(&ctx_mutex); 225 destroy_client(cl); 226 mutex_unlock(&ctx_mutex); 227 } else 228 mutex_unlock(&cl->clm); 229 } 230 231 /* 232 * Check for other expired contexts. 233 */ 234 if ((time(0) - last_swept) > sweep_interval) { 235 mutex_lock(&ctx_mutex); 236 /* 237 * Check again, in case some other thread got in. 238 */ 239 if ((time(0) - last_swept) > sweep_interval) 240 sweep_clients(); 241 mutex_unlock(&ctx_mutex); 242 } 243 } 244 245 /* 246 * Set server parameters. 247 */ 248 void 249 __rpc_gss_set_server_parms(int init_cred_lifetime, int max_cred_lifetime, 250 int cache_size) 251 { 252 /* 253 * Ignore parameters unless greater than zero. 254 */ 255 mutex_lock(&ctx_mutex); 256 if (cache_size > 0) 257 max_gss_contexts = cache_size; 258 if (max_cred_lifetime > 0) 259 max_lifetime = (uint_t)max_cred_lifetime; 260 if (init_cred_lifetime > 0) 261 init_lifetime = init_cred_lifetime; 262 mutex_unlock(&ctx_mutex); 263 } 264 265 /* 266 * Shift the array arr of length arrlen right by nbits bits. 267 */ 268 static void 269 shift_bits(uint_t *arr, int arrlen, int nbits) 270 { 271 int i, j; 272 uint_t lo, hi; 273 274 /* 275 * If the number of bits to be shifted exceeds SEQ_WIN, just 276 * zero out the array. 277 */ 278 if (nbits < SEQ_WIN) { 279 for (i = 0; i < nbits; i++) { 280 hi = 0; 281 for (j = 0; j < arrlen; j++) { 282 lo = arr[j] & SEQ_LO_BIT; 283 arr[j] >>= 1; 284 if (hi) 285 arr[j] |= SEQ_HI_BIT; 286 hi = lo; 287 } 288 } 289 } else { 290 for (j = 0; j < arrlen; j++) 291 arr[j] = 0; 292 } 293 } 294 295 /* 296 * Check that the received sequence number seq_num is valid. 297 */ 298 static bool_t 299 check_seq(svc_rpc_gss_data *cl, uint_t seq_num, bool_t *kill_context) 300 { 301 int i, j; 302 uint_t bit; 303 304 /* 305 * If it exceeds the maximum, kill context. 306 */ 307 if (seq_num >= SEQ_MAX) { 308 *kill_context = TRUE; 309 return (FALSE); 310 } 311 312 /* 313 * If greater than the last seen sequence number, just shift 314 * the sequence window so that it starts at the new sequence 315 * number and extends downwards by SEQ_WIN. 316 */ 317 if (seq_num > cl->seq_num) { 318 shift_bits(cl->seq_bits, SEQ_ARR_SIZE, seq_num - cl->seq_num); 319 cl->seq_bits[0] |= SEQ_HI_BIT; 320 cl->seq_num = seq_num; 321 return (TRUE); 322 } 323 324 /* 325 * If it is outside the sequence window, return failure. 326 */ 327 i = cl->seq_num - seq_num; 328 if (i >= SEQ_WIN) 329 return (FALSE); 330 331 /* 332 * If within sequence window, set the bit corresponding to it 333 * if not already seen; if already seen, return failure. 334 */ 335 j = SEQ_MASK - (i & SEQ_MASK); 336 bit = j > 0 ? (1 << j) : 1; 337 i >>= DIV_BY_32; 338 if (cl->seq_bits[i] & bit) 339 return (FALSE); 340 cl->seq_bits[i] |= bit; 341 return (TRUE); 342 } 343 344 /* 345 * Convert a name in gss exported type to rpc_gss_principal_t type. 346 */ 347 static bool_t 348 __rpc_gss_make_principal(rpc_gss_principal_t *principal, gss_buffer_desc *name) 349 { 350 int plen; 351 char *s; 352 353 plen = RNDUP(name->length) + sizeof (int); 354 (*principal) = (rpc_gss_principal_t)malloc(plen); 355 if ((*principal) == NULL) 356 return (FALSE); 357 bzero((caddr_t)(*principal), plen); 358 (*principal)->len = RNDUP(name->length); 359 s = (*principal)->name; 360 memcpy(s, name->value, name->length); 361 return (TRUE); 362 } 363 364 /* 365 * Convert a name in internal form to the exported type. 366 */ 367 static bool_t 368 set_client_principal(gss_name_t g_name, rpc_gss_principal_t *r_name) 369 { 370 gss_buffer_desc name; 371 OM_uint32 major, minor; 372 bool_t ret = FALSE; 373 374 major = gss_export_name(&minor, g_name, &name); 375 if (major != GSS_S_COMPLETE) 376 return (FALSE); 377 ret = __rpc_gss_make_principal(r_name, &name); 378 (void) gss_release_buffer(&minor, &name); 379 return (ret); 380 } 381 382 /* 383 * Set server callback. 384 */ 385 bool_t 386 __rpc_gss_set_callback(rpc_gss_callback_t *cb) 387 { 388 cblist_t *cbl; 389 390 if (cb->callback == NULL) 391 return (FALSE); 392 if ((cbl = (cblist_t *)malloc(sizeof (*cbl))) == NULL) 393 return (FALSE); 394 cbl->cb = *cb; 395 mutex_lock(&cb_mutex); 396 cbl->next = cblist; 397 cblist = cbl; 398 mutex_unlock(&cb_mutex); 399 return (TRUE); 400 } 401 402 /* 403 * Locate callback (if specified) and call server. Release any 404 * delegated credentials unless passed to server and the server 405 * accepts the context. If a callback is not specified, accept 406 * the incoming context. 407 */ 408 static bool_t 409 do_callback(struct svc_req *req, svc_rpc_gss_data *client_data) 410 { 411 cblist_t *cbl; 412 bool_t ret = TRUE, found = FALSE; 413 rpc_gss_lock_t lock; 414 OM_uint32 minor; 415 416 mutex_lock(&cb_mutex); 417 for (cbl = cblist; cbl != NULL; cbl = cbl->next) { 418 if (req->rq_prog != cbl->cb.program || 419 req->rq_vers != cbl->cb.version) 420 continue; 421 found = TRUE; 422 lock.locked = FALSE; 423 lock.raw_cred = &client_data->raw_cred; 424 ret = (*cbl->cb.callback)(req, client_data->deleg, 425 client_data->context, &lock, &client_data->cookie); 426 if (ret) { 427 client_data->locked = lock.locked; 428 client_data->deleg = GSS_C_NO_CREDENTIAL; 429 } 430 break; 431 } 432 if (!found) { 433 if (client_data->deleg != GSS_C_NO_CREDENTIAL) { 434 (void) gss_release_cred(&minor, &client_data->deleg); 435 client_data->deleg = GSS_C_NO_CREDENTIAL; 436 } 437 } 438 mutex_unlock(&cb_mutex); 439 return (ret); 440 } 441 442 /* 443 * Return caller credentials. 444 */ 445 bool_t 446 __rpc_gss_getcred(struct svc_req *req, rpc_gss_rawcred_t **rcred, 447 rpc_gss_ucred_t **ucred, void **cookie) 448 { 449 SVCAUTH *svcauth; 450 svc_rpc_gss_data *client_data; 451 svc_rpc_gss_parms_t *gss_parms; 452 gss_OID oid; 453 OM_uint32 status; 454 int len = 0; 455 struct timeval now; 456 457 svcauth = __svc_get_svcauth(req->rq_xprt); 458 /*LINTED*/ 459 client_data = (svc_rpc_gss_data *)svcauth->svc_ah_private; 460 gss_parms = &svcauth->svc_gss_parms; 461 462 mutex_lock(&client_data->clm); 463 464 if (rcred != NULL) { 465 svcauth->raw_cred = client_data->raw_cred; 466 svcauth->raw_cred.service = gss_parms->service; 467 svcauth->raw_cred.qop = __rpc_gss_num_to_qop( 468 svcauth->raw_cred.mechanism, gss_parms->qop_rcvd); 469 *rcred = &svcauth->raw_cred; 470 } 471 if (ucred != NULL) { 472 if (!client_data->u_cred_set) { 473 /* 474 * Double check making sure ucred is not set 475 * after acquiring the lock. 476 */ 477 if (!client_data->u_cred_set) { 478 if (!__rpc_gss_mech_to_oid( 479 (*rcred)->mechanism, &oid)) { 480 fprintf(stderr, dgettext(TEXT_DOMAIN, 481 "mech_to_oid failed in " 482 "getcred.\n")); 483 *ucred = NULL; 484 } else { 485 status = gsscred_name_to_unix_cred( 486 client_data->client_name, oid, 487 &client_data->u_cred.uid, 488 &client_data->u_cred.gid, 489 &client_data->u_cred.gidlist, 490 &len); 491 if (status == GSS_S_COMPLETE) { 492 client_data->u_cred_set = TRUE; 493 client_data->u_cred.gidlen = 494 (short)len; 495 gettimeofday(&now, NULL); 496 client_data->time_secs_set = 497 now.tv_sec; 498 *ucred = &client_data->u_cred; 499 } else 500 *ucred = NULL; 501 } 502 } 503 } else { 504 /* 505 * gid's already set; 506 * check if they have expired. 507 */ 508 gettimeofday(&now, NULL); 509 if ((now.tv_sec - client_data->time_secs_set) 510 > gid_timeout) { 511 /* Refresh gid's */ 512 status = gss_get_group_info( 513 client_data->u_cred.uid, 514 &client_data->u_cred.gid, 515 &client_data->u_cred.gidlist, 516 &len); 517 if (status == GSS_S_COMPLETE) { 518 client_data->u_cred.gidlen = 519 (short)len; 520 gettimeofday(&now, NULL); 521 client_data->time_secs_set = now.tv_sec; 522 *ucred = &client_data->u_cred; 523 } else { 524 client_data->u_cred_set = FALSE; 525 *ucred = NULL; 526 } 527 } 528 else 529 *ucred = &client_data->u_cred; 530 } 531 } 532 if (cookie != NULL) 533 *cookie = client_data->cookie; 534 535 mutex_unlock(&client_data->clm); 536 537 return (TRUE); 538 } 539 540 /* 541 * Server side authentication for RPCSEC_GSS. 542 */ 543 544 enum auth_stat 545 __svcrpcsec_gss(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) 546 { 547 XDR xdrs; 548 rpc_gss_creds creds; 549 rpc_gss_init_arg call_arg; 550 rpc_gss_init_res call_res, *retrans_result; 551 gss_buffer_desc output_token; 552 OM_uint32 gssstat, minor_stat, time_rec, ret_flags; 553 struct opaque_auth *cred; 554 svc_rpc_gss_data *client_data; 555 int ret; 556 svc_creds_list_t *sc; 557 SVCAUTH *svcauth; 558 svc_rpc_gss_parms_t *gss_parms; 559 gss_OID mech_type = GSS_C_NULL_OID; 560 561 /* 562 * Initialize response verifier to NULL verifier. If 563 * necessary, this will be changed later. 564 */ 565 rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NONE; 566 rqst->rq_xprt->xp_verf.oa_base = NULL; 567 rqst->rq_xprt->xp_verf.oa_length = 0; 568 /* 569 * Need to null out results to start with. 570 */ 571 memset((char *)&call_res, 0, sizeof (call_res)); 572 573 /* 574 * Pull out and check credential and verifier. 575 */ 576 cred = &msg->rm_call.cb_cred; 577 if (cred->oa_length == 0) { 578 return (AUTH_BADCRED); 579 } 580 581 xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE); 582 583 memset((char *)&creds, 0, sizeof (creds)); 584 if (!__xdr_rpc_gss_creds(&xdrs, &creds)) { 585 XDR_DESTROY(&xdrs); 586 ret = AUTH_BADCRED; 587 goto error; 588 } 589 XDR_DESTROY(&xdrs); 590 591 /* 592 * If this is a control message and proc is GSSAPI_INIT, then 593 * create a client handle for this client. Otherwise, look up 594 * the existing handle. 595 */ 596 if (creds.gss_proc == RPCSEC_GSS_INIT) { 597 if (creds.ctx_handle.length != 0) { 598 ret = AUTH_BADCRED; 599 goto error; 600 } 601 if ((client_data = create_client()) == NULL) { 602 ret = AUTH_FAILED; 603 goto error; 604 } 605 } else { 606 /* 607 * Only verify values for service parameter when proc 608 * not RPCSEC_GSS_INIT or RPCSEC_GSS_CONTINUE_INIT. 609 * RFC2203 says contents for sequence and service args 610 * are undefined for creation procs. 611 * 612 * Note: only need to check for *CONTINUE_INIT here because 613 * if() clause already checked for RPCSEC_GSS_INIT 614 */ 615 if (creds.gss_proc != RPCSEC_GSS_CONTINUE_INIT) { 616 switch (creds.service) { 617 case rpc_gss_svc_none: 618 case rpc_gss_svc_integrity: 619 case rpc_gss_svc_privacy: 620 break; 621 default: 622 ret = AUTH_BADCRED; 623 goto error; 624 } 625 } 626 if (creds.ctx_handle.length == 0) { 627 ret = AUTH_BADCRED; 628 goto error; 629 } 630 if ((client_data = get_client(&creds.ctx_handle)) == NULL) { 631 ret = RPCSEC_GSS_NOCRED; 632 goto error; 633 } 634 } 635 636 /* 637 * lock the client data until it's safe; if it's already stale, 638 * no more processing is possible 639 */ 640 mutex_lock(&client_data->clm); 641 if (client_data->stale) { 642 ret = RPCSEC_GSS_NOCRED; 643 goto error2; 644 } 645 646 /* 647 * Any response we send will use ctx_handle, so set it now; 648 * also set seq_window since this won't change. 649 */ 650 call_res.ctx_handle.length = sizeof (client_data->key); 651 call_res.ctx_handle.value = (char *)&client_data->key; 652 call_res.seq_window = SEQ_WIN; 653 654 /* 655 * Set the appropriate wrap/unwrap routine for RPCSEC_GSS. 656 */ 657 svcauth = __svc_get_svcauth(rqst->rq_xprt); 658 svcauth->svc_ah_ops = svc_rpc_gss_ops; 659 svcauth->svc_ah_private = (caddr_t)client_data; 660 661 /* 662 * Keep copy of parameters we'll need for response, for the 663 * sake of reentrancy (we don't want to look in the context 664 * data because when we are sending a response, another 665 * request may have come in. 666 */ 667 gss_parms = &svcauth->svc_gss_parms; 668 gss_parms->established = client_data->established; 669 gss_parms->service = creds.service; 670 gss_parms->qop_rcvd = (uint_t)client_data->qop; 671 gss_parms->context = (void *)client_data->context; 672 gss_parms->seq_num = creds.seq_num; 673 674 if (!client_data->established) { 675 if (creds.gss_proc == RPCSEC_GSS_DATA) { 676 ret = RPCSEC_GSS_FAILED; 677 client_data->stale = TRUE; 678 goto error2; 679 } 680 681 /* 682 * If the context is not established, then only GSSAPI_INIT 683 * and _CONTINUE requests are valid. 684 */ 685 if (creds.gss_proc != RPCSEC_GSS_INIT && creds.gss_proc != 686 RPCSEC_GSS_CONTINUE_INIT) { 687 ret = RPCSEC_GSS_FAILED; 688 client_data->stale = TRUE; 689 goto error2; 690 } 691 692 /* 693 * call is for us, deserialize arguments 694 */ 695 memset(&call_arg, 0, sizeof (call_arg)); 696 if (!svc_getargs(rqst->rq_xprt, __xdr_rpc_gss_init_arg, 697 (caddr_t)&call_arg)) { 698 ret = RPCSEC_GSS_FAILED; 699 client_data->stale = TRUE; 700 goto error2; 701 } 702 703 gssstat = GSS_S_FAILURE; 704 minor_stat = 0; 705 rw_rdlock(&cred_lock); 706 /* 707 * set next sc to point to the server cred 708 * if the client_data contains server_creds 709 */ 710 for (sc = svc_creds_list; sc != NULL; sc = sc->next) { 711 if (rqst->rq_prog != sc->program || 712 rqst->rq_vers != sc->version) 713 continue; 714 715 mutex_lock(&sc->refresh_mutex); 716 gssstat = gss_accept_sec_context(&minor_stat, 717 &client_data->context, 718 sc->cred, 719 &call_arg, 720 GSS_C_NO_CHANNEL_BINDINGS, 721 &client_data->client_name, 722 &mech_type, 723 &output_token, 724 &ret_flags, 725 &time_rec, 726 NULL); 727 728 if (gssstat == GSS_S_CREDENTIALS_EXPIRED) { 729 if (rpc_gss_refresh_svc_cred(sc)) { 730 gssstat = gss_accept_sec_context( 731 &minor_stat, 732 &client_data->context, 733 sc->cred, 734 &call_arg, 735 GSS_C_NO_CHANNEL_BINDINGS, 736 &client_data->client_name, 737 &mech_type, 738 &output_token, 739 &ret_flags, 740 &time_rec, 741 NULL); 742 mutex_unlock(&sc->refresh_mutex); 743 744 } else { 745 mutex_unlock(&sc->refresh_mutex); 746 gssstat = GSS_S_NO_CRED; 747 break; 748 } 749 750 } else 751 mutex_unlock(&sc->refresh_mutex); 752 753 if (gssstat == GSS_S_COMPLETE) { 754 /* 755 * Server_creds was right - set it. Also 756 * set the raw and unix credentials at this 757 * point. This saves a lot of computation 758 * later when credentials are retrieved. 759 */ 760 /* 761 * XXX server_creds will prob be stale 762 * after rpc_gss_refresh_svc_cred(), but 763 * it appears not to ever be referenced 764 * anyways. 765 */ 766 mutex_lock(&sc->refresh_mutex); 767 client_data->server_creds = sc->cred; 768 client_data->raw_cred.version = creds.version; 769 client_data->raw_cred.service = creds.service; 770 client_data->raw_cred.svc_principal = 771 sc->server_name; 772 mutex_unlock(&sc->refresh_mutex); 773 774 if ((client_data->raw_cred.mechanism 775 = __rpc_gss_oid_to_mech(mech_type)) 776 == NULL) { 777 gssstat = GSS_S_FAILURE; 778 (void) gss_release_buffer(&minor_stat, 779 &output_token); 780 } else if (!set_client_principal(client_data-> 781 client_name, &client_data-> 782 raw_cred.client_principal)) { 783 gssstat = GSS_S_FAILURE; 784 (void) gss_release_buffer(&minor_stat, 785 &output_token); 786 } 787 break; 788 } 789 790 if (gssstat == GSS_S_CONTINUE_NEEDED) { 791 /* 792 * XXX server_creds will prob be stale 793 * after rpc_gss_refresh_svc_cred(), but 794 * it appears not to ever be referenced 795 * anyways. 796 */ 797 mutex_lock(&sc->refresh_mutex); 798 client_data->server_creds = sc->cred; 799 mutex_unlock(&sc->refresh_mutex); 800 break; 801 } 802 803 } 804 rw_unlock(&cred_lock); 805 806 call_res.gss_major = gssstat; 807 call_res.gss_minor = minor_stat; 808 809 xdr_free(__xdr_rpc_gss_init_arg, (caddr_t)&call_arg); 810 811 if (gssstat != GSS_S_COMPLETE && 812 gssstat != GSS_S_CONTINUE_NEEDED) { 813 /* 814 * We have a failure - send response and delete 815 * the context. Don't dispatch. Set ctx_handle 816 * to NULL and seq_window to 0. 817 */ 818 call_res.ctx_handle.length = 0; 819 call_res.ctx_handle.value = NULL; 820 call_res.seq_window = 0; 821 822 svc_sendreply(rqst->rq_xprt, __xdr_rpc_gss_init_res, 823 (caddr_t)&call_res); 824 *no_dispatch = TRUE; 825 ret = AUTH_OK; 826 client_data->stale = TRUE; 827 goto error2; 828 } 829 830 /* 831 * This step succeeded. Send a response, along with 832 * a token if there's one. Don't dispatch. 833 */ 834 if (output_token.length != 0) { 835 GSS_COPY_BUFFER(call_res.token, output_token); 836 } 837 838 /* 839 * set response verifier: checksum of SEQ_WIN 840 */ 841 if (gssstat == GSS_S_COMPLETE) { 842 if (!set_response_verf(rqst, msg, client_data, 843 (uint_t)SEQ_WIN)) { 844 ret = RPCSEC_GSS_FAILED; 845 client_data->stale = TRUE; 846 (void) gss_release_buffer(&minor_stat, 847 &output_token); 848 goto error2; 849 } 850 } 851 852 svc_sendreply(rqst->rq_xprt, __xdr_rpc_gss_init_res, 853 (caddr_t)&call_res); 854 /* 855 * Cache last response in case it is lost and the client 856 * retries on an established context. 857 */ 858 (void) retrans_add(client_data, msg->rm_xid, &call_res); 859 *no_dispatch = TRUE; 860 (void) gss_release_buffer(&minor_stat, &output_token); 861 862 /* 863 * If appropriate, set established to TRUE *after* sending 864 * response (otherwise, the client will receive the final 865 * token encrypted) 866 */ 867 if (gssstat == GSS_S_COMPLETE) { 868 /* 869 * Context is established. Set expiry time for 870 * context (the minimum of time_rec and max_lifetime). 871 */ 872 client_data->seq_num = 1; 873 if (time_rec == GSS_C_INDEFINITE) { 874 if (max_lifetime != GSS_C_INDEFINITE) { 875 client_data->expiration = 876 max_lifetime + time(0); 877 } else { 878 client_data->expiration = 879 GSS_C_INDEFINITE; 880 } 881 } else if (max_lifetime == GSS_C_INDEFINITE || 882 max_lifetime > time_rec) { 883 client_data->expiration = time_rec + time(0); 884 } else { 885 client_data->expiration = max_lifetime + 886 time(0); 887 } 888 client_data->established = TRUE; 889 } 890 891 } else { 892 if ((creds.gss_proc != RPCSEC_GSS_DATA) && 893 (creds.gss_proc != RPCSEC_GSS_DESTROY)) { 894 895 switch (creds.gss_proc) { 896 897 case RPCSEC_GSS_CONTINUE_INIT: 898 /* 899 * This is an established context. Continue to 900 * satisfy retried continue init requests out of 901 * the retransmit cache. Throw away any that 902 * don't have a matching xid or the cach is 903 * empty. Delete the retransmit cache once the 904 * client sends a data request. 905 */ 906 if (client_data->retrans_data && 907 (client_data->retrans_data->xid == 908 msg->rm_xid)) { 909 910 retrans_result = 911 &client_data->retrans_data->result; 912 if (set_response_verf(rqst, msg, 913 client_data, (uint_t) 914 retrans_result->seq_window)) { 915 916 gss_parms->established = FALSE; 917 svc_sendreply(rqst->rq_xprt, 918 __xdr_rpc_gss_init_res, 919 (caddr_t)retrans_result); 920 *no_dispatch = TRUE; 921 goto success; 922 } 923 } 924 /* FALLTHROUGH */ 925 926 default: 927 syslog(LOG_ERR, "_svcrpcsec_gss: non-data " 928 "request on an established context"); 929 ret = AUTH_FAILED; 930 goto error2; 931 } 932 } 933 934 /* 935 * Once the context is established and there is no more 936 * retransmission of last continue init request, it is safe 937 * to delete the retransmit cache entry. 938 */ 939 if (client_data->retrans_data) 940 retrans_del(client_data); 941 942 /* 943 * Context is already established. Check verifier, and 944 * note parameters we will need for response in gss_parms. 945 */ 946 if (!check_verf(msg, client_data->context, 947 &gss_parms->qop_rcvd)) { 948 ret = RPCSEC_GSS_NOCRED; 949 goto error2; 950 } 951 /* 952 * Check and invoke callback if necessary. 953 */ 954 if (!client_data->done_docallback) { 955 client_data->done_docallback = TRUE; 956 client_data->qop = gss_parms->qop_rcvd; 957 client_data->raw_cred.qop = __rpc_gss_num_to_qop( 958 client_data->raw_cred.mechanism, 959 gss_parms->qop_rcvd); 960 client_data->raw_cred.service = creds.service; 961 if (!do_callback(rqst, client_data)) { 962 ret = AUTH_FAILED; 963 client_data->stale = TRUE; 964 goto error2; 965 } 966 } 967 968 /* 969 * If the context was locked, make sure that the client 970 * has not changed QOP. 971 */ 972 if (client_data->locked && 973 gss_parms->qop_rcvd != client_data->qop) { 974 ret = AUTH_BADVERF; 975 goto error2; 976 } 977 978 /* 979 * Validate sequence number. 980 */ 981 if (!check_seq(client_data, creds.seq_num, 982 &client_data->stale)) { 983 if (client_data->stale) 984 ret = RPCSEC_GSS_FAILED; 985 else { 986 /* 987 * Operational error, drop packet silently. 988 * The client will recover after timing out, 989 * assuming this is a client error and not 990 * a relpay attack. Don't dispatch. 991 */ 992 ret = AUTH_OK; 993 *no_dispatch = TRUE; 994 } 995 goto error2; 996 } 997 998 /* 999 * set response verifier 1000 */ 1001 if (!set_response_verf(rqst, msg, client_data, creds.seq_num)) { 1002 ret = RPCSEC_GSS_FAILED; 1003 client_data->stale = TRUE; 1004 goto error2; 1005 } 1006 1007 /* 1008 * If this is a control message RPCSEC_GSS_DESTROY, process 1009 * the call; otherwise, return AUTH_OK so it will be 1010 * dispatched to the application server. 1011 */ 1012 if (creds.gss_proc == RPCSEC_GSS_DESTROY) { 1013 svc_sendreply(rqst->rq_xprt, xdr_void, NULL); 1014 *no_dispatch = TRUE; 1015 client_data->stale = TRUE; 1016 1017 } else { 1018 /* 1019 * This should be an RPCSEC_GSS_DATA request. 1020 * If context is locked, make sure that the client 1021 * has not changed the security service. 1022 */ 1023 if (client_data->locked && 1024 client_data->raw_cred.service != creds.service) { 1025 ret = AUTH_FAILED; 1026 goto error2; 1027 } 1028 1029 /* 1030 * Set client credentials to raw credential 1031 * structure in context. This is okay, since 1032 * this will not change during the lifetime of 1033 * the context (so it's MT safe). 1034 */ 1035 rqst->rq_clntcred = (char *)&client_data->raw_cred; 1036 } 1037 } 1038 1039 success: 1040 /* 1041 * Success. 1042 */ 1043 if (creds.ctx_handle.length != 0) 1044 xdr_free(__xdr_rpc_gss_creds, (caddr_t)&creds); 1045 mutex_unlock(&client_data->clm); 1046 return (AUTH_OK); 1047 error2: 1048 mutex_unlock(&client_data->clm); 1049 error: 1050 /* 1051 * Failure. 1052 */ 1053 if (creds.ctx_handle.length != 0) 1054 xdr_free(__xdr_rpc_gss_creds, (caddr_t)&creds); 1055 return (ret); 1056 } 1057 1058 /* 1059 * Check verifier. The verifier is the checksum of the RPC header 1060 * upto and including the credentials field. 1061 */ 1062 static bool_t 1063 check_verf(struct rpc_msg *msg, gss_ctx_id_t context, int *qop_state) 1064 { 1065 int *buf, *tmp; 1066 int hdr[32]; 1067 struct opaque_auth *oa; 1068 int len; 1069 gss_buffer_desc msg_buf; 1070 gss_buffer_desc tok_buf; 1071 OM_uint32 gssstat, minor_stat; 1072 1073 /* 1074 * We have to reconstruct the RPC header from the previously 1075 * parsed information, since we haven't kept the header intact. 1076 */ 1077 1078 oa = &msg->rm_call.cb_cred; 1079 if (oa->oa_length > MAX_AUTH_BYTES) 1080 return (FALSE); 1081 1082 /* 8 XDR units from the IXDR macro calls. */ 1083 if (sizeof (hdr) < (8 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length))) 1084 return (FALSE); 1085 buf = hdr; 1086 1087 IXDR_PUT_U_INT32(buf, msg->rm_xid); 1088 IXDR_PUT_ENUM(buf, msg->rm_direction); 1089 IXDR_PUT_U_INT32(buf, msg->rm_call.cb_rpcvers); 1090 IXDR_PUT_U_INT32(buf, msg->rm_call.cb_prog); 1091 IXDR_PUT_U_INT32(buf, msg->rm_call.cb_vers); 1092 IXDR_PUT_U_INT32(buf, msg->rm_call.cb_proc); 1093 IXDR_PUT_ENUM(buf, oa->oa_flavor); 1094 IXDR_PUT_U_INT32(buf, oa->oa_length); 1095 if (oa->oa_length) { 1096 len = RNDUP(oa->oa_length); 1097 tmp = buf; 1098 buf += len / sizeof (int); 1099 *(buf - 1) = 0; 1100 (void) memcpy((caddr_t)tmp, oa->oa_base, oa->oa_length); 1101 } 1102 len = ((char *)buf) - (char *)hdr; 1103 msg_buf.length = len; 1104 msg_buf.value = (char *)hdr; 1105 oa = &msg->rm_call.cb_verf; 1106 tok_buf.length = oa->oa_length; 1107 tok_buf.value = oa->oa_base; 1108 1109 gssstat = gss_verify(&minor_stat, context, &msg_buf, &tok_buf, 1110 qop_state); 1111 if (gssstat != GSS_S_COMPLETE) 1112 return (FALSE); 1113 return (TRUE); 1114 } 1115 1116 /* 1117 * Set response verifier. This is the checksum of the given number. 1118 * (e.g. sequence number or sequence window) 1119 */ 1120 static bool_t 1121 set_response_verf(struct svc_req *rqst, struct rpc_msg *msg, 1122 svc_rpc_gss_data *cl, uint_t num) 1123 { 1124 OM_uint32 minor; 1125 gss_buffer_desc in_buf, out_buf; 1126 uint_t num_net; 1127 1128 num_net = (uint_t)htonl(num); 1129 in_buf.length = sizeof (num); 1130 in_buf.value = (char *)&num_net; 1131 if (gss_sign(&minor, cl->context, cl->qop, &in_buf, 1132 &out_buf) != GSS_S_COMPLETE) 1133 return (FALSE); 1134 rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; 1135 rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; 1136 rqst->rq_xprt->xp_verf.oa_length = out_buf.length; 1137 memcpy(rqst->rq_xprt->xp_verf.oa_base, out_buf.value, 1138 out_buf.length); 1139 (void) gss_release_buffer(&minor, &out_buf); 1140 return (TRUE); 1141 } 1142 1143 /* 1144 * Create client context. 1145 */ 1146 static svc_rpc_gss_data * 1147 create_client(void) 1148 { 1149 svc_rpc_gss_data *client_data; 1150 static uint_t key = 1; 1151 1152 client_data = (svc_rpc_gss_data *) malloc(sizeof (*client_data)); 1153 if (client_data == NULL) 1154 return (NULL); 1155 memset((char *)client_data, 0, sizeof (*client_data)); 1156 1157 /* 1158 * set up client data structure 1159 */ 1160 client_data->established = FALSE; 1161 client_data->locked = FALSE; 1162 client_data->u_cred_set = FALSE; 1163 client_data->context = GSS_C_NO_CONTEXT; 1164 client_data->expiration = init_lifetime + time(0); 1165 client_data->ref_cnt = 1; 1166 client_data->qop = GSS_C_QOP_DEFAULT; 1167 client_data->done_docallback = FALSE; 1168 client_data->stale = FALSE; 1169 client_data->time_secs_set = 0; 1170 client_data->retrans_data = NULL; 1171 mutex_init(&client_data->clm, USYNC_THREAD, NULL); 1172 /* 1173 * Check totals. If we've hit the limit, we destroy a context 1174 * based on LRU method. 1175 */ 1176 mutex_lock(&ctx_mutex); 1177 if (num_gss_contexts >= max_gss_contexts) { 1178 /* 1179 * now try on LRU basis 1180 */ 1181 drop_lru_client(); 1182 if (num_gss_contexts >= max_gss_contexts) { 1183 mutex_unlock(&ctx_mutex); 1184 free((char *)client_data); 1185 return (NULL); 1186 } 1187 } 1188 1189 /* 1190 * The client context handle is a 32-bit key (unsigned int). 1191 * The key is incremented until there is no duplicate for it. 1192 */ 1193 for (;;) { 1194 client_data->key = key++; 1195 if (find_client(client_data->key) == NULL) { 1196 insert_client(client_data); 1197 /* 1198 * Set cleanup callback if we haven't. 1199 */ 1200 if (!cleanup_cb_set) { 1201 old_cleanup_cb = 1202 (void (*)()) __svc_set_proc_cleanup_cb( 1203 (void *)ctx_cleanup); 1204 cleanup_cb_set = TRUE; 1205 } 1206 mutex_unlock(&ctx_mutex); 1207 return (client_data); 1208 } 1209 } 1210 /*NOTREACHED*/ 1211 } 1212 1213 /* 1214 * Insert client context into hash list and LRU list. 1215 */ 1216 static void 1217 insert_client(svc_rpc_gss_data *client_data) 1218 { 1219 svc_rpc_gss_data *cl; 1220 int index = (client_data->key & HASHMASK); 1221 1222 client_data->prev = NULL; 1223 cl = clients[index]; 1224 if ((client_data->next = cl) != NULL) 1225 cl->prev = client_data; 1226 clients[index] = client_data; 1227 1228 client_data->lru_prev = NULL; 1229 if ((client_data->lru_next = lru_first) != NULL) 1230 lru_first->lru_prev = client_data; 1231 else 1232 lru_last = client_data; 1233 lru_first = client_data; 1234 1235 num_gss_contexts++; 1236 } 1237 1238 /* 1239 * Fetch a client, given the client context handle. Move it to the 1240 * top of the LRU list since this is the most recently used context. 1241 */ 1242 static svc_rpc_gss_data * 1243 get_client(gss_buffer_t ctx_handle) 1244 { 1245 uint_t key = *(uint_t *)ctx_handle->value; 1246 svc_rpc_gss_data *cl; 1247 1248 mutex_lock(&ctx_mutex); 1249 if ((cl = find_client(key)) != NULL) { 1250 mutex_lock(&cl->clm); 1251 if (cl->stale) { 1252 mutex_unlock(&cl->clm); 1253 mutex_unlock(&ctx_mutex); 1254 return (NULL); 1255 } 1256 cl->ref_cnt++; 1257 mutex_unlock(&cl->clm); 1258 if (cl != lru_first) { 1259 cl->lru_prev->lru_next = cl->lru_next; 1260 if (cl->lru_next != NULL) 1261 cl->lru_next->lru_prev = cl->lru_prev; 1262 else 1263 lru_last = cl->lru_prev; 1264 cl->lru_prev = NULL; 1265 cl->lru_next = lru_first; 1266 lru_first->lru_prev = cl; 1267 lru_first = cl; 1268 } 1269 } 1270 mutex_unlock(&ctx_mutex); 1271 return (cl); 1272 } 1273 1274 /* 1275 * Given the client context handle, find the context corresponding to it. 1276 * Don't change its LRU state since it may not be used. 1277 */ 1278 static svc_rpc_gss_data * 1279 find_client(uint_t key) 1280 { 1281 int index = (key & HASHMASK); 1282 svc_rpc_gss_data *cl; 1283 1284 for (cl = clients[index]; cl != NULL; cl = cl->next) { 1285 if (cl->key == key) 1286 break; 1287 } 1288 return (cl); 1289 } 1290 1291 /* 1292 * Destroy a client context. 1293 */ 1294 static void 1295 destroy_client(svc_rpc_gss_data *client_data) 1296 { 1297 OM_uint32 minor; 1298 int index = (client_data->key & HASHMASK); 1299 1300 /* 1301 * remove from hash list 1302 */ 1303 if (client_data->prev == NULL) 1304 clients[index] = client_data->next; 1305 else 1306 client_data->prev->next = client_data->next; 1307 if (client_data->next != NULL) 1308 client_data->next->prev = client_data->prev; 1309 1310 /* 1311 * remove from LRU list 1312 */ 1313 if (client_data->lru_prev == NULL) 1314 lru_first = client_data->lru_next; 1315 else 1316 client_data->lru_prev->lru_next = client_data->lru_next; 1317 if (client_data->lru_next != NULL) 1318 client_data->lru_next->lru_prev = client_data->lru_prev; 1319 else 1320 lru_last = client_data->lru_prev; 1321 1322 /* 1323 * If there is a GSS context, clean up GSS state. 1324 */ 1325 if (client_data->context != GSS_C_NO_CONTEXT) { 1326 (void) gss_delete_sec_context(&minor, &client_data->context, 1327 NULL); 1328 if (client_data->client_name) { 1329 (void) gss_release_name(&minor, 1330 &client_data->client_name); 1331 } 1332 free(client_data->raw_cred.client_principal); 1333 free(client_data->u_cred.gidlist); 1334 if (client_data->deleg != GSS_C_NO_CREDENTIAL) 1335 (void) gss_release_cred(&minor, &client_data->deleg); 1336 } 1337 1338 if (client_data->retrans_data != NULL) 1339 retrans_del(client_data); 1340 1341 free(client_data); 1342 num_gss_contexts--; 1343 } 1344 1345 /* 1346 * Check for expired client contexts. 1347 */ 1348 static void 1349 sweep_clients(void) 1350 { 1351 svc_rpc_gss_data *cl, *next; 1352 int index; 1353 1354 for (index = 0; index < HASHMOD; index++) { 1355 cl = clients[index]; 1356 while (cl) { 1357 next = cl->next; 1358 mutex_lock(&cl->clm); 1359 if ((cl->expiration != GSS_C_INDEFINITE && 1360 cl->expiration <= time(0)) || cl->stale) { 1361 cl->stale = TRUE; 1362 if (cl->ref_cnt == 0) { 1363 mutex_unlock(&cl->clm); 1364 destroy_client(cl); 1365 } else 1366 mutex_unlock(&cl->clm); 1367 } else 1368 mutex_unlock(&cl->clm); 1369 cl = next; 1370 } 1371 } 1372 last_swept = time(0); 1373 } 1374 1375 /* 1376 * Drop the least recently used client context, if possible. 1377 */ 1378 static void 1379 drop_lru_client(void) 1380 { 1381 mutex_lock(&lru_last->clm); 1382 lru_last->stale = TRUE; 1383 mutex_unlock(&lru_last->clm); 1384 if (lru_last->ref_cnt == 0) 1385 destroy_client(lru_last); 1386 else 1387 sweep_clients(); 1388 } 1389 1390 /* 1391 * find service credentials 1392 * return cred if found, 1393 * other wise, NULL 1394 */ 1395 svc_creds_list_t * 1396 find_svc_cred(char *service_name, uint_t program, uint_t version) 1397 { 1398 1399 svc_creds_list_t *sc; 1400 1401 if (!svc_creds_list) 1402 return (NULL); 1403 1404 for (sc = svc_creds_list; sc != NULL; sc = sc->next) { 1405 if (program != sc->program || version != sc->version) 1406 continue; 1407 1408 if (strcmp(service_name, sc->server_name) != 0) 1409 continue; 1410 return (sc); 1411 } 1412 return (NULL); 1413 } 1414 1415 /* 1416 * Set the server principal name. 1417 */ 1418 bool_t 1419 __rpc_gss_set_svc_name(char *server_name, char *mech, OM_uint32 req_time, 1420 uint_t program, uint_t version) 1421 { 1422 gss_name_t name; 1423 svc_creds_list_t *svc_cred; 1424 gss_OID mechanism; 1425 gss_OID_set_desc oid_set_desc; 1426 gss_OID_set oid_set; 1427 OM_uint32 ret_time; 1428 OM_uint32 major, minor; 1429 gss_buffer_desc name_buf; 1430 1431 if (!__rpc_gss_mech_to_oid(mech, &mechanism)) { 1432 return (FALSE); 1433 } 1434 1435 name_buf.value = server_name; 1436 name_buf.length = strlen(server_name); 1437 major = gss_import_name(&minor, &name_buf, 1438 (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &name); 1439 if (major != GSS_S_COMPLETE) { 1440 return (FALSE); 1441 } 1442 1443 /* Check if there is already an entry in the svc_creds_list. */ 1444 rw_wrlock(&cred_lock); 1445 if (svc_cred = find_svc_cred(server_name, program, version)) { 1446 1447 major = gss_add_cred(&minor, svc_cred->cred, name, 1448 mechanism, GSS_C_ACCEPT, 0, req_time, NULL, 1449 &oid_set, NULL, &ret_time); 1450 (void) gss_release_name(&minor, &name); 1451 if (major == GSS_S_COMPLETE) { 1452 /* 1453 * Successfully added the mech to the cred handle 1454 * free the existing oid_set in svc_cred 1455 */ 1456 gss_release_oid_set(&minor, &svc_cred->oid_set); 1457 svc_cred->oid_set = oid_set; 1458 rw_unlock(&cred_lock); 1459 return (TRUE); 1460 } else if (major == GSS_S_DUPLICATE_ELEMENT) { 1461 rw_unlock(&cred_lock); 1462 return (TRUE); 1463 } else if (major == GSS_S_CREDENTIALS_EXPIRED) { 1464 if (rpc_gss_refresh_svc_cred(svc_cred)) { 1465 rw_unlock(&cred_lock); 1466 return (TRUE); 1467 } else { 1468 rw_unlock(&cred_lock); 1469 return (FALSE); 1470 } 1471 } else { 1472 rw_unlock(&cred_lock); 1473 return (FALSE); 1474 } 1475 } else { 1476 svc_cred = (svc_creds_list_t *)malloc(sizeof (*svc_cred)); 1477 if (svc_cred == NULL) { 1478 (void) gss_release_name(&minor, &name); 1479 rw_unlock(&cred_lock); 1480 return (FALSE); 1481 } 1482 oid_set_desc.count = 1; 1483 oid_set_desc.elements = mechanism; 1484 major = gss_acquire_cred(&minor, name, req_time, &oid_set_desc, 1485 GSS_C_ACCEPT, &svc_cred->cred, &oid_set, &ret_time); 1486 1487 if (major != GSS_S_COMPLETE) { 1488 (void) gss_release_name(&minor, &name); 1489 free(svc_cred); 1490 rw_unlock(&cred_lock); 1491 return (FALSE); 1492 } 1493 1494 svc_cred->name = name; 1495 svc_cred->program = program; 1496 svc_cred->version = version; 1497 svc_cred->req_time = req_time; 1498 svc_cred->oid_set = oid_set; 1499 svc_cred->server_name = strdup(server_name); 1500 if (svc_cred->server_name == NULL) { 1501 (void) gss_release_name(&minor, &name); 1502 free((char *)svc_cred); 1503 rw_unlock(&cred_lock); 1504 return (FALSE); 1505 } 1506 mutex_init(&svc_cred->refresh_mutex, USYNC_THREAD, NULL); 1507 1508 svc_cred->next = svc_creds_list; 1509 svc_creds_list = svc_cred; 1510 svc_creds_count++; 1511 rw_unlock(&cred_lock); 1512 1513 return (TRUE); 1514 } 1515 } 1516 /* 1517 * Refresh server credentials. 1518 */ 1519 static bool_t 1520 rpc_gss_refresh_svc_cred(svc_creds_list_t *svc_cred) 1521 { 1522 OM_uint32 major, minor; 1523 gss_OID_set oid_set; 1524 OM_uint32 ret_time; 1525 1526 (void) gss_release_cred(&minor, &svc_cred->cred); 1527 svc_cred->cred = GSS_C_NO_CREDENTIAL; 1528 major = gss_acquire_cred(&minor, svc_cred->name, svc_cred->req_time, 1529 svc_cred->oid_set, GSS_C_ACCEPT, &svc_cred->cred, &oid_set, 1530 &ret_time); 1531 if (major != GSS_S_COMPLETE) { 1532 return (FALSE); 1533 } 1534 gss_release_oid_set(&minor, &svc_cred->oid_set); 1535 svc_cred->oid_set = oid_set; 1536 return (TRUE); 1537 } 1538 1539 /* 1540 * Encrypt the serialized arguments from xdr_func applied to xdr_ptr 1541 * and write the result to xdrs. 1542 */ 1543 static bool_t 1544 svc_rpc_gss_wrap(SVCAUTH *auth, XDR *out_xdrs, bool_t (*xdr_func)(), 1545 caddr_t xdr_ptr) 1546 { 1547 svc_rpc_gss_parms_t *gss_parms = &auth->svc_gss_parms; 1548 1549 /* 1550 * If context is not established, or if neither integrity nor 1551 * privacy service is used, don't wrap - just XDR encode. 1552 * Otherwise, wrap data using service and QOP parameters. 1553 */ 1554 if (!gss_parms->established || gss_parms->service == rpc_gss_svc_none) 1555 return ((*xdr_func)(out_xdrs, xdr_ptr)); 1556 1557 return (__rpc_gss_wrap_data(gss_parms->service, 1558 (OM_uint32)gss_parms->qop_rcvd, 1559 (gss_ctx_id_t)gss_parms->context, 1560 gss_parms->seq_num, 1561 out_xdrs, xdr_func, xdr_ptr)); 1562 } 1563 1564 /* 1565 * Decrypt the serialized arguments and XDR decode them. 1566 */ 1567 static bool_t 1568 svc_rpc_gss_unwrap(SVCAUTH *auth, XDR *in_xdrs, bool_t (*xdr_func)(), 1569 caddr_t xdr_ptr) 1570 { 1571 svc_rpc_gss_parms_t *gss_parms = &auth->svc_gss_parms; 1572 1573 /* 1574 * If context is not established, or if neither integrity nor 1575 * privacy service is used, don't unwrap - just XDR decode. 1576 * Otherwise, unwrap data. 1577 */ 1578 if (!gss_parms->established || gss_parms->service == rpc_gss_svc_none) 1579 return ((*xdr_func)(in_xdrs, xdr_ptr)); 1580 1581 return (__rpc_gss_unwrap_data(gss_parms->service, 1582 (gss_ctx_id_t)gss_parms->context, 1583 gss_parms->seq_num, 1584 gss_parms->qop_rcvd, 1585 in_xdrs, xdr_func, xdr_ptr)); 1586 } 1587 1588 int 1589 __rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len) 1590 { 1591 SVCAUTH *svcauth; 1592 svc_rpc_gss_parms_t *gss_parms; 1593 1594 svcauth = __svc_get_svcauth(req->rq_xprt); 1595 gss_parms = &svcauth->svc_gss_parms; 1596 1597 if (!gss_parms->established || max_tp_unit_len <= 0) 1598 return (0); 1599 1600 return (__find_max_data_length(gss_parms->service, 1601 (gss_ctx_id_t)gss_parms->context, 1602 gss_parms->qop_rcvd, max_tp_unit_len)); 1603 } 1604 1605 /* 1606 * Add retransmit entry to the context cache entry for a new xid. 1607 * If there is already an entry, delete it before adding the new one. 1608 */ 1609 static void retrans_add(svc_rpc_gss_data *client, uint32_t xid, 1610 rpc_gss_init_res *result) 1611 { 1612 retrans_entry *rdata; 1613 1614 if (client->retrans_data && client->retrans_data->xid == xid) 1615 return; 1616 1617 rdata = (retrans_entry *) malloc(sizeof (*rdata)); 1618 if (rdata == NULL) 1619 return; 1620 1621 rdata->xid = xid; 1622 rdata->result = *result; 1623 1624 if (result->token.length != 0) { 1625 GSS_DUP_BUFFER(rdata->result.token, result->token); 1626 } 1627 1628 if (client->retrans_data) 1629 retrans_del(client); 1630 1631 client->retrans_data = rdata; 1632 } 1633 1634 /* 1635 * Delete the retransmit data from the context cache entry. 1636 */ 1637 static void retrans_del(svc_rpc_gss_data *client) 1638 { 1639 retrans_entry *rdata; 1640 OM_uint32 minor_stat; 1641 1642 if (client->retrans_data == NULL) 1643 return; 1644 1645 rdata = client->retrans_data; 1646 if (rdata->result.token.length != 0) { 1647 (void) gss_release_buffer(&minor_stat, &rdata->result.token); 1648 } 1649 1650 free((caddr_t)rdata); 1651 client->retrans_data = NULL; 1652 } 1653