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 * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2012 Milan Jurik. All rights reserved. 24 */ 25 26 /* 27 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. 28 * 29 * $Id: svc_auth_gssapi.c,v 1.19 1994/10/27 12:38:51 jik Exp $ 30 */ 31 32 /* 33 * Server side handling of RPCSEC_GSS flavor. 34 */ 35 36 #include <sys/systm.h> 37 #include <sys/kstat.h> 38 #include <sys/cmn_err.h> 39 #include <sys/debug.h> 40 #include <sys/types.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/sunddi.h> 47 #include <sys/atomic.h> 48 49 extern bool_t __rpc_gss_make_principal(rpc_gss_principal_t *, gss_buffer_t); 50 51 #ifdef DEBUG 52 extern void prom_printf(const char *, ...); 53 #endif 54 55 #ifdef _KERNEL 56 #define memcmp(a, b, l) bcmp((a), (b), (l)) 57 #endif 58 59 60 /* 61 * Sequence window definitions. 62 */ 63 #define SEQ_ARR_SIZE 4 64 #define SEQ_WIN (SEQ_ARR_SIZE*32) 65 #define SEQ_HI_BIT 0x80000000 66 #define SEQ_LO_BIT 1 67 #define DIV_BY_32 5 68 #define SEQ_MASK 0x1f 69 #define SEQ_MAX ((unsigned int)0x80000000) 70 71 72 /* cache retransmit data */ 73 typedef struct _retrans_entry { 74 uint32_t xid; 75 rpc_gss_init_res result; 76 } retrans_entry; 77 78 /* 79 * Server side RPCSEC_GSS context information. 80 */ 81 typedef struct _svc_rpc_gss_data { 82 struct _svc_rpc_gss_data *next, *prev; 83 struct _svc_rpc_gss_data *lru_next, *lru_prev; 84 bool_t established; 85 gss_ctx_id_t context; 86 gss_buffer_desc client_name; 87 time_t expiration; 88 uint_t seq_num; 89 uint_t seq_bits[SEQ_ARR_SIZE]; 90 uint_t key; 91 OM_uint32 qop; 92 bool_t done_docallback; 93 bool_t locked; 94 rpc_gss_rawcred_t raw_cred; 95 rpc_gss_ucred_t u_cred; 96 time_t u_cred_set; 97 void *cookie; 98 gss_cred_id_t deleg; 99 kmutex_t clm; 100 int ref_cnt; 101 time_t last_ref_time; 102 bool_t stale; 103 retrans_entry *retrans_data; 104 } svc_rpc_gss_data; 105 106 /* 107 * Data structures used for LRU based context management. 108 */ 109 110 111 #define HASH(key) ((key) % svc_rpc_gss_hashmod) 112 /* Size of hash table for svc_rpc_gss_data structures */ 113 #define GSS_DATA_HASH_SIZE 1024 114 115 /* 116 * The following two defines specify a time delta that is used in 117 * sweep_clients. When the last_ref_time of a context is older than 118 * than the current time minus the delta, i.e, the context has not 119 * been referenced in the last delta seconds, we will return the 120 * context back to the cache if the ref_cnt is zero. The first delta 121 * value will be used when sweep_clients is called from 122 * svc_data_reclaim, the kmem_cache reclaim call back. We will reclaim 123 * all entries except those that are currently "active". By active we 124 * mean those that have been referenced in the last ACTIVE_DELTA 125 * seconds. If sweep_client is not being called from reclaim, then we 126 * will reclaim all entries that are "inactive". By inactive we mean 127 * those entries that have not been accessed in INACTIVE_DELTA 128 * seconds. Note we always assume that ACTIVE_DELTA is less than 129 * INACTIVE_DELTA, so that reaping entries from a reclaim operation 130 * will necessarily imply reaping all "inactive" entries and then 131 * some. 132 */ 133 134 /* 135 * If low on memory reap cache entries that have not been active for 136 * ACTIVE_DELTA seconds and have a ref_cnt equal to zero. 137 */ 138 #define ACTIVE_DELTA 30*60 /* 30 minutes */ 139 140 /* 141 * If in sweeping contexts we find contexts with a ref_cnt equal to zero 142 * and the context has not been referenced in INACTIVE_DELTA seconds, return 143 * the entry to the cache. 144 */ 145 #define INACTIVE_DELTA 8*60*60 /* 8 hours */ 146 147 int svc_rpc_gss_hashmod = GSS_DATA_HASH_SIZE; 148 static svc_rpc_gss_data **clients; 149 static svc_rpc_gss_data *lru_first, *lru_last; 150 static time_t sweep_interval = 60*60; 151 static time_t last_swept = 0; 152 static int num_gss_contexts = 0; 153 static time_t svc_rpcgss_gid_timeout = 60*60*12; 154 static kmem_cache_t *svc_data_handle; 155 static time_t svc_rpc_gss_active_delta = ACTIVE_DELTA; 156 static time_t svc_rpc_gss_inactive_delta = INACTIVE_DELTA; 157 158 /* 159 * lock used with context/lru variables 160 */ 161 static kmutex_t ctx_mutex; 162 163 /* 164 * Data structure to contain cache statistics 165 */ 166 167 static struct { 168 int64_t total_entries_allocated; 169 int64_t no_reclaims; 170 int64_t no_returned_by_reclaim; 171 } svc_rpc_gss_cache_stats; 172 173 174 /* 175 * lock used with server credential variables list 176 * 177 * server cred list locking guidelines: 178 * - Writer's lock holder has exclusive access to the list 179 */ 180 static krwlock_t cred_lock; 181 182 /* 183 * server callback list 184 */ 185 typedef struct rpc_gss_cblist_s { 186 struct rpc_gss_cblist_s *next; 187 rpc_gss_callback_t cb; 188 } rpc_gss_cblist_t; 189 190 static rpc_gss_cblist_t *rpc_gss_cblist = NULL; 191 192 /* 193 * lock used with callback variables 194 */ 195 static kmutex_t cb_mutex; 196 197 /* 198 * forward declarations 199 */ 200 static bool_t svc_rpc_gss_wrap(); 201 static bool_t svc_rpc_gss_unwrap(); 202 static svc_rpc_gss_data *create_client(); 203 static svc_rpc_gss_data *get_client(); 204 static svc_rpc_gss_data *find_client(); 205 static void destroy_client(); 206 static void sweep_clients(bool_t); 207 static void insert_client(); 208 static bool_t check_verf(struct rpc_msg *, gss_ctx_id_t, 209 int *, uid_t); 210 static bool_t set_response_verf(); 211 static void retrans_add(svc_rpc_gss_data *, uint32_t, 212 rpc_gss_init_res *); 213 static void retrans_del(svc_rpc_gss_data *); 214 static bool_t transfer_sec_context(svc_rpc_gss_data *); 215 static void common_client_data_free(svc_rpc_gss_data *); 216 217 /* 218 * server side wrap/unwrap routines 219 */ 220 struct svc_auth_ops svc_rpc_gss_ops = { 221 svc_rpc_gss_wrap, 222 svc_rpc_gss_unwrap, 223 }; 224 225 /* taskq(9F) */ 226 typedef struct svcrpcsec_gss_taskq_arg { 227 SVCXPRT *rq_xprt; 228 rpc_gss_init_arg *rpc_call_arg; 229 struct rpc_msg *msg; 230 svc_rpc_gss_data *client_data; 231 uint_t cr_version; 232 rpc_gss_service_t cr_service; 233 } svcrpcsec_gss_taskq_arg_t; 234 235 /* gssd is single threaded, so 1 thread for the taskq is probably good/ok */ 236 int rpcsec_gss_init_taskq_nthreads = 1; 237 static ddi_taskq_t *svcrpcsec_gss_init_taskq = NULL; 238 239 extern struct rpc_msg *rpc_msg_dup(struct rpc_msg *); 240 extern void rpc_msg_free(struct rpc_msg **, int); 241 242 /* 243 * from svc_clts.c: 244 * Transport private data. 245 * Kept in xprt->xp_p2buf. 246 */ 247 struct udp_data { 248 mblk_t *ud_resp; /* buffer for response */ 249 mblk_t *ud_inmp; /* mblk chain of request */ 250 }; 251 252 /*ARGSUSED*/ 253 static int 254 svc_gss_data_create(void *buf, void *pdata, int kmflag) 255 { 256 svc_rpc_gss_data *client_data = (svc_rpc_gss_data *)buf; 257 258 mutex_init(&client_data->clm, NULL, MUTEX_DEFAULT, NULL); 259 260 return (0); 261 } 262 263 /*ARGSUSED*/ 264 static void 265 svc_gss_data_destroy(void *buf, void *pdata) 266 { 267 svc_rpc_gss_data *client_data = (svc_rpc_gss_data *)buf; 268 269 mutex_destroy(&client_data->clm); 270 } 271 272 273 /*ARGSUSED*/ 274 static void 275 svc_gss_data_reclaim(void *pdata) 276 { 277 mutex_enter(&ctx_mutex); 278 279 svc_rpc_gss_cache_stats.no_reclaims++; 280 sweep_clients(TRUE); 281 282 mutex_exit(&ctx_mutex); 283 } 284 285 /* 286 * Init stuff on the server side. 287 */ 288 void 289 svc_gss_init() 290 { 291 mutex_init(&cb_mutex, NULL, MUTEX_DEFAULT, NULL); 292 mutex_init(&ctx_mutex, NULL, MUTEX_DEFAULT, NULL); 293 rw_init(&cred_lock, NULL, RW_DEFAULT, NULL); 294 clients = (svc_rpc_gss_data **) 295 kmem_zalloc(svc_rpc_gss_hashmod * sizeof (svc_rpc_gss_data *), 296 KM_SLEEP); 297 svc_data_handle = kmem_cache_create("rpc_gss_data_cache", 298 sizeof (svc_rpc_gss_data), 0, 299 svc_gss_data_create, 300 svc_gss_data_destroy, 301 svc_gss_data_reclaim, 302 NULL, NULL, 0); 303 304 if (svcrpcsec_gss_init_taskq == NULL) { 305 svcrpcsec_gss_init_taskq = ddi_taskq_create(NULL, 306 "rpcsec_gss_init_taskq", rpcsec_gss_init_taskq_nthreads, 307 TASKQ_DEFAULTPRI, 0); 308 if (svcrpcsec_gss_init_taskq == NULL) 309 cmn_err(CE_NOTE, 310 "svc_gss_init: ddi_taskq_create failed"); 311 } 312 } 313 314 /* 315 * Destroy structures allocated in svc_gss_init(). 316 * This routine is called by _init() if mod_install() failed. 317 */ 318 void 319 svc_gss_fini() 320 { 321 mutex_destroy(&cb_mutex); 322 mutex_destroy(&ctx_mutex); 323 rw_destroy(&cred_lock); 324 kmem_free(clients, svc_rpc_gss_hashmod * sizeof (svc_rpc_gss_data *)); 325 kmem_cache_destroy(svc_data_handle); 326 } 327 328 /* 329 * Cleanup routine for destroying context, called after service 330 * procedure is executed. Actually we just decrement the reference count 331 * associated with this context. If the reference count is zero and the 332 * context is marked as stale, we would then destroy the context. Additionally, 333 * we check if its been longer than sweep_interval since the last sweep_clients 334 * was run, and if so run sweep_clients to free all stale contexts with zero 335 * reference counts or contexts that are old. (Haven't been access in 336 * svc_rpc_inactive_delta seconds). 337 */ 338 void 339 rpc_gss_cleanup(SVCXPRT *clone_xprt) 340 { 341 svc_rpc_gss_data *cl; 342 SVCAUTH *svcauth; 343 344 /* 345 * First check if current context needs to be cleaned up. 346 * There might be other threads stale this client data 347 * in between. 348 */ 349 svcauth = &clone_xprt->xp_auth; 350 mutex_enter(&ctx_mutex); 351 if ((cl = (svc_rpc_gss_data *)svcauth->svc_ah_private) != NULL) { 352 mutex_enter(&cl->clm); 353 ASSERT(cl->ref_cnt > 0); 354 if (--cl->ref_cnt == 0 && cl->stale) { 355 mutex_exit(&cl->clm); 356 destroy_client(cl); 357 svcauth->svc_ah_private = NULL; 358 } else 359 mutex_exit(&cl->clm); 360 } 361 362 /* 363 * Check for other expired contexts. 364 */ 365 if ((gethrestime_sec() - last_swept) > sweep_interval) 366 sweep_clients(FALSE); 367 368 mutex_exit(&ctx_mutex); 369 } 370 371 /* 372 * Shift the array arr of length arrlen right by nbits bits. 373 */ 374 static void 375 shift_bits(arr, arrlen, nbits) 376 uint_t *arr; 377 int arrlen; 378 int nbits; 379 { 380 int i, j; 381 uint_t lo, hi; 382 383 /* 384 * If the number of bits to be shifted exceeds SEQ_WIN, just 385 * zero out the array. 386 */ 387 if (nbits < SEQ_WIN) { 388 for (i = 0; i < nbits; i++) { 389 hi = 0; 390 for (j = 0; j < arrlen; j++) { 391 lo = arr[j] & SEQ_LO_BIT; 392 arr[j] >>= 1; 393 if (hi) 394 arr[j] |= SEQ_HI_BIT; 395 hi = lo; 396 } 397 } 398 } else { 399 for (j = 0; j < arrlen; j++) 400 arr[j] = 0; 401 } 402 } 403 404 /* 405 * Check that the received sequence number seq_num is valid. 406 */ 407 static bool_t 408 check_seq(cl, seq_num, kill_context) 409 svc_rpc_gss_data *cl; 410 uint_t seq_num; 411 bool_t *kill_context; 412 { 413 int i, j; 414 uint_t bit; 415 416 /* 417 * If it exceeds the maximum, kill context. 418 */ 419 if (seq_num >= SEQ_MAX) { 420 *kill_context = TRUE; 421 RPCGSS_LOG0(4, "check_seq: seq_num not valid\n"); 422 return (FALSE); 423 } 424 425 /* 426 * If greater than the last seen sequence number, just shift 427 * the sequence window so that it starts at the new sequence 428 * number and extends downwards by SEQ_WIN. 429 */ 430 if (seq_num > cl->seq_num) { 431 (void) shift_bits(cl->seq_bits, SEQ_ARR_SIZE, 432 (int)(seq_num - cl->seq_num)); 433 cl->seq_bits[0] |= SEQ_HI_BIT; 434 cl->seq_num = seq_num; 435 return (TRUE); 436 } 437 438 /* 439 * If it is outside the sequence window, return failure. 440 */ 441 i = cl->seq_num - seq_num; 442 if (i >= SEQ_WIN) { 443 RPCGSS_LOG0(4, "check_seq: seq_num is outside the window\n"); 444 return (FALSE); 445 } 446 447 /* 448 * If within sequence window, set the bit corresponding to it 449 * if not already seen; if already seen, return failure. 450 */ 451 j = SEQ_MASK - (i & SEQ_MASK); 452 bit = j > 0 ? (1 << j) : 1; 453 i >>= DIV_BY_32; 454 if (cl->seq_bits[i] & bit) { 455 RPCGSS_LOG0(4, "check_seq: sequence number already seen\n"); 456 return (FALSE); 457 } 458 cl->seq_bits[i] |= bit; 459 return (TRUE); 460 } 461 462 /* 463 * Set server callback. 464 */ 465 bool_t 466 rpc_gss_set_callback(cb) 467 rpc_gss_callback_t *cb; 468 { 469 rpc_gss_cblist_t *cbl, *tmp; 470 471 if (cb->callback == NULL) { 472 RPCGSS_LOG0(1, "rpc_gss_set_callback: no callback to set\n"); 473 return (FALSE); 474 } 475 476 /* check if there is already an entry in the rpc_gss_cblist. */ 477 mutex_enter(&cb_mutex); 478 if (rpc_gss_cblist) { 479 for (tmp = rpc_gss_cblist; tmp != NULL; tmp = tmp->next) { 480 if ((tmp->cb.callback == cb->callback) && 481 (tmp->cb.version == cb->version) && 482 (tmp->cb.program == cb->program)) { 483 mutex_exit(&cb_mutex); 484 return (TRUE); 485 } 486 } 487 } 488 489 /* Not in rpc_gss_cblist. Create a new entry. */ 490 if ((cbl = (rpc_gss_cblist_t *)kmem_alloc(sizeof (*cbl), KM_SLEEP)) 491 == NULL) { 492 mutex_exit(&cb_mutex); 493 return (FALSE); 494 } 495 cbl->cb = *cb; 496 cbl->next = rpc_gss_cblist; 497 rpc_gss_cblist = cbl; 498 mutex_exit(&cb_mutex); 499 return (TRUE); 500 } 501 502 /* 503 * Locate callback (if specified) and call server. Release any 504 * delegated credentials unless passed to server and the server 505 * accepts the context. If a callback is not specified, accept 506 * the incoming context. 507 */ 508 static bool_t 509 do_callback(req, client_data) 510 struct svc_req *req; 511 svc_rpc_gss_data *client_data; 512 { 513 rpc_gss_cblist_t *cbl; 514 bool_t ret = TRUE, found = FALSE; 515 rpc_gss_lock_t lock; 516 OM_uint32 minor; 517 mutex_enter(&cb_mutex); 518 for (cbl = rpc_gss_cblist; cbl != NULL; cbl = cbl->next) { 519 if (req->rq_prog != cbl->cb.program || 520 req->rq_vers != cbl->cb.version) 521 continue; 522 found = TRUE; 523 lock.locked = FALSE; 524 lock.raw_cred = &client_data->raw_cred; 525 ret = (*cbl->cb.callback)(req, client_data->deleg, 526 client_data->context, &lock, &client_data->cookie); 527 req->rq_xprt->xp_cookie = client_data->cookie; 528 529 if (ret) { 530 client_data->locked = lock.locked; 531 client_data->deleg = GSS_C_NO_CREDENTIAL; 532 } 533 break; 534 } 535 if (!found) { 536 if (client_data->deleg != GSS_C_NO_CREDENTIAL) { 537 (void) kgss_release_cred(&minor, &client_data->deleg, 538 crgetuid(CRED())); 539 client_data->deleg = GSS_C_NO_CREDENTIAL; 540 } 541 } 542 mutex_exit(&cb_mutex); 543 return (ret); 544 } 545 546 /* 547 * Get caller credentials. 548 */ 549 bool_t 550 rpc_gss_getcred(req, rcred, ucred, cookie) 551 struct svc_req *req; 552 rpc_gss_rawcred_t **rcred; 553 rpc_gss_ucred_t **ucred; 554 void **cookie; 555 { 556 SVCAUTH *svcauth; 557 svc_rpc_gss_data *client_data; 558 int gssstat, gidlen; 559 560 svcauth = &req->rq_xprt->xp_auth; 561 client_data = (svc_rpc_gss_data *)svcauth->svc_ah_private; 562 563 mutex_enter(&client_data->clm); 564 565 if (rcred != NULL) { 566 svcauth->raw_cred = client_data->raw_cred; 567 *rcred = &svcauth->raw_cred; 568 } 569 if (ucred != NULL) { 570 *ucred = &client_data->u_cred; 571 572 if (client_data->u_cred_set == 0 || 573 client_data->u_cred_set < gethrestime_sec()) { 574 if (client_data->u_cred_set == 0) { 575 if ((gssstat = kgsscred_expname_to_unix_cred( 576 &client_data->client_name, 577 &client_data->u_cred.uid, 578 &client_data->u_cred.gid, 579 &client_data->u_cred.gidlist, 580 &gidlen, crgetuid(CRED()))) != GSS_S_COMPLETE) { 581 RPCGSS_LOG(1, "rpc_gss_getcred: " 582 "kgsscred_expname_to_unix_cred failed %x\n", 583 gssstat); 584 *ucred = NULL; 585 } else { 586 client_data->u_cred.gidlen = (short)gidlen; 587 client_data->u_cred_set = 588 gethrestime_sec() + svc_rpcgss_gid_timeout; 589 } 590 } else if (client_data->u_cred_set < gethrestime_sec()) { 591 if ((gssstat = kgss_get_group_info( 592 client_data->u_cred.uid, 593 &client_data->u_cred.gid, 594 &client_data->u_cred.gidlist, 595 &gidlen, crgetuid(CRED()))) != GSS_S_COMPLETE) { 596 RPCGSS_LOG(1, "rpc_gss_getcred: " 597 "kgss_get_group_info failed %x\n", 598 gssstat); 599 *ucred = NULL; 600 } else { 601 client_data->u_cred.gidlen = (short)gidlen; 602 client_data->u_cred_set = 603 gethrestime_sec() + svc_rpcgss_gid_timeout; 604 } 605 } 606 } 607 } 608 609 if (cookie != NULL) 610 *cookie = client_data->cookie; 611 req->rq_xprt->xp_cookie = client_data->cookie; 612 613 mutex_exit(&client_data->clm); 614 615 return (TRUE); 616 } 617 618 /* 619 * Transfer the context data from the user land to the kernel. 620 */ 621 bool_t transfer_sec_context(svc_rpc_gss_data *client_data) { 622 623 gss_buffer_desc process_token; 624 OM_uint32 gssstat, minor; 625 626 /* 627 * Call kgss_export_sec_context 628 * if an error is returned log a message 629 * go to error handling 630 * Otherwise call kgss_import_sec_context to 631 * convert the token into a context 632 */ 633 gssstat = kgss_export_sec_context(&minor, client_data->context, 634 &process_token); 635 /* 636 * if export_sec_context returns an error we delete the 637 * context just to be safe. 638 */ 639 if (gssstat == GSS_S_NAME_NOT_MN) { 640 RPCGSS_LOG0(4, "svc_rpcsec_gss: export sec context " 641 "Kernel mod unavailable\n"); 642 643 } else if (gssstat != GSS_S_COMPLETE) { 644 RPCGSS_LOG(1, "svc_rpcsec_gss: export sec context failed " 645 " gssstat = 0x%x\n", gssstat); 646 (void) gss_release_buffer(&minor, &process_token); 647 (void) kgss_delete_sec_context(&minor, &client_data->context, 648 NULL); 649 return (FALSE); 650 651 } else if (process_token.length == 0) { 652 RPCGSS_LOG0(1, "svc_rpcsec_gss:zero length token in response " 653 "for export_sec_context, but " 654 "gsstat == GSS_S_COMPLETE\n"); 655 (void) kgss_delete_sec_context(&minor, &client_data->context, 656 NULL); 657 return (FALSE); 658 659 } else { 660 gssstat = kgss_import_sec_context(&minor, &process_token, 661 client_data->context); 662 if (gssstat != GSS_S_COMPLETE) { 663 RPCGSS_LOG(1, "svc_rpcsec_gss: import sec context " 664 " failed gssstat = 0x%x\n", gssstat); 665 (void) kgss_delete_sec_context(&minor, 666 &client_data->context, NULL); 667 (void) gss_release_buffer(&minor, &process_token); 668 return (FALSE); 669 } 670 671 RPCGSS_LOG0(4, "gss_import_sec_context successful\n"); 672 (void) gss_release_buffer(&minor, &process_token); 673 } 674 675 return (TRUE); 676 } 677 678 /* 679 * do_gss_accept is called from a taskq and does all the work for a 680 * RPCSEC_GSS_INIT call (mostly calling kgss_accept_sec_context()). 681 */ 682 static enum auth_stat 683 do_gss_accept( 684 SVCXPRT *xprt, 685 rpc_gss_init_arg *call_arg, 686 struct rpc_msg *msg, 687 svc_rpc_gss_data *client_data, 688 uint_t cr_version, 689 rpc_gss_service_t cr_service) 690 { 691 rpc_gss_init_res call_res; 692 gss_buffer_desc output_token; 693 OM_uint32 gssstat, minor, minor_stat, time_rec; 694 int ret_flags, ret; 695 gss_OID mech_type = GSS_C_NULL_OID; 696 int free_mech_type = 1; 697 struct svc_req r, *rqst; 698 699 rqst = &r; 700 rqst->rq_xprt = xprt; 701 702 /* 703 * Initialize output_token. 704 */ 705 output_token.length = 0; 706 output_token.value = NULL; 707 708 bzero((char *)&call_res, sizeof (call_res)); 709 710 mutex_enter(&client_data->clm); 711 if (client_data->stale) { 712 ret = RPCSEC_GSS_NOCRED; 713 RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n"); 714 goto error2; 715 } 716 717 /* 718 * Any response we send will use ctx_handle, so set it now; 719 * also set seq_window since this won't change. 720 */ 721 call_res.ctx_handle.length = sizeof (client_data->key); 722 call_res.ctx_handle.value = (char *)&client_data->key; 723 call_res.seq_window = SEQ_WIN; 724 725 gssstat = GSS_S_FAILURE; 726 minor = 0; 727 minor_stat = 0; 728 rw_enter(&cred_lock, RW_READER); 729 730 if (client_data->client_name.length) { 731 (void) gss_release_buffer(&minor, 732 &client_data->client_name); 733 } 734 gssstat = kgss_accept_sec_context(&minor_stat, 735 &client_data->context, 736 GSS_C_NO_CREDENTIAL, 737 call_arg, 738 GSS_C_NO_CHANNEL_BINDINGS, 739 &client_data->client_name, 740 &mech_type, 741 &output_token, 742 &ret_flags, 743 &time_rec, 744 NULL, /* don't need a delegated cred back */ 745 crgetuid(CRED())); 746 747 RPCGSS_LOG(4, "gssstat 0x%x \n", gssstat); 748 749 if (gssstat == GSS_S_COMPLETE) { 750 /* 751 * Set the raw and unix credentials at this 752 * point. This saves a lot of computation 753 * later when credentials are retrieved. 754 */ 755 client_data->raw_cred.version = cr_version; 756 client_data->raw_cred.service = cr_service; 757 758 if (client_data->raw_cred.mechanism) { 759 kgss_free_oid(client_data->raw_cred.mechanism); 760 client_data->raw_cred.mechanism = NULL; 761 } 762 client_data->raw_cred.mechanism = (rpc_gss_OID) mech_type; 763 /* 764 * client_data is now responsible for freeing 765 * the data of 'mech_type'. 766 */ 767 free_mech_type = 0; 768 769 if (client_data->raw_cred.client_principal) { 770 kmem_free((caddr_t)client_data->\ 771 raw_cred.client_principal, 772 client_data->raw_cred.\ 773 client_principal->len + sizeof (int)); 774 client_data->raw_cred.client_principal = NULL; 775 } 776 777 /* 778 * The client_name returned from 779 * kgss_accept_sec_context() is in an 780 * exported flat format. 781 */ 782 if (! __rpc_gss_make_principal( 783 &client_data->raw_cred.client_principal, 784 &client_data->client_name)) { 785 RPCGSS_LOG0(1, "_svcrpcsec_gss: " 786 "make principal failed\n"); 787 gssstat = GSS_S_FAILURE; 788 (void) gss_release_buffer(&minor_stat, &output_token); 789 } 790 } 791 792 rw_exit(&cred_lock); 793 794 call_res.gss_major = gssstat; 795 call_res.gss_minor = minor_stat; 796 797 if (gssstat != GSS_S_COMPLETE && 798 gssstat != GSS_S_CONTINUE_NEEDED) { 799 call_res.ctx_handle.length = 0; 800 call_res.ctx_handle.value = NULL; 801 call_res.seq_window = 0; 802 rpc_gss_display_status(gssstat, minor_stat, mech_type, 803 crgetuid(CRED()), 804 "_svc_rpcsec_gss gss_accept_sec_context"); 805 (void) svc_sendreply(rqst->rq_xprt, 806 __xdr_rpc_gss_init_res, (caddr_t)&call_res); 807 client_data->stale = TRUE; 808 ret = AUTH_OK; 809 goto error2; 810 } 811 812 /* 813 * If appropriate, set established to TRUE *after* sending 814 * response (otherwise, the client will receive the final 815 * token encrypted) 816 */ 817 if (gssstat == GSS_S_COMPLETE) { 818 /* 819 * Context is established. Set expiration time 820 * for the context. 821 */ 822 client_data->seq_num = 1; 823 if ((time_rec == GSS_C_INDEFINITE) || (time_rec == 0)) { 824 client_data->expiration = GSS_C_INDEFINITE; 825 } else { 826 client_data->expiration = 827 time_rec + gethrestime_sec(); 828 } 829 830 if (!transfer_sec_context(client_data)) { 831 ret = RPCSEC_GSS_FAILED; 832 client_data->stale = TRUE; 833 RPCGSS_LOG0(1, 834 "_svc_rpcsec_gss: transfer sec context failed\n"); 835 goto error2; 836 } 837 838 client_data->established = TRUE; 839 } 840 841 /* 842 * This step succeeded. Send a response, along with 843 * a token if there's one. Don't dispatch. 844 */ 845 846 if (output_token.length != 0) 847 GSS_COPY_BUFFER(call_res.token, output_token); 848 849 /* 850 * If GSS_S_COMPLETE: set response verifier to 851 * checksum of SEQ_WIN 852 */ 853 if (gssstat == GSS_S_COMPLETE) { 854 if (!set_response_verf(rqst, msg, client_data, 855 (uint_t)SEQ_WIN)) { 856 ret = RPCSEC_GSS_FAILED; 857 client_data->stale = TRUE; 858 RPCGSS_LOG0(1, 859 "_svc_rpcsec_gss:set response verifier failed\n"); 860 goto error2; 861 } 862 } 863 864 if (!svc_sendreply(rqst->rq_xprt, __xdr_rpc_gss_init_res, 865 (caddr_t)&call_res)) { 866 ret = RPCSEC_GSS_FAILED; 867 client_data->stale = TRUE; 868 RPCGSS_LOG0(1, "_svc_rpcsec_gss:send reply failed\n"); 869 goto error2; 870 } 871 872 /* 873 * Cache last response in case it is lost and the client 874 * retries on an established context. 875 */ 876 (void) retrans_add(client_data, msg->rm_xid, &call_res); 877 ASSERT(client_data->ref_cnt > 0); 878 client_data->ref_cnt--; 879 mutex_exit(&client_data->clm); 880 881 (void) gss_release_buffer(&minor_stat, &output_token); 882 883 return (AUTH_OK); 884 885 error2: 886 ASSERT(client_data->ref_cnt > 0); 887 client_data->ref_cnt--; 888 mutex_exit(&client_data->clm); 889 (void) gss_release_buffer(&minor_stat, &output_token); 890 if (free_mech_type && mech_type) 891 kgss_free_oid(mech_type); 892 893 return (ret); 894 } 895 896 static void 897 svcrpcsec_gss_taskq_func(void *svcrpcsecgss_taskq_arg) 898 { 899 enum auth_stat retval; 900 svcrpcsec_gss_taskq_arg_t *arg = svcrpcsecgss_taskq_arg; 901 902 retval = do_gss_accept(arg->rq_xprt, arg->rpc_call_arg, arg->msg, 903 arg->client_data, arg->cr_version, arg->cr_service); 904 if (retval != AUTH_OK) { 905 cmn_err(CE_NOTE, 906 "svcrpcsec_gss_taskq_func: do_gss_accept fail 0x%x", 907 retval); 908 } 909 rpc_msg_free(&arg->msg, MAX_AUTH_BYTES); 910 svc_clone_unlink(arg->rq_xprt); 911 svc_clone_free(arg->rq_xprt); 912 xdr_free(__xdr_rpc_gss_init_arg, (caddr_t)arg->rpc_call_arg); 913 kmem_free(arg->rpc_call_arg, sizeof (*arg->rpc_call_arg)); 914 915 kmem_free(arg, sizeof (*arg)); 916 } 917 918 static enum auth_stat 919 rpcsec_gss_init( 920 struct svc_req *rqst, 921 struct rpc_msg *msg, 922 rpc_gss_creds creds, 923 bool_t *no_dispatch, 924 svc_rpc_gss_data *c_d) /* client data, can be NULL */ 925 { 926 svc_rpc_gss_data *client_data; 927 int ret; 928 svcrpcsec_gss_taskq_arg_t *arg; 929 930 if (creds.ctx_handle.length != 0) { 931 RPCGSS_LOG0(1, "_svcrpcsec_gss: ctx_handle not null\n"); 932 ret = AUTH_BADCRED; 933 return (ret); 934 } 935 936 client_data = c_d ? c_d : create_client(); 937 if (client_data == NULL) { 938 RPCGSS_LOG0(1, 939 "_svcrpcsec_gss: can't create a new cache entry\n"); 940 ret = AUTH_FAILED; 941 return (ret); 942 } 943 944 mutex_enter(&client_data->clm); 945 if (client_data->stale) { 946 ret = RPCSEC_GSS_NOCRED; 947 RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n"); 948 goto error2; 949 } 950 951 /* 952 * kgss_accept_sec_context()/gssd(1M) can be overly time 953 * consuming so let's queue it and return asap. 954 * 955 * taskq func must free arg. 956 */ 957 arg = kmem_alloc(sizeof (*arg), KM_SLEEP); 958 959 /* taskq func must free rpc_call_arg & deserialized arguments */ 960 arg->rpc_call_arg = kmem_alloc(sizeof (*arg->rpc_call_arg), KM_SLEEP); 961 962 /* deserialize arguments */ 963 bzero(arg->rpc_call_arg, sizeof (*arg->rpc_call_arg)); 964 if (!SVC_GETARGS(rqst->rq_xprt, __xdr_rpc_gss_init_arg, 965 (caddr_t)arg->rpc_call_arg)) { 966 ret = RPCSEC_GSS_FAILED; 967 client_data->stale = TRUE; 968 goto error2; 969 } 970 971 /* get a xprt clone for taskq thread, taskq func must free it */ 972 arg->rq_xprt = svc_clone_init(); 973 svc_clone_link(rqst->rq_xprt->xp_master, arg->rq_xprt, rqst->rq_xprt); 974 arg->rq_xprt->xp_xid = rqst->rq_xprt->xp_xid; 975 976 977 /* set the appropriate wrap/unwrap routine for RPCSEC_GSS */ 978 arg->rq_xprt->xp_auth.svc_ah_ops = svc_rpc_gss_ops; 979 arg->rq_xprt->xp_auth.svc_ah_private = (caddr_t)client_data; 980 981 /* get a dup of rpc msg for taskq thread */ 982 arg->msg = rpc_msg_dup(msg); /* taskq func must free msg dup */ 983 984 arg->client_data = client_data; 985 arg->cr_version = creds.version; 986 arg->cr_service = creds.service; 987 988 /* We no longer need the xp_xdrin, destroy it all here. */ 989 XDR_DESTROY(&(rqst->rq_xprt->xp_xdrin)); 990 991 /* should be ok to hold clm lock as taskq will have new thread(s) */ 992 ret = ddi_taskq_dispatch(svcrpcsec_gss_init_taskq, 993 svcrpcsec_gss_taskq_func, arg, DDI_SLEEP); 994 if (ret == DDI_FAILURE) { 995 cmn_err(CE_NOTE, "rpcsec_gss_init: taskq dispatch fail"); 996 ret = RPCSEC_GSS_FAILED; 997 rpc_msg_free(&arg->msg, MAX_AUTH_BYTES); 998 svc_clone_unlink(arg->rq_xprt); 999 svc_clone_free(arg->rq_xprt); 1000 kmem_free(arg, sizeof (*arg)); 1001 goto error2; 1002 } 1003 1004 mutex_exit(&client_data->clm); 1005 *no_dispatch = TRUE; 1006 return (AUTH_OK); 1007 1008 error2: 1009 ASSERT(client_data->ref_cnt > 0); 1010 client_data->ref_cnt--; 1011 mutex_exit(&client_data->clm); 1012 cmn_err(CE_NOTE, "rpcsec_gss_init: error 0x%x", ret); 1013 return (ret); 1014 } 1015 1016 static enum auth_stat 1017 rpcsec_gss_continue_init( 1018 struct svc_req *rqst, 1019 struct rpc_msg *msg, 1020 rpc_gss_creds creds, 1021 bool_t *no_dispatch) 1022 { 1023 int ret; 1024 svc_rpc_gss_data *client_data; 1025 svc_rpc_gss_parms_t *gss_parms; 1026 rpc_gss_init_res *retrans_result; 1027 1028 if (creds.ctx_handle.length == 0) { 1029 RPCGSS_LOG0(1, "_svcrpcsec_gss: no ctx_handle\n"); 1030 ret = AUTH_BADCRED; 1031 return (ret); 1032 } 1033 if ((client_data = get_client(&creds.ctx_handle)) == NULL) { 1034 ret = RPCSEC_GSS_NOCRED; 1035 RPCGSS_LOG0(1, "_svcrpcsec_gss: no security context\n"); 1036 return (ret); 1037 } 1038 1039 mutex_enter(&client_data->clm); 1040 if (client_data->stale) { 1041 ret = RPCSEC_GSS_NOCRED; 1042 RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n"); 1043 goto error2; 1044 } 1045 1046 /* 1047 * If context not established, go thru INIT code but with 1048 * this client handle. 1049 */ 1050 if (!client_data->established) { 1051 mutex_exit(&client_data->clm); 1052 return (rpcsec_gss_init(rqst, msg, creds, no_dispatch, 1053 client_data)); 1054 } 1055 1056 /* 1057 * Set the appropriate wrap/unwrap routine for RPCSEC_GSS. 1058 */ 1059 rqst->rq_xprt->xp_auth.svc_ah_ops = svc_rpc_gss_ops; 1060 rqst->rq_xprt->xp_auth.svc_ah_private = (caddr_t)client_data; 1061 1062 /* 1063 * Keep copy of parameters we'll need for response, for the 1064 * sake of reentrancy (we don't want to look in the context 1065 * data because when we are sending a response, another 1066 * request may have come in). 1067 */ 1068 gss_parms = &rqst->rq_xprt->xp_auth.svc_gss_parms; 1069 gss_parms->established = client_data->established; 1070 gss_parms->service = creds.service; 1071 gss_parms->qop_rcvd = (uint_t)client_data->qop; 1072 gss_parms->context = (void *)client_data->context; 1073 gss_parms->seq_num = creds.seq_num; 1074 1075 /* 1076 * This is an established context. Continue to 1077 * satisfy retried continue init requests out of 1078 * the retransmit cache. Throw away any that don't 1079 * have a matching xid or the cach is empty. 1080 * Delete the retransmit cache once the client sends 1081 * a data request. 1082 */ 1083 if (client_data->retrans_data && 1084 (client_data->retrans_data->xid == msg->rm_xid)) { 1085 retrans_result = &client_data->retrans_data->result; 1086 if (set_response_verf(rqst, msg, client_data, 1087 (uint_t)retrans_result->seq_window)) { 1088 gss_parms->established = FALSE; 1089 (void) svc_sendreply(rqst->rq_xprt, 1090 __xdr_rpc_gss_init_res, (caddr_t)retrans_result); 1091 *no_dispatch = TRUE; 1092 ASSERT(client_data->ref_cnt > 0); 1093 client_data->ref_cnt--; 1094 } 1095 } 1096 mutex_exit(&client_data->clm); 1097 1098 return (AUTH_OK); 1099 1100 error2: 1101 ASSERT(client_data->ref_cnt > 0); 1102 client_data->ref_cnt--; 1103 mutex_exit(&client_data->clm); 1104 return (ret); 1105 } 1106 1107 static enum auth_stat 1108 rpcsec_gss_data( 1109 struct svc_req *rqst, 1110 struct rpc_msg *msg, 1111 rpc_gss_creds creds, 1112 bool_t *no_dispatch) 1113 { 1114 int ret; 1115 svc_rpc_gss_parms_t *gss_parms; 1116 svc_rpc_gss_data *client_data; 1117 1118 switch (creds.service) { 1119 case rpc_gss_svc_none: 1120 case rpc_gss_svc_integrity: 1121 case rpc_gss_svc_privacy: 1122 break; 1123 default: 1124 cmn_err(CE_NOTE, "__svcrpcsec_gss: unknown service type=0x%x", 1125 creds.service); 1126 RPCGSS_LOG(1, "_svcrpcsec_gss: unknown service type: 0x%x\n", 1127 creds.service); 1128 ret = AUTH_BADCRED; 1129 return (ret); 1130 } 1131 1132 if (creds.ctx_handle.length == 0) { 1133 RPCGSS_LOG0(1, "_svcrpcsec_gss: no ctx_handle\n"); 1134 ret = AUTH_BADCRED; 1135 return (ret); 1136 } 1137 if ((client_data = get_client(&creds.ctx_handle)) == NULL) { 1138 ret = RPCSEC_GSS_NOCRED; 1139 RPCGSS_LOG0(1, "_svcrpcsec_gss: no security context\n"); 1140 return (ret); 1141 } 1142 1143 1144 mutex_enter(&client_data->clm); 1145 if (!client_data->established) { 1146 ret = AUTH_FAILED; 1147 goto error2; 1148 } 1149 if (client_data->stale) { 1150 ret = RPCSEC_GSS_NOCRED; 1151 RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n"); 1152 goto error2; 1153 } 1154 1155 /* 1156 * Once the context is established and there is no more 1157 * retransmission of last continue init request, it is safe 1158 * to delete the retransmit cache entry. 1159 */ 1160 if (client_data->retrans_data) 1161 retrans_del(client_data); 1162 1163 /* 1164 * Set the appropriate wrap/unwrap routine for RPCSEC_GSS. 1165 */ 1166 rqst->rq_xprt->xp_auth.svc_ah_ops = svc_rpc_gss_ops; 1167 rqst->rq_xprt->xp_auth.svc_ah_private = (caddr_t)client_data; 1168 1169 /* 1170 * Keep copy of parameters we'll need for response, for the 1171 * sake of reentrancy (we don't want to look in the context 1172 * data because when we are sending a response, another 1173 * request may have come in). 1174 */ 1175 gss_parms = &rqst->rq_xprt->xp_auth.svc_gss_parms; 1176 gss_parms->established = client_data->established; 1177 gss_parms->service = creds.service; 1178 gss_parms->qop_rcvd = (uint_t)client_data->qop; 1179 gss_parms->context = (void *)client_data->context; 1180 gss_parms->seq_num = creds.seq_num; 1181 1182 /* 1183 * Context is already established. Check verifier, and 1184 * note parameters we will need for response in gss_parms. 1185 */ 1186 if (!check_verf(msg, client_data->context, 1187 (int *)&gss_parms->qop_rcvd, client_data->u_cred.uid)) { 1188 ret = RPCSEC_GSS_NOCRED; 1189 RPCGSS_LOG0(1, "_svcrpcsec_gss: check verf failed\n"); 1190 goto error2; 1191 } 1192 1193 /* 1194 * Check and invoke callback if necessary. 1195 */ 1196 if (!client_data->done_docallback) { 1197 client_data->done_docallback = TRUE; 1198 client_data->qop = gss_parms->qop_rcvd; 1199 client_data->raw_cred.qop = gss_parms->qop_rcvd; 1200 client_data->raw_cred.service = creds.service; 1201 if (!do_callback(rqst, client_data)) { 1202 ret = AUTH_FAILED; 1203 RPCGSS_LOG0(1, "_svc_rpcsec_gss:callback failed\n"); 1204 goto error2; 1205 } 1206 } 1207 1208 /* 1209 * If the context was locked, make sure that the client 1210 * has not changed QOP. 1211 */ 1212 if (client_data->locked && gss_parms->qop_rcvd != client_data->qop) { 1213 ret = AUTH_BADVERF; 1214 RPCGSS_LOG0(1, "_svcrpcsec_gss: can not change qop\n"); 1215 goto error2; 1216 } 1217 1218 /* 1219 * Validate sequence number. 1220 */ 1221 if (!check_seq(client_data, creds.seq_num, &client_data->stale)) { 1222 if (client_data->stale) { 1223 ret = RPCSEC_GSS_FAILED; 1224 RPCGSS_LOG0(1, 1225 "_svc_rpcsec_gss:check seq failed\n"); 1226 } else { 1227 RPCGSS_LOG0(4, "_svc_rpcsec_gss:check seq " 1228 "failed on good context. Ignoring " 1229 "request\n"); 1230 /* 1231 * Operational error, drop packet silently. 1232 * The client will recover after timing out, 1233 * assuming this is a client error and not 1234 * a relpay attack. Don't dispatch. 1235 */ 1236 ret = AUTH_OK; 1237 *no_dispatch = TRUE; 1238 } 1239 goto error2; 1240 } 1241 1242 /* 1243 * set response verifier 1244 */ 1245 if (!set_response_verf(rqst, msg, client_data, creds.seq_num)) { 1246 ret = RPCSEC_GSS_FAILED; 1247 client_data->stale = TRUE; 1248 RPCGSS_LOG0(1, 1249 "_svc_rpcsec_gss:set response verifier failed\n"); 1250 goto error2; 1251 } 1252 1253 /* 1254 * If context is locked, make sure that the client 1255 * has not changed the security service. 1256 */ 1257 if (client_data->locked && 1258 client_data->raw_cred.service != creds.service) { 1259 RPCGSS_LOG0(1, "_svc_rpcsec_gss: " 1260 "security service changed.\n"); 1261 ret = AUTH_FAILED; 1262 goto error2; 1263 } 1264 1265 /* 1266 * Set client credentials to raw credential 1267 * structure in context. This is okay, since 1268 * this will not change during the lifetime of 1269 * the context (so it's MT safe). 1270 */ 1271 rqst->rq_clntcred = (char *)&client_data->raw_cred; 1272 1273 mutex_exit(&client_data->clm); 1274 return (AUTH_OK); 1275 1276 error2: 1277 ASSERT(client_data->ref_cnt > 0); 1278 client_data->ref_cnt--; 1279 mutex_exit(&client_data->clm); 1280 return (ret); 1281 } 1282 1283 /* 1284 * Note we don't have a client yet to use this routine and test it. 1285 */ 1286 static enum auth_stat 1287 rpcsec_gss_destroy( 1288 struct svc_req *rqst, 1289 rpc_gss_creds creds, 1290 bool_t *no_dispatch) 1291 { 1292 svc_rpc_gss_data *client_data; 1293 int ret; 1294 1295 if (creds.ctx_handle.length == 0) { 1296 RPCGSS_LOG0(1, "_svcrpcsec_gss: no ctx_handle\n"); 1297 ret = AUTH_BADCRED; 1298 return (ret); 1299 } 1300 if ((client_data = get_client(&creds.ctx_handle)) == NULL) { 1301 ret = RPCSEC_GSS_NOCRED; 1302 RPCGSS_LOG0(1, "_svcrpcsec_gss: no security context\n"); 1303 return (ret); 1304 } 1305 1306 mutex_enter(&client_data->clm); 1307 if (!client_data->established) { 1308 ret = AUTH_FAILED; 1309 goto error2; 1310 } 1311 if (client_data->stale) { 1312 ret = RPCSEC_GSS_NOCRED; 1313 RPCGSS_LOG0(1, "_svcrpcsec_gss: client data stale\n"); 1314 goto error2; 1315 } 1316 1317 (void) svc_sendreply(rqst->rq_xprt, xdr_void, NULL); 1318 *no_dispatch = TRUE; 1319 ASSERT(client_data->ref_cnt > 0); 1320 client_data->ref_cnt--; 1321 client_data->stale = TRUE; 1322 mutex_exit(&client_data->clm); 1323 return (AUTH_OK); 1324 1325 error2: 1326 ASSERT(client_data->ref_cnt > 0); 1327 client_data->ref_cnt--; 1328 client_data->stale = TRUE; 1329 mutex_exit(&client_data->clm); 1330 return (ret); 1331 } 1332 1333 /* 1334 * Server side authentication for RPCSEC_GSS. 1335 */ 1336 enum auth_stat 1337 __svcrpcsec_gss( 1338 struct svc_req *rqst, 1339 struct rpc_msg *msg, 1340 bool_t *no_dispatch) 1341 { 1342 XDR xdrs; 1343 rpc_gss_creds creds; 1344 struct opaque_auth *cred; 1345 int ret; 1346 1347 *no_dispatch = FALSE; 1348 1349 /* 1350 * Initialize response verifier to NULL verifier. If 1351 * necessary, this will be changed later. 1352 */ 1353 rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NONE; 1354 rqst->rq_xprt->xp_verf.oa_base = NULL; 1355 rqst->rq_xprt->xp_verf.oa_length = 0; 1356 1357 /* 1358 * Pull out and check credential and verifier. 1359 */ 1360 cred = &msg->rm_call.cb_cred; 1361 1362 if (cred->oa_length == 0) { 1363 RPCGSS_LOG0(1, "_svcrpcsec_gss: zero length cred\n"); 1364 return (AUTH_BADCRED); 1365 } 1366 1367 xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE); 1368 bzero((char *)&creds, sizeof (creds)); 1369 if (!__xdr_rpc_gss_creds(&xdrs, &creds)) { 1370 XDR_DESTROY(&xdrs); 1371 RPCGSS_LOG0(1, "_svcrpcsec_gss: can't decode creds\n"); 1372 ret = AUTH_BADCRED; 1373 return (AUTH_BADCRED); 1374 } 1375 XDR_DESTROY(&xdrs); 1376 1377 switch (creds.gss_proc) { 1378 case RPCSEC_GSS_INIT: 1379 ret = rpcsec_gss_init(rqst, msg, creds, no_dispatch, NULL); 1380 break; 1381 case RPCSEC_GSS_CONTINUE_INIT: 1382 ret = rpcsec_gss_continue_init(rqst, msg, creds, no_dispatch); 1383 break; 1384 case RPCSEC_GSS_DATA: 1385 ret = rpcsec_gss_data(rqst, msg, creds, no_dispatch); 1386 break; 1387 case RPCSEC_GSS_DESTROY: 1388 ret = rpcsec_gss_destroy(rqst, creds, no_dispatch); 1389 break; 1390 default: 1391 cmn_err(CE_NOTE, "__svcrpcsec_gss: bad proc=%d", 1392 creds.gss_proc); 1393 ret = AUTH_BADCRED; 1394 } 1395 1396 if (creds.ctx_handle.length != 0) 1397 xdr_free(__xdr_rpc_gss_creds, (caddr_t)&creds); 1398 return (ret); 1399 } 1400 1401 /* 1402 * Check verifier. The verifier is the checksum of the RPC header 1403 * upto and including the credentials field. 1404 */ 1405 1406 /* ARGSUSED */ 1407 static bool_t 1408 check_verf(struct rpc_msg *msg, gss_ctx_id_t context, int *qop_state, uid_t uid) 1409 { 1410 int *buf, *tmp; 1411 char hdr[128]; 1412 struct opaque_auth *oa; 1413 int len; 1414 gss_buffer_desc msg_buf; 1415 gss_buffer_desc tok_buf; 1416 OM_uint32 gssstat, minor_stat; 1417 1418 /* 1419 * We have to reconstruct the RPC header from the previously 1420 * parsed information, since we haven't kept the header intact. 1421 */ 1422 1423 oa = &msg->rm_call.cb_cred; 1424 if (oa->oa_length > MAX_AUTH_BYTES) 1425 return (FALSE); 1426 1427 /* 8 XDR units from the IXDR macro calls. */ 1428 if (sizeof (hdr) < (8 * BYTES_PER_XDR_UNIT + 1429 RNDUP(oa->oa_length))) 1430 return (FALSE); 1431 buf = (int *)hdr; 1432 IXDR_PUT_U_INT32(buf, msg->rm_xid); 1433 IXDR_PUT_ENUM(buf, msg->rm_direction); 1434 IXDR_PUT_U_INT32(buf, msg->rm_call.cb_rpcvers); 1435 IXDR_PUT_U_INT32(buf, msg->rm_call.cb_prog); 1436 IXDR_PUT_U_INT32(buf, msg->rm_call.cb_vers); 1437 IXDR_PUT_U_INT32(buf, msg->rm_call.cb_proc); 1438 IXDR_PUT_ENUM(buf, oa->oa_flavor); 1439 IXDR_PUT_U_INT32(buf, oa->oa_length); 1440 if (oa->oa_length) { 1441 len = RNDUP(oa->oa_length); 1442 tmp = buf; 1443 buf += len / sizeof (int); 1444 *(buf - 1) = 0; 1445 (void) bcopy(oa->oa_base, (caddr_t)tmp, oa->oa_length); 1446 } 1447 len = ((char *)buf) - hdr; 1448 msg_buf.length = len; 1449 msg_buf.value = hdr; 1450 oa = &msg->rm_call.cb_verf; 1451 tok_buf.length = oa->oa_length; 1452 tok_buf.value = oa->oa_base; 1453 1454 gssstat = kgss_verify(&minor_stat, context, &msg_buf, &tok_buf, 1455 qop_state); 1456 if (gssstat != GSS_S_COMPLETE) { 1457 RPCGSS_LOG(1, "check_verf: kgss_verify status 0x%x\n", gssstat); 1458 1459 RPCGSS_LOG(4, "check_verf: msg_buf length %d\n", len); 1460 RPCGSS_LOG(4, "check_verf: msg_buf value 0x%x\n", *(int *)hdr); 1461 RPCGSS_LOG(4, "check_verf: tok_buf length %ld\n", 1462 tok_buf.length); 1463 RPCGSS_LOG(4, "check_verf: tok_buf value 0x%p\n", 1464 (void *)oa->oa_base); 1465 RPCGSS_LOG(4, "check_verf: context 0x%p\n", (void *)context); 1466 1467 return (FALSE); 1468 } 1469 return (TRUE); 1470 } 1471 1472 1473 /* 1474 * Set response verifier. This is the checksum of the given number. 1475 * (e.g. sequence number or sequence window) 1476 */ 1477 static bool_t 1478 set_response_verf(rqst, msg, cl, num) 1479 struct svc_req *rqst; 1480 struct rpc_msg *msg; 1481 svc_rpc_gss_data *cl; 1482 uint_t num; 1483 { 1484 OM_uint32 minor; 1485 gss_buffer_desc in_buf, out_buf; 1486 uint_t num_net; 1487 1488 num_net = (uint_t)htonl(num); 1489 in_buf.length = sizeof (num); 1490 in_buf.value = (char *)&num_net; 1491 /* XXX uid ? */ 1492 1493 if ((kgss_sign(&minor, cl->context, cl->qop, &in_buf, 1494 &out_buf)) != GSS_S_COMPLETE) 1495 return (FALSE); 1496 1497 rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; 1498 rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; 1499 rqst->rq_xprt->xp_verf.oa_length = out_buf.length; 1500 bcopy(out_buf.value, rqst->rq_xprt->xp_verf.oa_base, out_buf.length); 1501 (void) gss_release_buffer(&minor, &out_buf); 1502 return (TRUE); 1503 } 1504 1505 /* 1506 * Create client context. 1507 */ 1508 static svc_rpc_gss_data * 1509 create_client() 1510 { 1511 svc_rpc_gss_data *client_data; 1512 static uint_t key = 1; 1513 1514 client_data = (svc_rpc_gss_data *) kmem_cache_alloc(svc_data_handle, 1515 KM_SLEEP); 1516 if (client_data == NULL) 1517 return (NULL); 1518 1519 /* 1520 * set up client data structure 1521 */ 1522 client_data->next = NULL; 1523 client_data->prev = NULL; 1524 client_data->lru_next = NULL; 1525 client_data->lru_prev = NULL; 1526 client_data->client_name.length = 0; 1527 client_data->client_name.value = NULL; 1528 client_data->seq_num = 0; 1529 bzero(client_data->seq_bits, sizeof (client_data->seq_bits)); 1530 client_data->key = 0; 1531 client_data->cookie = NULL; 1532 bzero(&client_data->u_cred, sizeof (client_data->u_cred)); 1533 client_data->established = FALSE; 1534 client_data->locked = FALSE; 1535 client_data->u_cred_set = 0; 1536 client_data->context = GSS_C_NO_CONTEXT; 1537 client_data->expiration = GSS_C_INDEFINITE; 1538 client_data->deleg = GSS_C_NO_CREDENTIAL; 1539 client_data->ref_cnt = 1; 1540 client_data->last_ref_time = gethrestime_sec(); 1541 client_data->qop = GSS_C_QOP_DEFAULT; 1542 client_data->done_docallback = FALSE; 1543 client_data->stale = FALSE; 1544 client_data->retrans_data = NULL; 1545 bzero(&client_data->raw_cred, sizeof (client_data->raw_cred)); 1546 1547 /* 1548 * The client context handle is a 32-bit key (unsigned int). 1549 * The key is incremented until there is no duplicate for it. 1550 */ 1551 1552 svc_rpc_gss_cache_stats.total_entries_allocated++; 1553 mutex_enter(&ctx_mutex); 1554 for (;;) { 1555 client_data->key = key++; 1556 if (find_client(client_data->key) == NULL) { 1557 insert_client(client_data); 1558 mutex_exit(&ctx_mutex); 1559 return (client_data); 1560 } 1561 } 1562 /*NOTREACHED*/ 1563 } 1564 1565 /* 1566 * Insert client context into hash list and LRU list. 1567 */ 1568 static void 1569 insert_client(client_data) 1570 svc_rpc_gss_data *client_data; 1571 { 1572 svc_rpc_gss_data *cl; 1573 int index = HASH(client_data->key); 1574 1575 ASSERT(mutex_owned(&ctx_mutex)); 1576 1577 client_data->prev = NULL; 1578 cl = clients[index]; 1579 if ((client_data->next = cl) != NULL) 1580 cl->prev = client_data; 1581 clients[index] = client_data; 1582 1583 client_data->lru_prev = NULL; 1584 if ((client_data->lru_next = lru_first) != NULL) 1585 lru_first->lru_prev = client_data; 1586 else 1587 lru_last = client_data; 1588 lru_first = client_data; 1589 1590 num_gss_contexts++; 1591 } 1592 1593 /* 1594 * Fetch a client, given the client context handle. Move it to the 1595 * top of the LRU list since this is the most recently used context. 1596 */ 1597 static svc_rpc_gss_data * 1598 get_client(ctx_handle) 1599 gss_buffer_t ctx_handle; 1600 { 1601 uint_t key = *(uint_t *)ctx_handle->value; 1602 svc_rpc_gss_data *cl; 1603 1604 mutex_enter(&ctx_mutex); 1605 if ((cl = find_client(key)) != NULL) { 1606 mutex_enter(&cl->clm); 1607 if (cl->stale) { 1608 if (cl->ref_cnt == 0) { 1609 mutex_exit(&cl->clm); 1610 destroy_client(cl); 1611 } else { 1612 mutex_exit(&cl->clm); 1613 } 1614 mutex_exit(&ctx_mutex); 1615 return (NULL); 1616 } 1617 cl->ref_cnt++; 1618 cl->last_ref_time = gethrestime_sec(); 1619 mutex_exit(&cl->clm); 1620 if (cl != lru_first) { 1621 cl->lru_prev->lru_next = cl->lru_next; 1622 if (cl->lru_next != NULL) 1623 cl->lru_next->lru_prev = cl->lru_prev; 1624 else 1625 lru_last = cl->lru_prev; 1626 cl->lru_prev = NULL; 1627 cl->lru_next = lru_first; 1628 lru_first->lru_prev = cl; 1629 lru_first = cl; 1630 } 1631 } 1632 mutex_exit(&ctx_mutex); 1633 return (cl); 1634 } 1635 1636 /* 1637 * Given the client context handle, find the context corresponding to it. 1638 * Don't change its LRU state since it may not be used. 1639 */ 1640 static svc_rpc_gss_data * 1641 find_client(key) 1642 uint_t key; 1643 { 1644 int index = HASH(key); 1645 svc_rpc_gss_data *cl = NULL; 1646 1647 ASSERT(mutex_owned(&ctx_mutex)); 1648 1649 for (cl = clients[index]; cl != NULL; cl = cl->next) { 1650 if (cl->key == key) 1651 break; 1652 } 1653 return (cl); 1654 } 1655 1656 /* 1657 * Destroy a client context. 1658 */ 1659 static void 1660 destroy_client(client_data) 1661 svc_rpc_gss_data *client_data; 1662 { 1663 OM_uint32 minor; 1664 int index = HASH(client_data->key); 1665 1666 ASSERT(mutex_owned(&ctx_mutex)); 1667 1668 /* 1669 * remove from hash list 1670 */ 1671 if (client_data->prev == NULL) 1672 clients[index] = client_data->next; 1673 else 1674 client_data->prev->next = client_data->next; 1675 if (client_data->next != NULL) 1676 client_data->next->prev = client_data->prev; 1677 1678 /* 1679 * remove from LRU list 1680 */ 1681 if (client_data->lru_prev == NULL) 1682 lru_first = client_data->lru_next; 1683 else 1684 client_data->lru_prev->lru_next = client_data->lru_next; 1685 if (client_data->lru_next != NULL) 1686 client_data->lru_next->lru_prev = client_data->lru_prev; 1687 else 1688 lru_last = client_data->lru_prev; 1689 1690 /* 1691 * If there is a GSS context, clean up GSS state. 1692 */ 1693 if (client_data->context != GSS_C_NO_CONTEXT) { 1694 (void) kgss_delete_sec_context(&minor, &client_data->context, 1695 NULL); 1696 1697 common_client_data_free(client_data); 1698 1699 if (client_data->deleg != GSS_C_NO_CREDENTIAL) { 1700 (void) kgss_release_cred(&minor, &client_data->deleg, 1701 crgetuid(CRED())); 1702 } 1703 } 1704 1705 if (client_data->u_cred.gidlist != NULL) { 1706 kmem_free((char *)client_data->u_cred.gidlist, 1707 client_data->u_cred.gidlen * sizeof (gid_t)); 1708 client_data->u_cred.gidlist = NULL; 1709 } 1710 if (client_data->retrans_data != NULL) 1711 retrans_del(client_data); 1712 1713 kmem_cache_free(svc_data_handle, client_data); 1714 num_gss_contexts--; 1715 } 1716 1717 /* 1718 * Check for expired and stale client contexts. 1719 */ 1720 static void 1721 sweep_clients(bool_t from_reclaim) 1722 { 1723 svc_rpc_gss_data *cl, *next; 1724 time_t last_reference_needed; 1725 time_t now = gethrestime_sec(); 1726 1727 ASSERT(mutex_owned(&ctx_mutex)); 1728 1729 last_reference_needed = now - (from_reclaim ? 1730 svc_rpc_gss_active_delta : svc_rpc_gss_inactive_delta); 1731 1732 cl = lru_last; 1733 while (cl) { 1734 /* 1735 * We assume here that any manipulation of the LRU pointers 1736 * and hash bucket pointers are only done when holding the 1737 * ctx_mutex. 1738 */ 1739 next = cl->lru_prev; 1740 1741 mutex_enter(&cl->clm); 1742 1743 if ((cl->expiration != GSS_C_INDEFINITE && 1744 cl->expiration <= now) || cl->stale || 1745 cl->last_ref_time <= last_reference_needed) { 1746 1747 if ((cl->expiration != GSS_C_INDEFINITE && 1748 cl->expiration <= now) || cl->stale || 1749 (cl->last_ref_time <= last_reference_needed && 1750 cl->ref_cnt == 0)) { 1751 1752 cl->stale = TRUE; 1753 1754 if (cl->ref_cnt == 0) { 1755 mutex_exit(&cl->clm); 1756 if (from_reclaim) 1757 svc_rpc_gss_cache_stats. 1758 no_returned_by_reclaim++; 1759 destroy_client(cl); 1760 } else 1761 mutex_exit(&cl->clm); 1762 } else 1763 mutex_exit(&cl->clm); 1764 } else 1765 mutex_exit(&cl->clm); 1766 1767 cl = next; 1768 } 1769 1770 last_swept = gethrestime_sec(); 1771 } 1772 1773 /* 1774 * Encrypt the serialized arguments from xdr_func applied to xdr_ptr 1775 * and write the result to xdrs. 1776 */ 1777 static bool_t 1778 svc_rpc_gss_wrap(auth, out_xdrs, xdr_func, xdr_ptr) 1779 SVCAUTH *auth; 1780 XDR *out_xdrs; 1781 bool_t (*xdr_func)(); 1782 caddr_t xdr_ptr; 1783 { 1784 svc_rpc_gss_parms_t *gss_parms = SVCAUTH_GSSPARMS(auth); 1785 bool_t ret; 1786 1787 /* 1788 * If context is not established, or if neither integrity nor 1789 * privacy service is used, don't wrap - just XDR encode. 1790 * Otherwise, wrap data using service and QOP parameters. 1791 */ 1792 if (!gss_parms->established || 1793 gss_parms->service == rpc_gss_svc_none) 1794 return ((*xdr_func)(out_xdrs, xdr_ptr)); 1795 1796 ret = __rpc_gss_wrap_data(gss_parms->service, 1797 (OM_uint32)gss_parms->qop_rcvd, 1798 (gss_ctx_id_t)gss_parms->context, 1799 gss_parms->seq_num, 1800 out_xdrs, xdr_func, xdr_ptr); 1801 return (ret); 1802 } 1803 1804 /* 1805 * Decrypt the serialized arguments and XDR decode them. 1806 */ 1807 static bool_t 1808 svc_rpc_gss_unwrap(auth, in_xdrs, xdr_func, xdr_ptr) 1809 SVCAUTH *auth; 1810 XDR *in_xdrs; 1811 bool_t (*xdr_func)(); 1812 caddr_t xdr_ptr; 1813 { 1814 svc_rpc_gss_parms_t *gss_parms = SVCAUTH_GSSPARMS(auth); 1815 1816 /* 1817 * If context is not established, or if neither integrity nor 1818 * privacy service is used, don't unwrap - just XDR decode. 1819 * Otherwise, unwrap data. 1820 */ 1821 if (!gss_parms->established || 1822 gss_parms->service == rpc_gss_svc_none) 1823 return ((*xdr_func)(in_xdrs, xdr_ptr)); 1824 1825 return (__rpc_gss_unwrap_data(gss_parms->service, 1826 (gss_ctx_id_t)gss_parms->context, 1827 gss_parms->seq_num, 1828 gss_parms->qop_rcvd, 1829 in_xdrs, xdr_func, xdr_ptr)); 1830 } 1831 1832 1833 /* ARGSUSED */ 1834 int 1835 rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len) 1836 { 1837 return (0); 1838 } 1839 1840 /* 1841 * Add retransmit entry to the context cache entry for a new xid. 1842 * If there is already an entry, delete it before adding the new one. 1843 */ 1844 static void retrans_add(client, xid, result) 1845 svc_rpc_gss_data *client; 1846 uint32_t xid; 1847 rpc_gss_init_res *result; 1848 { 1849 retrans_entry *rdata; 1850 1851 if (client->retrans_data && client->retrans_data->xid == xid) 1852 return; 1853 1854 rdata = kmem_zalloc(sizeof (*rdata), KM_SLEEP); 1855 1856 if (rdata == NULL) 1857 return; 1858 1859 rdata->xid = xid; 1860 rdata->result = *result; 1861 1862 if (result->token.length != 0) { 1863 GSS_DUP_BUFFER(rdata->result.token, result->token); 1864 } 1865 1866 if (client->retrans_data) 1867 retrans_del(client); 1868 1869 client->retrans_data = rdata; 1870 } 1871 1872 /* 1873 * Delete the retransmit data from the context cache entry. 1874 */ 1875 static void retrans_del(client) 1876 svc_rpc_gss_data *client; 1877 { 1878 retrans_entry *rdata; 1879 OM_uint32 minor_stat; 1880 1881 if (client->retrans_data == NULL) 1882 return; 1883 1884 rdata = client->retrans_data; 1885 if (rdata->result.token.length != 0) { 1886 (void) gss_release_buffer(&minor_stat, &rdata->result.token); 1887 } 1888 1889 kmem_free((caddr_t)rdata, sizeof (*rdata)); 1890 client->retrans_data = NULL; 1891 } 1892 1893 /* 1894 * This function frees the following fields of svc_rpc_gss_data: 1895 * client_name, raw_cred.client_principal, raw_cred.mechanism. 1896 */ 1897 static void 1898 common_client_data_free(svc_rpc_gss_data *client_data) 1899 { 1900 if (client_data->client_name.length > 0) { 1901 (void) gss_release_buffer(NULL, &client_data->client_name); 1902 } 1903 1904 if (client_data->raw_cred.client_principal) { 1905 kmem_free((caddr_t)client_data->raw_cred.client_principal, 1906 client_data->raw_cred.client_principal->len + 1907 sizeof (int)); 1908 client_data->raw_cred.client_principal = NULL; 1909 } 1910 1911 /* 1912 * In the user GSS-API library, mechanism (mech_type returned 1913 * by gss_accept_sec_context) is static storage, however 1914 * since all the work is done for gss_accept_sec_context under 1915 * gssd, what is returned in the kernel, is a copy from the oid 1916 * obtained under from gssd, so need to free it when destroying 1917 * the client data. 1918 */ 1919 1920 if (client_data->raw_cred.mechanism) { 1921 kgss_free_oid(client_data->raw_cred.mechanism); 1922 client_data->raw_cred.mechanism = NULL; 1923 } 1924 }