1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME 80** 81** comauth.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Generic interface to authentication services 90** 91** 92*/ 93 94#include <commonp.h> /* Common declarations for all RPC runtime */ 95#include <com.h> /* Common communications services */ 96#include <comp.h> /* Private communications services */ 97#include <comauth.h> /* Common Authentication services */ 98 99#if HAVE_SYS_KAUTH_H 100#include <sys/kauth.h> 101#endif 102 103#if HAVE_SYS_SYSCALL_H 104#include <sys/syscall.h> 105#endif 106 107/* 108 * Internal variables to maintain the auth info cache. 109 */ 110INTERNAL rpc_list_t auth_info_cache; 111INTERNAL rpc_mutex_t auth_info_cache_mutex; 112 113/* 114 * R P C _ _ A U T H _ I N F O _ C A C H E _ L K U P 115 */ 116INTERNAL rpc_auth_info_t *rpc__auth_info_cache_lkup ( 117 unsigned_char_p_t /*server_princ_name*/, 118 rpc_authn_level_t /*authn_level*/, 119 rpc_auth_identity_handle_t /*auth_identity*/, 120 rpc_authz_protocol_id_t /*authz_protocol*/, 121 rpc_authn_protocol_id_t /* authn_protocol*/ 122 ); 123 124/* 125 * R P C _ _ A U T H _ I N F O _ C A C H E _ A D D 126 */ 127 128INTERNAL void rpc__auth_info_cache_add ( 129 rpc_auth_info_p_t /*auth_info*/ 130 ); 131 132/* 133 * R P C _ _ A U T H _ I N F O _ C A C H E _ R E M O V E 134 */ 135INTERNAL void rpc__auth_info_cache_remove ( 136 rpc_auth_info_p_t /*auth_info*/ 137 ); 138 139 140/* 141 * Macro to assign through a pointer iff the pointer is non-NULL. Note 142 * that we depend on the fact that "val" is not evaluated if "ptr" is 143 * NULL (i.e., this must be a macro, not a function). 144 */ 145#define ASSIGN(ptr, val) \ 146( \ 147 (ptr) != NULL ? *(ptr) = (val) : 0 \ 148) 149 150#define ASSIGN_COPY(buffer, length, val) do { \ 151 char* _val = (char*) (val); \ 152 size_t _vallength = _val ? strlen(_val) : 0; \ 153 if ((buffer) == NULL || (length) < _vallength) { \ 154 *st = rpc_s_ss_bad_buffer; \ 155 return; \ 156 } else { \ 157 if (_val != NULL) \ 158 memcpy((buffer), _val, _vallength + 1); \ 159 else \ 160 (buffer)[0] = '\0'; \ 161 (length) = (unsigned32) _vallength; \ 162 } \ 163 } while (0) 164 165 166/* 167**++ 168** 169** ROUTINE NAME: rpc__auth_inq_supported 170** 171** SCOPE: PRIVATE - declared in com.h 172** 173** DESCRIPTION: 174** 175** Return a boolean indicating whether the authentication protocol 176** is supported by the runtime. 177** 178** INPUTS: 179** 180** authn_prot_id Authentication protocol ID 181** 182** INPUTS/OUTPUTS: none 183** 184** OUTPUTS: none 185** 186** IMPLICIT INPUTS: none 187** 188** IMPLICIT OUTPUTS: none 189** 190** FUNCTION VALUE: boolean32 191** 192** true if supported 193** 194** SIDE EFFECTS: none 195** 196**-- 197**/ 198 199PRIVATE boolean32 rpc__auth_inq_supported 200( 201 rpc_authn_protocol_id_t authn_prot_id 202) 203{ 204 return (RPC_AUTHN_INQ_SUPPORTED(authn_prot_id)); 205} 206 207 208/* 209**++ 210** 211** ROUTINE NAME: rpc__auth_cvt_id_api_to_wire 212** 213** SCOPE: PRIVATE - declared in com.h 214** 215** DESCRIPTION: 216** 217** Return the wire value of an authentication protocol ID given its 218** API counterpart. 219** 220** INPUTS: 221** 222** api_authn_prot_id API Authentication protocol ID 223** 224** INPUTS/OUTPUTS: 225** 226** OUTPUTS: none 227** 228** status A value indicating the return status of the routine 229** 230** IMPLICIT INPUTS: none 231** 232** IMPLICIT OUTPUTS: none 233** 234** FUNCTION VALUE: unsigned32 235** 236** The wire Authentication protocol ID. 237** 238** SIDE EFFECTS: none 239** 240**-- 241**/ 242 243PRIVATE unsigned32 rpc__auth_cvt_id_api_to_wire 244( 245 rpc_authn_protocol_id_t api_authn_prot_id, 246 unsigned32 *status 247) 248{ 249 if (! RPC_AUTHN_IN_RANGE(api_authn_prot_id) || 250 ! RPC_AUTHN_INQ_SUPPORTED(api_authn_prot_id)) 251 { 252 *status = rpc_s_unknown_auth_protocol; 253 return (0xeffaced); 254 } 255 256 *status = rpc_s_ok; 257 return (rpc_g_authn_protocol_id[api_authn_prot_id].dce_rpc_authn_protocol_id); 258} 259 260 261/* 262**++ 263** 264** ROUTINE NAME: rpc__auth_cvt_id_wire_to_api 265** 266** SCOPE: PRIVATE - declared in com.h 267** 268** DESCRIPTION: 269** 270** Return the API value of an authentication protocol ID given its 271** wire counterpart. 272** 273** INPUTS: 274** 275** wire_authn_prot_id Wire Authentication protocol ID 276** 277** INPUTS/OUTPUTS: 278** 279** OUTPUTS: 280** 281** status A value indicating the return status of the routine 282** 283** IMPLICIT INPUTS: none 284** 285** IMPLICIT OUTPUTS: none 286** 287** FUNCTION VALUE: unsigned32 288** 289** The API Authentication protocol ID. 290** 291** SIDE EFFECTS: none 292** 293**-- 294**/ 295 296PRIVATE rpc_authn_protocol_id_t rpc__auth_cvt_id_wire_to_api 297( 298 unsigned32 wire_authn_prot_id, 299 unsigned32 *status 300) 301{ 302 rpc_authn_protocol_id_t authn_protocol; 303 304 for (authn_protocol = 0; 305 authn_protocol < RPC_C_AUTHN_PROTOCOL_ID_MAX; 306 authn_protocol++) 307 { 308 rpc_authn_protocol_id_elt_p_t aprot = &rpc_g_authn_protocol_id[authn_protocol]; 309 310 if (aprot->epv != NULL && 311 aprot->dce_rpc_authn_protocol_id == wire_authn_prot_id) 312 { 313 break; 314 } 315 } 316 317 if (authn_protocol >= RPC_C_AUTHN_PROTOCOL_ID_MAX) 318 { 319 *status = rpc_s_unknown_auth_protocol; 320 return ((rpc_authn_protocol_id_t)0xdeaddeadUL); 321 } 322 323 *status = rpc_s_ok; 324 return (authn_protocol); 325} 326 327 328/* 329**++ 330** 331** ROUTINE NAME: rpc__auth_inq_rpc_prot_epv 332** 333** SCOPE: PRIVATE - declared in com.h 334** 335** DESCRIPTION: 336** 337** Return the RPC protocol specific entry point vector for a given 338** Authentication protocol. 339** 340** INPUTS: 341** 342** authn_prot_id Authentication protocol ID 343** rpc_prot_id RPC protocol ID 344** 345** INPUTS/OUTPUTS: 346** 347** OUTPUTS: none 348** 349** IMPLICIT INPUTS: none 350** 351** IMPLICIT OUTPUTS: none 352** 353** FUNCTION VALUE: rpc_prot_epv_tbl 354** 355** The address of the RPC protocol specific, authentication 356** protocol specific entry point vector. 357** 358** SIDE EFFECTS: none 359** 360**-- 361**/ 362 363PRIVATE rpc_auth_rpc_prot_epv_t *rpc__auth_rpc_prot_epv 364( 365 rpc_authn_protocol_id_t authn_prot_id, 366 rpc_protocol_id_t rpc_prot_id 367) 368{ 369 return (RPC_AUTHN_INQ_RPC_PROT_EPV(authn_prot_id,rpc_prot_id)); 370} 371 372 373/* 374**++ 375** 376** ROUTINE NAME: rpc__auth_info_reference 377** 378** SCOPE: PRIVATE - declared in com.h 379** 380** DESCRIPTION: 381** 382** Establish a reference to authentication info. 383** 384** INPUTS: 385** 386** auth_info Authentication information 387** 388** INPUTS/OUTPUTS: 389** 390** OUTPUTS: none 391** 392** IMPLICIT INPUTS: none 393** 394** IMPLICIT OUTPUTS: none 395** 396** FUNCTION VALUE: none 397** 398** SIDE EFFECTS: none 399** 400**-- 401**/ 402 403PRIVATE void rpc__auth_info_reference 404( 405 rpc_auth_info_p_t auth_info 406) 407{ 408#ifdef DEBUG 409 const char *info_type = auth_info->is_server?"server":"client"; 410#endif 411 412 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc__auth_info_reference) %p: bumping %s refcount (was %d, now %d)\n", 413 auth_info, 414 info_type, auth_info->refcount, 415 auth_info->refcount + 1)); 416 417/* assert (auth_info->refcount >= 0); XXX unsigned values always >= 0*/ 418 auth_info->refcount++; 419} 420 421 422/* 423**++ 424** 425** ROUTINE NAME: rpc__auth_info_binding_release 426** 427** SCOPE: PRIVATE - declared in comauth.h 428** 429** DESCRIPTION: 430** 431** Release reference to authentication info (stored in passed binding 432** handle) previously returned by set_server or inq_caller. If we don't 433** have any auth info, do nothing. 434** 435** INPUTS: 436** 437** binding_rep RPC binding handle 438** 439** INPUTS/OUTPUTS: 440** 441** OUTPUTS: none 442** 443** IMPLICIT INPUTS: none 444** 445** IMPLICIT OUTPUTS: none 446** 447** FUNCTION VALUE: none 448** 449** SIDE EFFECTS: none 450** 451**-- 452**/ 453 454PRIVATE void rpc__auth_info_binding_release 455( 456 rpc_binding_rep_p_t binding_rep 457) 458{ 459 rpc__auth_info_release (&binding_rep->auth_info); 460} 461 462 463 464/* 465**++ 466** 467** ROUTINE NAME: rpc__auth_info_release 468** 469** SCOPE: PRIVATE - declared in com.h 470** 471** DESCRIPTION: 472** 473** Release reference to authentication info previously returned by 474** set_server or inq_caller. 475** 476** INPUTS: 477** 478** info Authentication info 479** 480** INPUTS/OUTPUTS: 481** 482** OUTPUTS: none 483** 484** IMPLICIT INPUTS: none 485** 486** IMPLICIT OUTPUTS: none 487** 488** FUNCTION VALUE: none 489** 490** SIDE EFFECTS: none 491** 492**-- 493**/ 494 495PRIVATE void rpc__auth_info_release 496( 497 rpc_auth_info_p_t *info 498) 499{ 500 rpc_auth_info_p_t auth_info = *info; 501 const char *info_type; 502 503 if (auth_info == NULL) 504 { 505 return; 506 } 507 508 info_type = auth_info->is_server?"server":"client"; 509 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc__auth_info_release) %p: dropping %s refcount (was %d, now %d)\n", 510 auth_info, 511 info_type, 512 auth_info->refcount, 513 auth_info->refcount-1 )); 514 assert(auth_info->refcount >= 1); 515 516 /* 517 * Remove the reference. 518 */ 519 auth_info->refcount--; 520 521 /* 522 * Some special logic is required for cache maintenance on the 523 * client side. 524 */ 525 if (!(auth_info->is_server)) 526 { 527 if (auth_info->refcount == 1) 528 { 529 /* 530 * The auth info can be removed from the cache if there is only 531 * one reference left to it. That single reference is the cache's 532 * reference. 533 */ 534 rpc__auth_info_cache_remove (auth_info); 535 } 536 } 537 538 /* 539 * Free the auth info when nobody holds a reference to it. 540 */ 541 if (auth_info->refcount == 0) 542 { 543 (*rpc_g_authn_protocol_id[auth_info->authn_protocol].epv->free_info) 544 (&auth_info); 545 } 546 547 /* 548 * NULL out the caller's reference to the auth info. 549 */ 550 *info = NULL; 551} 552 553 554/* 555**++ 556** 557** ROUTINE NAME: rpc__key_info_reference 558** 559** SCOPE: PRIVATE - declared in com.h 560** 561** DESCRIPTION: 562** 563** Establish a reference to keyentication info. 564** 565** INPUTS: 566** 567** key_info Authentication information 568** 569** INPUTS/OUTPUTS: 570** 571** OUTPUTS: none 572** 573** IMPLICIT INPUTS: none 574** 575** IMPLICIT OUTPUTS: none 576** 577** FUNCTION VALUE: none 578** 579** SIDE EFFECTS: none 580** 581**-- 582**/ 583 584PRIVATE void rpc__key_info_reference 585( 586 rpc_key_info_p_t key_info 587) 588{ 589 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc__key_info_reference) %p: bumping %s refcnt (was %d, now %d)\n", 590 key_info, 591 (key_info->is_server?"server":"client"), 592 key_info->refcnt, 593 key_info->refcnt + 1)); 594 595 assert (key_info->refcnt >= 1); 596 key_info->refcnt++; 597} 598 599/* 600**++ 601** 602** ROUTINE NAME: rpc__key_info_release 603** 604** SCOPE: PRIVATE - declared in com.h 605** 606** DESCRIPTION: 607** 608** Release reference to keyentication info previously returned by 609** set_server or inq_caller. 610** 611** INPUTS: 612** 613** info Authentication info 614** 615** INPUTS/OUTPUTS: 616** 617** OUTPUTS: none 618** 619** IMPLICIT INPUTS: none 620** 621** IMPLICIT OUTPUTS: none 622** 623** FUNCTION VALUE: none 624** 625** SIDE EFFECTS: none 626** 627**-- 628**/ 629 630PRIVATE void rpc__key_info_release 631( 632 rpc_key_info_p_t *info 633) 634{ 635 rpc_key_info_p_t key_info = *info; 636 637 if (key_info == NULL) 638 { 639 return; 640 } 641 *info = NULL; 642 643 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, 644 ("(rpc__key_info_release) %p: dropping %s refcnt (was %d, now %d)\n", 645 key_info, 646 key_info->is_server?"server":"client", 647 key_info->refcnt, 648 key_info->refcnt-1 )); 649 assert(key_info->refcnt >= 1); 650 651 /* 652 * Remove the reference. 653 */ 654 key_info->refcnt--; 655 656 /* 657 * Free the auth info when nobody holds a reference to it. 658 */ 659 if (key_info->refcnt == 0) 660 { 661 (*rpc_g_authn_protocol_id[key_info->auth_info->authn_protocol].epv->free_key) 662 (&key_info); 663 } 664} 665 666/* 667**++ 668** 669** ROUTINE NAME: rpc__auth_inq_my_princ_name 670** 671** SCOPE: PRIVATE - declared in comauth.h 672** 673** DESCRIPTION: 674** 675** 676** 677** 678** 679** INPUTS: 680** 681** h RPC binding handle 682** 683** INPUTS/OUTPUTS: 684** 685** OUTPUTS: 686** 687** status A value indicating the return status of the routine 688** 689** IMPLICIT INPUTS: none 690** 691** IMPLICIT OUTPUTS: none 692** 693** FUNCTION VALUE: none 694** 695** SIDE EFFECTS: none 696** 697**-- 698**/ 699 700PRIVATE void rpc__auth_inq_my_princ_name 701( 702 unsigned32 dce_rpc_authn_protocol, 703 unsigned32 princ_name_size, 704 unsigned_char_p_t princ_name, 705 unsigned32 *st 706) 707{ 708 rpc_authn_protocol_id_t authn_protocol; 709 710 authn_protocol = rpc__auth_cvt_id_wire_to_api(dce_rpc_authn_protocol, st); 711 if (*st != rpc_s_ok) 712 { 713 return; 714 } 715 716 (*rpc_g_authn_protocol_id[authn_protocol] 717 .epv->inq_my_princ_name) 718 (princ_name_size, princ_name, st); 719} 720 721/* 722**++ 723** 724** ROUTINE NAME: rpc_binding_set_auth_info 725** 726** SCOPE: PUBLIC - declared in rpcauth.idl 727** 728** DESCRIPTION: 729** 730** Set up client handle for authentication. 731** 732** INPUTS: 733** 734** h RPC binding handle 735** 736** server_princ_name 737** Name of server to authenticate to 738** 739** authn_level Authentication level 740** 741** authn_protocol Desired authentication protocol to use 742** 743** auth_identity Credentials to use on calls 744** 745** authz_protocol Authorization protocol to use 746** 747** INPUTS/OUTPUTS: 748** 749** OUTPUTS: 750** 751** status A value indicating the return status of the routine 752** rpc_s_invalid_binding 753** RPC Protocol ID in binding handle was invalid. 754** 755** IMPLICIT INPUTS: none 756** 757** IMPLICIT OUTPUTS: none 758** 759** FUNCTION VALUE: none 760** 761** SIDE EFFECTS: none 762** 763**-- 764**/ 765 766PUBLIC void rpc_binding_set_auth_info 767( 768 rpc_binding_handle_t binding_h, 769 unsigned_char_p_t server_princ_name, 770 unsigned32 authn_level, 771 unsigned32 authn_protocol, 772 rpc_auth_identity_handle_t auth_identity, 773 unsigned32 authz_protocol, 774 unsigned32 *st 775) 776{ 777 rpc_auth_identity_handle_t ref_auth_identity; 778 rpc_auth_info_p_t auth_info; 779 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 780 rpc_auth_epv_p_t auth_epv; 781 boolean need_to_free_server_name = false; 782 783 CODING_ERROR (st); 784 RPC_VERIFY_INIT (); 785 786 assert(binding_rep != NULL); 787 788 RPC_BINDING_VALIDATE_CLIENT(binding_rep, st); 789 if (*st != rpc_s_ok) 790 return; 791 792 /* 793 * If asking to set to authentication type "none", just free any auth info 794 * we have and return now. 795 */ 796 797 if (authn_protocol == rpc_c_authn_none) 798 { 799 rpc__auth_info_binding_release(binding_rep); 800 return; 801 } 802 803 RPC_AUTHN_CHECK_SUPPORTED_RPC_PROT(authn_protocol, binding_rep->protocol_id, st); 804 805 /* 806 * If asking for default authn level, get the actual level now (i.e., 807 * spare each auth service the effort of coding this logic). 808 */ 809 810 if (authn_level == rpc_c_authn_level_default) 811 { 812 rpc_mgmt_inq_dflt_authn_level (authn_protocol, &authn_level, st); 813 if (*st != rpc_s_ok) 814 return; 815 } 816 817 auth_epv = rpc_g_authn_protocol_id[authn_protocol].epv; 818 /* 819 * Resolve the auth_identity into a real reference to the identity 820 * prior to the cache lookup. 821 */ 822 823 *st = (*auth_epv->resolve_id) 824 (auth_identity, &ref_auth_identity); 825 826 if (*st != rpc_s_ok) 827 return; 828 829 /* 830 * If no server principal name was specified, go ask for it. 831 * 832 * Not all authentication protocols require a server principal 833 * name to do authentication. Hence, only inquire the server 834 * principal name if we know the authentication protocol is 835 * secret key based. 836 * 837 * We did not move the inq_princ_name function to an 838 * authentication service specific module because we need 839 * a server principal name for the auth_info cache lookup. 840 * 841 * Note that we want to be avoid bypassing the auth_info 842 * cache because certain protocol services cache credentials. 843 * Allocating a new auth_info structure on every call can 844 * cause these credentials to accumulate until the heap is 845 * exhausted. 846 */ 847 if (server_princ_name == NULL) { 848 switch (authn_protocol) { 849 case rpc_c_authn_dce_secret: 850 case rpc_c_authn_winnt: 851 case rpc_c_authn_gss_negotiate: 852 case rpc_c_authn_gss_mskrb: 853 rpc_mgmt_inq_server_princ_name 854 (binding_h, 855 authn_protocol, 856 &server_princ_name, 857 st); 858 859 if (*st != rpc_s_ok) 860 return; 861 862 need_to_free_server_name = true; 863 break; 864 865 default: 866 break; 867 } 868 } 869 870 /* 871 * Consult the cache before creating a new auth info structure. 872 * We may be able to add a reference to an already existing one. 873 */ 874 if ((auth_info = rpc__auth_info_cache_lkup (server_princ_name, 875 authn_level, 876 ref_auth_identity, 877 authz_protocol, 878 authn_protocol)) == NULL) 879 { 880 881 /* 882 * A new auth info will have to be created. 883 * Call authentication service to do generic (not specific 884 * to a single RPC protocol) "set server" function. 885 */ 886 (*auth_epv->binding_set_auth_info) 887 (server_princ_name, authn_level, auth_identity, 888 authz_protocol, binding_h, &auth_info, st); 889 890 if (*st != rpc_s_ok) 891 { 892 if (need_to_free_server_name) 893 RPC_MEM_FREE (server_princ_name, RPC_C_MEM_STRING); 894 return; 895 } 896 897 /* 898 * Add this new auth info to a cache of auth infos. This cache 899 * will be consulted on a subsequent call to this routine. 900 */ 901 rpc__auth_info_cache_add (auth_info); 902 903 } 904 905 /* 906 * Release our reference to the identity. If a new auth_info was 907 * created, then it added a reference also. 908 */ 909 910 (*auth_epv->release_id) (&ref_auth_identity); 911 912 /* 913 * If we inquired the server principal name, free it now. 914 */ 915 if (need_to_free_server_name) 916 RPC_MEM_FREE (server_princ_name, RPC_C_MEM_STRING); 917 918 /* 919 * If we have any auth info for this binding already, lose it. 920 */ 921 922 if (binding_rep->auth_info != NULL) 923 { 924 rpc__auth_info_binding_release(binding_rep); 925 } 926 927 binding_rep->auth_info = auth_info; 928 929 /* 930 * Notify the protocol service that the binding has changed. 931 */ 932 933 (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv 934 ->binding_changed) (binding_rep, st); 935} 936 937/* 938**++ 939** 940** ROUTINE NAME: rpc_binding_inq_auth_info 941** 942** SCOPE: PUBLIC - declared in rpcauth.idl 943** 944** DESCRIPTION: 945** 946** Return authentication and authorization information from a binding 947** handle. 948** 949** INPUTS: 950** 951** h RPC binding handle 952** 953** INPUTS/OUTPUTS: 954** 955** OUTPUTS: 956** 957** server_princ_name 958** Name of server to authenticate to 959** 960** authn_level Authentication level 961** 962** authn_protocol Desired authentication protocol to use 963** 964** auth_identity Credentials to use on calls 965** 966** authz_protocol Authorization protocol to use 967** 968** status A value indicating the return status of the routine 969** rpc_s_invalid_binding 970** RPC Protocol ID in binding handle was invalid. 971** 972** IMPLICIT INPUTS: none 973** 974** IMPLICIT OUTPUTS: none 975** 976** FUNCTION VALUE: none 977** 978** SIDE EFFECTS: none 979** 980**-- 981**/ 982 983PUBLIC void rpc_binding_inq_auth_info 984( 985 rpc_binding_handle_t binding_h, 986 unsigned_char_p_t *server_princ_name, 987 unsigned32 *authn_level, 988 unsigned32 *authn_protocol, 989 rpc_auth_identity_handle_t *auth_identity, 990 unsigned32 *authz_protocol, 991 unsigned32 *st 992 ) 993{ 994 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 995 rpc_auth_info_p_t auth_info; 996 997 assert(binding_rep != NULL); 998 999 CODING_ERROR (st); 1000 RPC_VERIFY_INIT (); 1001 1002 RPC_BINDING_VALIDATE_CLIENT(binding_rep, st); 1003 if (*st != rpc_s_ok) 1004 return; 1005 1006 auth_info = ((rpc_binding_rep_p_t)binding_h)->auth_info; 1007 1008 if (auth_info == NULL) 1009 { 1010 *st = rpc_s_binding_has_no_auth; 1011 return; 1012 } 1013 1014 assert(! auth_info->is_server); 1015 1016 if (auth_info->server_princ_name == NULL) 1017 { 1018 (void) ASSIGN(server_princ_name, NULL); 1019 } else 1020 { 1021 (void) ASSIGN(server_princ_name, rpc_stralloc(auth_info->server_princ_name)); 1022 } 1023 (void) ASSIGN(authn_level, auth_info->authn_level); 1024 (void) ASSIGN(authn_protocol, auth_info->authn_protocol); 1025 (void) ASSIGN(auth_identity, auth_info->u.auth_identity); 1026 (void) ASSIGN(authz_protocol, auth_info->authz_protocol); 1027 1028 *st = rpc_s_ok; 1029} 1030 1031 1032/* 1033**++ 1034** 1035** ROUTINE NAME: rpc_server_register_auth_info 1036** 1037** SCOPE: PUBLIC - declared in rpcauth.idl 1038** 1039** DESCRIPTION: 1040** 1041** Register authentication information with the RPC runtime. 1042** 1043** INPUTS: 1044** 1045** authn_protocol Desired authentication protocol to use 1046** 1047** server_princ_name 1048** Name server should use 1049** 1050** get_key_func Function ptr to call to get keys 1051** 1052** arg Opaque params for key func. 1053** 1054** INPUTS/OUTPUTS: none 1055** 1056** OUTPUTS: 1057** 1058** status A value indicating the return status of the routine 1059** 1060** IMPLICIT INPUTS: none 1061** 1062** IMPLICIT OUTPUTS: none 1063** 1064** FUNCTION VALUE: none 1065** 1066** SIDE EFFECTS: none 1067** 1068**-- 1069**/ 1070 1071PUBLIC void rpc_server_register_auth_info 1072( 1073 unsigned_char_p_t server_princ_name, 1074 unsigned32 authn_protocol, 1075 rpc_auth_key_retrieval_fn_t get_key_func, 1076 ndr_void_p_t arg, 1077 unsigned32 *st 1078) 1079{ 1080 CODING_ERROR (st); 1081 RPC_VERIFY_INIT (); 1082 1083 if (authn_protocol == rpc_c_authn_none) 1084 { 1085 *st = rpc_s_ok; 1086 return; 1087 } 1088 1089 if (authn_protocol == (typeof(authn_protocol))(rpc_c_authn_default) && get_key_func != NULL) 1090 { 1091 *st = rpc_s_key_func_not_allowed; 1092 return; 1093 } 1094 1095 RPC_AUTHN_CHECK_SUPPORTED (authn_protocol, st); 1096 1097 (*rpc_g_authn_protocol_id[authn_protocol] 1098 .epv->server_register_auth_info) 1099 (server_princ_name, get_key_func, (dce_pointer_t) arg, st); 1100} 1101 1102/* 1103**++ 1104** 1105** ROUTINE NAME: rpc_binding_inq_auth_client 1106** 1107** SCOPE: PUBLIC - declared in rpcauth.idl 1108** 1109** DESCRIPTION: 1110** 1111** Return authentication and authorization information from a binding 1112** handle to an authenticated client. 1113** be freed. 1114** 1115** INPUTS: 1116** 1117** binding_h Server-side binding handle to remote caller whose 1118** identity is being requested. 1119** 1120** INPUTS/OUTPUTS: none 1121** 1122** OUTPUTS: 1123** 1124** privs PAC for remote caller. 1125** 1126** server_princ_name 1127** Server name that caller authenticated to. 1128** 1129** authn_level Authentication level used by remote caller. 1130** 1131** authn_protocol Authentication protocol used by remote caller. 1132** 1133** authz_protocol Authorization protocol used by remote caller. 1134** 1135** status A value indicating the return status of the routine 1136** rpc_s_invalid_binding 1137** RPC Protocol ID in binding handle was invalid. 1138** 1139** IMPLICIT INPUTS: none 1140** 1141** IMPLICIT OUTPUTS: none 1142** 1143** FUNCTION VALUE: none 1144** 1145** SIDE EFFECTS: none 1146** 1147**-- 1148**/ 1149 1150PUBLIC void rpc_binding_inq_auth_client 1151( 1152 rpc_binding_handle_t binding_h, 1153 rpc_authz_handle_t *privs, 1154 unsigned_char_p_t *server_princ_name, 1155 unsigned32 *authn_level, 1156 unsigned32 *authn_protocol, 1157 unsigned32 *authz_protocol, 1158 unsigned32 *st 1159) 1160{ 1161 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1162 rpc_auth_info_p_t auth_info; 1163 1164 assert(binding_rep != NULL); 1165 1166 CODING_ERROR (st); 1167 RPC_VERIFY_INIT (); 1168 1169 RPC_BINDING_VALIDATE_SERVER(binding_rep, st); 1170 if (*st != rpc_s_ok) 1171 return; 1172 1173 auth_info = ((rpc_binding_rep_p_t)binding_h)->auth_info; 1174 1175 if (auth_info == NULL) 1176 { 1177 *st = rpc_s_binding_has_no_auth; 1178 return; 1179 } 1180 1181 assert(auth_info->is_server); 1182 1183 (void) ASSIGN(privs, auth_info->u.s.privs); 1184 1185 if (server_princ_name != NULL) 1186 { 1187 if (auth_info->server_princ_name == NULL) 1188 { 1189 (void) ASSIGN(server_princ_name, NULL); 1190 } 1191 else 1192 { 1193 (void) ASSIGN(server_princ_name, rpc_stralloc(auth_info->server_princ_name)); 1194 } 1195 } 1196 1197 (void) ASSIGN(authn_level, auth_info->authn_level); 1198 (void) ASSIGN(authn_protocol, auth_info->authn_protocol); 1199 (void) ASSIGN(authz_protocol, auth_info->authz_protocol); 1200 1201 *st = rpc_s_ok; 1202} 1203 1204/* 1205**++ 1206** 1207** ROUTINE NAME: rpc_binding_inq_auth_caller 1208** 1209** SCOPE: PUBLIC - declared in rpcauth.idl 1210** 1211** DESCRIPTION: 1212** 1213** Return authentication and 1.1+ authorization information from a binding 1214** handle to an authenticated client. 1215** 1216** INPUTS: 1217** 1218** binding_h Server-side binding handle to remote caller whose 1219** identity is being requested. 1220** 1221** INPUTS/OUTPUTS: none 1222** 1223** OUTPUTS: 1224** 1225** creds Opaque handle on caller's credentials to 1226** be used in making sec_cred_ calls 1227** 1228** server_princ_name 1229** Server name that caller authenticated to. 1230** 1231** authn_level Authentication level used by remote caller. 1232** 1233** authn_protocol Authentication protocol used by remote caller. 1234** 1235** authz_protocol Authorization protocol used by remote caller. 1236** 1237** status A value indicating the return status of the routine 1238** rpc_s_invalid_binding 1239** RPC Protocol ID in binding handle was invalid. 1240** 1241** IMPLICIT INPUTS: none 1242** 1243** IMPLICIT OUTPUTS: none 1244** 1245** FUNCTION VALUE: none 1246** 1247** SIDE EFFECTS: none 1248** 1249**-- 1250**/ 1251 1252PUBLIC void rpc_binding_inq_auth_caller 1253( 1254 rpc_binding_handle_t binding_h, 1255 rpc_authz_cred_handle_t *creds, 1256 unsigned_char_p_t *server_princ_name, 1257 unsigned32 *authn_level, 1258 unsigned32 *authn_protocol, 1259 unsigned32 *authz_protocol, 1260 unsigned32 *st 1261) 1262{ 1263 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1264 rpc_auth_info_p_t auth_info; 1265 1266 assert(binding_rep != NULL); 1267 1268 CODING_ERROR (st); 1269 RPC_VERIFY_INIT (); 1270 1271 RPC_BINDING_VALIDATE_SERVER(binding_rep, st); 1272 if (*st != rpc_s_ok) 1273 return; 1274 1275 auth_info = ((rpc_binding_rep_p_t)binding_h)->auth_info; 1276 1277 if (auth_info == NULL) 1278 { 1279 *st = rpc_s_binding_has_no_auth; 1280 return; 1281 } 1282 1283 assert(auth_info->is_server); 1284 1285 if (auth_info->u.s.creds != NULL) { 1286 *creds = *auth_info->u.s.creds; 1287 } 1288 1289 if (server_princ_name != NULL) 1290 { 1291 if (auth_info->server_princ_name == NULL) 1292 { 1293 (void) ASSIGN(server_princ_name, NULL); 1294 } 1295 else 1296 { 1297 (void) ASSIGN(server_princ_name, rpc_stralloc(auth_info->server_princ_name)); 1298 } 1299 } 1300 1301 (void) ASSIGN(authn_level, auth_info->authn_level); 1302 (void) ASSIGN(authn_protocol, auth_info->authn_protocol); 1303 (void) ASSIGN(authz_protocol, auth_info->authz_protocol); 1304 1305 *st = rpc_s_ok; 1306} 1307 1308/* 1309**++ 1310** 1311** ROUTINE NAME: rpc_mgmt_inq_dflt_protect_level 1312** 1313** SCOPE: PUBLIC - declared in rpcauth.idl 1314** 1315** DESCRIPTION: 1316** 1317** Returns the default authentication level for an authentication service. 1318** 1319** INPUTS: 1320** 1321** authn_protocol Desired authentication protocol. 1322** 1323** INPUTS/OUTPUTS: none 1324** 1325** OUTPUTS: 1326** 1327** authn_level Authentication level used by remote caller. 1328** 1329** status A value indicating the return status of the routine 1330** 1331** IMPLICIT INPUTS: none 1332** 1333** IMPLICIT OUTPUTS: none 1334** 1335** FUNCTION VALUE: none 1336** 1337** SIDE EFFECTS: none 1338** 1339**-- 1340**/ 1341 1342PUBLIC void rpc_mgmt_inq_dflt_protect_level 1343( 1344 unsigned32 authn_protocol, 1345 unsigned32 *authn_level, 1346 unsigned32 *st 1347) 1348{ 1349 CODING_ERROR (st); 1350 RPC_VERIFY_INIT (); 1351 1352 if (authn_protocol == rpc_c_authn_none) 1353 { 1354 *authn_level = rpc_c_authn_level_none; 1355 *st = rpc_s_ok; 1356 return; 1357 } 1358 1359 RPC_AUTHN_CHECK_SUPPORTED (authn_protocol, st); 1360 1361 (*rpc_g_authn_protocol_id[authn_protocol] 1362 .epv->mgmt_inq_dflt_auth_level) 1363 (authn_level, st); 1364} 1365 1366/* 1367 * Retain entry point with old name for compatibility. 1368 */ 1369 1370PUBLIC void rpc_mgmt_inq_dflt_authn_level 1371( 1372 unsigned32 authn_protocol, 1373 unsigned32 *authn_level, 1374 unsigned32 *st 1375) 1376{ 1377 rpc_mgmt_inq_dflt_protect_level (authn_protocol, authn_level, st); 1378} 1379 1380 1381/* 1382**++ 1383** 1384** ROUTINE NAME: rpc__auth_info_cache_init 1385** 1386** SCOPE: PRIVATE - declared in comauth.h 1387** 1388** DESCRIPTION: 1389** 1390** Initialize the auth info cache including mutexes and list head. 1391** 1392** INPUTS: none 1393** 1394** INPUTS/OUTPUTS: none 1395** 1396** OUTPUTS: 1397** 1398** status A value indicating the return status of the routine 1399** 1400** IMPLICIT INPUTS: none 1401** 1402** IMPLICIT OUTPUTS: none 1403** 1404** FUNCTION VALUE: none 1405** 1406** SIDE EFFECTS: none 1407** 1408**-- 1409**/ 1410 1411PRIVATE void rpc__auth_info_cache_init 1412( 1413 unsigned32 *status 1414) 1415{ 1416 CODING_ERROR (status); 1417 1418 RPC_MUTEX_INIT (auth_info_cache_mutex); 1419 RPC_LIST_INIT (auth_info_cache); 1420 *status = rpc_s_ok; 1421} 1422 1423 1424/* 1425**++ 1426** 1427** ROUTINE NAME: rpc__auth_info_cache_lkup 1428** 1429** SCOPE: INTERNAL - declared locally 1430** 1431** DESCRIPTION: 1432** 1433** Scan a linked list of auth info structures looking for one which 1434** contains fields which match the input parameters. If and when a 1435** match is found the reference count of the auth info structure will 1436** be incremented before being returned. 1437** 1438** Note that it is possible for a null server principal name to 1439** match an auth info structure if that structure also has a 1440** null server principal name. 1441** 1442** INPUTS: 1443** 1444** server_princ_name Server principal name. 1445** authn_level Authentication level. 1446** authn_identity Authentication identity handle. 1447** authz_protocol Authorization protocol. 1448** authn_protocol Authentication protocol. 1449** 1450** INPUTS/OUTPUTS: none 1451** 1452** OUTPUTS: none 1453** 1454** IMPLICIT INPUTS: none 1455** 1456** IMPLICIT OUTPUTS: none 1457** 1458** FUNCTION VALUE: rpc_auth_info_t * 1459** 1460** A pointer to a matching auth info, NULL if none found. 1461** 1462** SIDE EFFECTS: 1463** 1464** If a matching auth info is found the reference count of it 1465** will have already been incremented. 1466** 1467**-- 1468**/ 1469 1470INTERNAL rpc_auth_info_t *rpc__auth_info_cache_lkup 1471( 1472 unsigned_char_p_t server_princ_name, 1473 rpc_authn_level_t authn_level, 1474 rpc_auth_identity_handle_t auth_identity, 1475 rpc_authz_protocol_id_t authz_protocol, 1476 rpc_authn_protocol_id_t authn_protocol 1477) 1478{ 1479 rpc_auth_info_t *auth_info; 1480 1481 RPC_MUTEX_LOCK (auth_info_cache_mutex); 1482 1483 /* 1484 * Scan the linked list of auth info structure looking for one 1485 * whose fields match the input args. 1486 */ 1487 RPC_LIST_FIRST (auth_info_cache, 1488 auth_info, 1489 rpc_auth_info_p_t); 1490 while (auth_info != NULL) 1491 { 1492 if (( 1493 /* 1494 * DCE secret key authentication requires a 1495 * non-null server principal name for authentication. 1496 * We allow a null server principal name here so 1497 * that this will work in the future when an 1498 * authentication service without this requirement 1499 * is used. 1500 */ 1501 ((server_princ_name == NULL) 1502 && (auth_info->server_princ_name == NULL)) 1503 || 1504 (server_princ_name 1505 && auth_info->server_princ_name 1506 && (strcmp ((char *) server_princ_name, 1507 (char *) auth_info->server_princ_name) == 0)) 1508 ) 1509 && 1510 (authn_level == auth_info->authn_level) 1511 && 1512 (authn_protocol == auth_info->authn_protocol) 1513 && 1514 (authz_protocol == auth_info->authz_protocol) 1515 && 1516 (auth_identity == auth_info->u.auth_identity)) 1517 { 1518 /* 1519 * A matching auth info was found. 1520 */ 1521 rpc__auth_info_reference (auth_info); 1522 break; 1523 } 1524 RPC_LIST_NEXT (auth_info, auth_info, rpc_auth_info_p_t); 1525 } 1526 RPC_MUTEX_UNLOCK (auth_info_cache_mutex); 1527 return (auth_info); 1528} 1529 1530 1531/* 1532**++ 1533** 1534** ROUTINE NAME: rpc__auth_info_cache_add 1535** 1536** SCOPE: INTERNAL - declared locally 1537** 1538** DESCRIPTION: 1539** 1540** Add an auth info structure to a linked list of them. The 1541** reference count of the added auth info structure will be incremented 1542** by the caller to account for its presence in the cache. 1543** 1544** INPUTS: 1545** 1546** auth_info The auth info to be added. 1547** 1548** INPUTS/OUTPUTS: none 1549** 1550** OUTPUTS: none 1551** 1552** IMPLICIT INPUTS: none 1553** 1554** IMPLICIT OUTPUTS: none 1555** 1556** FUNCTION VALUE: none 1557** 1558** SIDE EFFECTS: none 1559** 1560** The reference count of the added auth info structure will be 1561** incremented. 1562** 1563**-- 1564**/ 1565 1566INTERNAL void rpc__auth_info_cache_add 1567( 1568 rpc_auth_info_p_t auth_info 1569) 1570{ 1571 assert (!auth_info->is_server); 1572 1573 RPC_MUTEX_LOCK (auth_info_cache_mutex); 1574 RPC_LIST_ADD_HEAD (auth_info_cache, 1575 auth_info, 1576 rpc_auth_info_p_t); 1577 rpc__auth_info_reference (auth_info); 1578 RPC_MUTEX_UNLOCK (auth_info_cache_mutex); 1579} 1580 1581 1582/* 1583**++ 1584** 1585** ROUTINE NAME: rpc__auth_info_cache_remove 1586** 1587** SCOPE: INTERNAL - declared locally 1588** 1589** DESCRIPTION: 1590** 1591** Remove an auth info structure from a linked list of them. The 1592** cache's reference to the auth info structure will be released by 1593** the caller. 1594** 1595** It is assumed that the caller has already determined it is OK to 1596** remove this auth info from the cache. It is expected that the 1597** cache holds the last reference to this auth info structure at 1598** this point. 1599** 1600** INPUTS: 1601** 1602** auth_info The auth info to be removed. 1603** 1604** INPUTS/OUTPUTS: none 1605** 1606** OUTPUTS: none 1607** 1608** IMPLICIT INPUTS: none 1609** 1610** IMPLICIT OUTPUTS: none 1611** 1612** FUNCTION VALUE: none 1613** 1614** SIDE EFFECTS: none 1615** 1616**-- 1617**/ 1618 1619INTERNAL void rpc__auth_info_cache_remove 1620( 1621 rpc_auth_info_p_t auth_info 1622) 1623{ 1624 assert (!auth_info->is_server); 1625 1626 RPC_MUTEX_LOCK (auth_info_cache_mutex); 1627 1628 /* 1629 * Make sure, under the protection of the cache lock, that this 1630 * really should be removed from the cache. 1631 */ 1632 if (auth_info->refcount == 1) 1633 { 1634 const char *info_type; 1635 1636 RPC_LIST_REMOVE (auth_info_cache, auth_info); 1637 info_type = auth_info->is_server?"server":"client"; 1638 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc__auth_info_release) %p: dropping %s refcount (was %d, now %d)\n", 1639 auth_info, 1640 info_type, 1641 auth_info->refcount, 1642 auth_info->refcount-1 )); 1643 assert(auth_info->refcount >= 1); 1644 auth_info->refcount--; 1645 } 1646 RPC_MUTEX_UNLOCK (auth_info_cache_mutex); 1647} 1648 1649 1650/* 1651**++ 1652** 1653** ROUTINE NAME: rpc_server_inq_call_attributes 1654** 1655** SCOPE: PUBLIC - declared in rpcauth.idl 1656** 1657** DESCRIPTION: 1658** 1659** Return RPC call attributes 1660** 1661** INPUTS: 1662** 1663** binding_h Server-side binding handle to remote caller whose 1664** identity is being requested. 1665** 1666** INPUTS/OUTPUTS: none 1667** 1668** OUTPUTS: 1669** 1670** attributes RPC call attributes 1671** 1672** status Status code 1673** 1674** IMPLICIT INPUTS: none 1675** 1676** IMPLICIT OUTPUTS: none 1677** 1678** FUNCTION VALUE: none 1679** 1680** SIDE EFFECTS: none 1681** 1682**-- 1683**/ 1684 1685PUBLIC void rpc_server_inq_call_attributes 1686( 1687 rpc_binding_handle_t binding_h, 1688 rpc_call_attributes_t *attributes, 1689 unsigned32 *st 1690) 1691{ 1692 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1693 rpc_auth_info_p_t auth_info; 1694 rpc_call_attributes_v1_t *v1_attributes; 1695 1696 assert(binding_rep != NULL); 1697 1698 CODING_ERROR (st); 1699 RPC_VERIFY_INIT (); 1700 1701 RPC_BINDING_VALIDATE_SERVER(binding_rep, st); 1702 if (*st != rpc_s_ok) 1703 return; 1704 1705 auth_info = ((rpc_binding_rep_p_t)binding_h)->auth_info; 1706 1707 if (auth_info == NULL) 1708 { 1709 *st = rpc_s_binding_has_no_auth; 1710 return; 1711 } 1712 1713 assert(auth_info->is_server); 1714 1715 if (attributes->version != 1) 1716 { 1717 *st = rpc_s_auth_badversion; 1718 return; 1719 } 1720 1721 v1_attributes = (rpc_call_attributes_v1_p_t)attributes; 1722 1723 if (v1_attributes->flags & rpc_query_server_principal_name) 1724 { 1725 ASSIGN_COPY(v1_attributes->server_princ_name, 1726 v1_attributes->server_princ_name_buff_len, 1727 auth_info->server_princ_name); 1728 } 1729 1730 if (v1_attributes->flags & rpc_query_client_principal_name) 1731 { 1732 if (auth_info->authz_protocol != rpc_c_authz_name) 1733 { 1734 *st = rpc_s_binding_has_no_auth; 1735 return; 1736 } 1737 1738 ASSIGN_COPY(v1_attributes->client_princ_name, 1739 v1_attributes->client_princ_name_buff_len, 1740 (unsigned_char_p_t)auth_info->u.s.privs); 1741 } 1742 1743 v1_attributes->authn_level = auth_info ? auth_info->authn_level : rpc_c_protect_level_none; 1744 v1_attributes->authn_protocol = auth_info ? auth_info->authn_protocol : rpc_c_authn_winnt; 1745 v1_attributes->null_session = /* FIXME: determine meaning of this flag */ 0; 1746 1747 *st = rpc_s_ok; 1748} 1749 1750 1751/* 1752**++ 1753** 1754** ROUTINE NAME: rpc_binding_inq_security_context 1755** 1756** SCOPE: PUBLIC - declared in rpc.idl 1757** 1758** DESCRIPTION: 1759** 1760** Return mechanism-specific security context from a binding handle. 1761** 1762** INPUTS: 1763** 1764** h RPC binding handle 1765** 1766** INPUTS/OUTPUTS: 1767** 1768** OUTPUTS: 1769** 1770** authn_protocol Authentication level 1771** 1772** sec_context Security context 1773** 1774** status A value indicating the return status of the routine 1775** rpc_s_invalid_binding 1776** RPC Protocol ID in binding handle was invalid. 1777** 1778** IMPLICIT INPUTS: none 1779** 1780** IMPLICIT OUTPUTS: none 1781** 1782** FUNCTION VALUE: none 1783** 1784** SIDE EFFECTS: none 1785** 1786**-- 1787**/ 1788 1789PUBLIC void rpc_binding_inq_security_context 1790( 1791 rpc_binding_handle_t binding_h, 1792 unsigned32 *authn_protocol, 1793 void **mech_context, 1794 unsigned32 *st 1795 ) 1796{ 1797 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1798 rpc_auth_info_p_t auth_info; 1799 1800 CODING_ERROR (st); 1801 RPC_VERIFY_INIT (); 1802 1803 *authn_protocol = rpc_c_authn_none; 1804 *mech_context = NULL; 1805 1806 auth_info = binding_rep->auth_info; 1807 if (auth_info == NULL) 1808 { 1809 *st = rpc_s_binding_has_no_auth; 1810 return; 1811 } 1812 1813 *authn_protocol = auth_info->authn_protocol; 1814 if (*authn_protocol == rpc_c_authn_none) 1815 { 1816 *st = rpc_s_ok; 1817 return; 1818 } 1819 1820 RPC_AUTHN_CHECK_SUPPORTED (*authn_protocol, st); 1821 1822 if (rpc_g_authn_protocol_id[*authn_protocol] 1823 .epv->inq_sec_context == NULL) 1824 { 1825 *st = rpc_s_binding_has_no_auth; 1826 return; 1827 } 1828 1829 (*rpc_g_authn_protocol_id[*authn_protocol] 1830 .epv->inq_sec_context) (auth_info, mech_context, st); 1831} 1832 1833/* 1834 **++ 1835 ** 1836 ** ROUTINE NAME: rpc_impersonate_named_pipe_client 1837 ** 1838 ** SCOPE: PUBLIC - declared in rpc.idl 1839 ** 1840 ** DESCRIPTION: 1841 ** 1842 ** This routine allows a server thread to run with the security credentials 1843 ** of the active client. 1844 ** 1845 ** INPUTS: 1846 ** 1847 ** binding_h RPC binding handle 1848 ** 1849 ** INPUTS/OUTPUTS: none 1850 ** 1851 ** OUTPUTS: 1852 ** 1853 ** status A value indicating the status of the routine. 1854 ** 1855 ** rpc_s_ok The call was successful. 1856 ** rpc_s_invalid_binding RPC Protocol ID in binding handle 1857 ** was invalid. 1858 ** rpc_s_coding_error 1859 ** rpc_s_protocol_error Wrong type of connection 1860 ** rpc_s_wrong_kind_of_binding Wrong kind of binding 1861 ** 1862 ** IMPLICIT INPUTS: none 1863 ** 1864 ** IMPLICIT OUTPUTS: none 1865 ** 1866 ** FUNCTION VALUE: void 1867 ** 1868 ** SIDE EFFECTS: none 1869 ** 1870 **-- 1871 **/ 1872 1873PUBLIC void rpc_impersonate_named_pipe_client 1874( 1875 rpc_binding_handle_t binding_h, 1876 unsigned32 *status 1877 ) 1878{ 1879#if HAVE_PTHREAD_SETUGID_NP 1880 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1881 rpc_protocol_id_t protid; 1882 rpc_prot_network_epv_p_t net_epv; 1883 uid_t euid = 0; 1884 gid_t egid = 0; 1885 int ret; 1886 1887 assert(binding_rep != NULL); 1888 1889 CODING_ERROR (status); 1890 RPC_VERIFY_INIT (); 1891 1892 RPC_BINDING_VALIDATE(binding_rep, status); 1893 if (*status != rpc_s_ok) 1894 { 1895 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_impersonate_named_pipe_client): invalid binding\n")); 1896 return; 1897 } 1898 1899 if (RPC_BINDING_IS_CLIENT (binding_rep)) 1900 { 1901 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_impersonate_named_pipe_client): wrong type of binding\n")); 1902 *status = rpc_s_wrong_kind_of_binding; 1903 return; 1904 } 1905 1906 protid = binding_rep->protocol_id; 1907 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (protid); 1908 1909 if (net_epv->network_getpeereid == NULL) 1910 { 1911 *status = rpc_s_protocol_error; 1912 return; 1913 } 1914 1915 /* 1916 * Call network protocol routine. 1917 */ 1918 (*net_epv->network_getpeereid) 1919 (binding_rep, &euid, &egid, status); 1920 1921 if (*status != rpc_s_ok) 1922 { 1923 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_impersonate_named_pipe_client): network_getpeereid failed %d\n", *status)); 1924 return; 1925 } 1926 1927 ret = pthread_setugid_np(euid, egid); 1928 if (ret != 0) { 1929 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_impersonate_named_pipe_client): pthread_setugid_np failed %d for euid %d, egid %d\n", errno, euid, egid)); 1930 *status = rpc_s_no_context_available; 1931 return; 1932 } 1933 1934 /* opt back into the dynamic group resolutions. 1935 For better performance, we only add in our egid instead of the 1936 entire group list. */ 1937 ret = syscall(SYS_initgroups, 1, &egid, euid); 1938 if (ret == -1) 1939 { 1940 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_impersonate_named_pipe_client): SYS_initgroups failed %d for euid %d, egid %d\n", errno, euid, egid)); 1941 *status = rpc_s_no_context_available; 1942 goto error; 1943 } 1944 1945 *status = rpc_s_ok; 1946 1947error: 1948 if (*status != rpc_s_ok) 1949 { 1950 /* error occurred, try to revert back to previous user/group ID */ 1951 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_impersonate_named_pipe_client): reverting credentials due to error %d\n", *status)); 1952 pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE); 1953 } 1954 1955#else 1956 *status = rpc_s_not_supported; 1957#endif 1958} 1959 1960/* 1961 **++ 1962 ** 1963 ** ROUTINE NAME: rpc_revert_to_self 1964 ** 1965 ** SCOPE: PUBLIC - declared in rpc.idl 1966 ** 1967 ** DESCRIPTION: 1968 ** 1969 ** This routine allows a server thread to end impersonation and revert to the 1970 ** per process credentials. 1971 ** 1972 ** INPUTS: none 1973 ** 1974 ** INPUTS/OUTPUTS: none 1975 ** 1976 ** OUTPUTS: 1977 ** 1978 ** status A value indicating the status of the routine. 1979 ** 1980 ** rpc_s_ok The call was successful. 1981 ** rpc_s_invalid_binding RPC Protocol ID in binding handle 1982 ** was invalid. 1983 ** rpc_s_coding_error 1984 ** rpc_s_protocol_error Wrong type of connection 1985 ** rpc_s_wrong_kind_of_binding Wrong kind of binding 1986 ** 1987 ** IMPLICIT INPUTS: none 1988 ** 1989 ** IMPLICIT OUTPUTS: none 1990 ** 1991 ** FUNCTION VALUE: void 1992 ** 1993 ** SIDE EFFECTS: none 1994 ** 1995 **-- 1996 **/ 1997 1998PUBLIC void rpc_revert_to_self 1999( 2000 rpc_binding_handle_t binding_h, 2001 unsigned32 *status 2002 ) 2003{ 2004#if HAVE_PTHREAD_SETUGID_NP 2005 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 2006 int ret; 2007 2008 assert(binding_rep != NULL); 2009 2010 CODING_ERROR (status); 2011 RPC_VERIFY_INIT (); 2012 2013 RPC_BINDING_VALIDATE(binding_rep, status); 2014 if (*status != rpc_s_ok) 2015 { 2016 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_revert_to_self): invalid binding\n")); 2017 return; 2018 } 2019 2020 if (RPC_BINDING_IS_CLIENT (binding_rep)) 2021 { 2022 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_revert_to_self): wrong type of binding\n")); 2023 *status = rpc_s_wrong_kind_of_binding; 2024 return; 2025 } 2026 2027 ret = pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE); 2028 if (ret != 0) 2029 { 2030 RPC_DBG_PRINTF(rpc_e_dbg_auth, 3, ("(rpc_revert_to_self): pthread_setugid_np failed %d\n", errno)); 2031 *status = rpc_s_no_context_available; 2032 return; 2033 } 2034 2035 *status = rpc_s_ok; 2036#else 2037 *status = rpc_s_not_supported; 2038#endif 2039} 2040