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