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