LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/gssapi/krb5 - name_attrs.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 0 575 0.0 %
Date: 2024-04-13 12:30:31 Functions: 0 19 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2021 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       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             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "gsskrb5_locl.h"
      35             : 
      36             : /*
      37             :  * (Not-yet-)Standard name attributes for Kerberos MNs,
      38             :  * GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "...".
      39             :  *
      40             :  * I.e., "urn:ietf:kerberos:nameattr-...".  (XXX Register this URN namespace
      41             :  * with IANA.)
      42             :  *
      43             :  * Note that we do use URN fragments.
      44             :  *
      45             :  * Specific attributes below the base URN:
      46             :  *
      47             :  *  - name access attributes:
      48             :  *     - "realm"                    -> realm of name
      49             :  *     - "name-ncomp"               -> count of name components
      50             :  *     - "name-ncomp#<digit>"       -> name component N (0 <= N <= 9)
      51             :  *
      52             :  * Ticket and Authenticator access attributes:
      53             :  *
      54             :  *  - "transit-path"                -> encoding of the transited path
      55             :  *  - "authenticator-authz-data"    -> encoding of all of the authz-data from
      56             :  *                                     the AP-REQ's Authenticator
      57             :  *  - "ticket-authz-data"           -> encoding of all of the authz-data from
      58             :  *                                     the AP-REQ's Ticket
      59             :  *  - "ticket-authz-data#pac"       -> the PAC
      60             :  *  - "authz-data#<N>"              -> encoding of all of a specific auth-data
      61             :  *                                     element type N (e.g., 2, meaning
      62             :  *                                     AD-INTENDED-FOR-SERVER)
      63             :  *
      64             :  * Misc. attributes:
      65             :  *
      66             :  *  - "peer-realm"                  -> name of peer's realm (if this is an MN
      67             :  *                                     resulting for establishing a security
      68             :  *                                     context)
      69             :  *  - "canonical-name"              -> exported name token and RFC1964 display
      70             :  *                                     syntax of the name's canonical name
      71             :  *
      72             :  * Compatibility with MIT:
      73             :  *
      74             :  *  - "urn:mspac:"                  -> the PAC and its individual info buffers
      75             :  *
      76             :  * TODO:
      77             :  *
      78             :  *  - Add some sort of display syntax for transit path
      79             :  *  - Add support for URN q-components or attribute prefixes to specify
      80             :  *    alternative raw and/or display value encodings (JSON?)
      81             :  *  - Add support for attributes for accessing other parts of the Ticket / KDC
      82             :  *    reply enc-parts, like auth times
      83             :  *  - Add support for getting PAC logon fields, including SIDs (one at a time)
      84             :  *  - Add support for CAMMAC?
      85             :  */
      86             : 
      87             : static int
      88           0 : attr_eq(gss_const_buffer_t attr, const char *aname, size_t aname_len, \
      89             :         int prefix_check)
      90             : {
      91           0 :     if (attr->length < aname_len)
      92           0 :         return 0;
      93             : 
      94           0 :     if (strncmp((char *)attr->value, aname, aname_len) != 0)
      95           0 :         return 0;
      96             : 
      97           0 :     return prefix_check || attr->length == aname_len;
      98             : }
      99             : 
     100             : #define ATTR_EQ(a, an) (attr_eq(a, an, sizeof(an) - 1, FALSE))
     101             : #define ATTR_EQ_PREFIX(a, an) (attr_eq(a, an, sizeof(an) - 1, TRUE))
     102             : 
     103             : /* Split attribute into prefix, suffix, and fragment.  See RFC6680. */
     104             : static void
     105           0 : split_attr(gss_const_buffer_t orig,
     106             :            gss_buffer_t prefix,
     107             :            gss_buffer_t attr,
     108             :            gss_buffer_t frag,
     109             :            int *is_urn)
     110             : {
     111           0 :     char *last = NULL;
     112           0 :     char *p = orig->value;
     113             : 
     114           0 :     *attr = *orig;
     115           0 :     prefix->value = orig->value;
     116           0 :     prefix->length = 0;
     117           0 :     frag->length = 0;
     118           0 :     frag->value = NULL;
     119             : 
     120             :     /* FIXME We don't have a memrchr() in lib/roken */
     121           0 :     for (p = memchr(p, ' ', orig->length);
     122           0 :          p;
     123           0 :          p = memchr(p + 1, ' ', orig->length)) {
     124           0 :         last = p;
     125           0 :         prefix->length = last - (const char *)orig->value;
     126           0 :         attr->value = last + 1;
     127           0 :         attr->length = orig->length - (prefix->length + 1);
     128             :     }
     129           0 :     if (prefix->length == 0)
     130           0 :         prefix->value = NULL;
     131             : 
     132           0 :     if ((*is_urn = (strncmp(attr->value, "urn:", sizeof("urn:") - 1) == 0)) &&
     133           0 :         (p = memchr((char *)attr->value + 1, '#', attr->length - 1))) {
     134           0 :         frag->value = ++p;
     135           0 :         frag->length = attr->length - (p - (const char *)attr->value);
     136           0 :         attr->length = --p - (const char *)attr->value;
     137             :     }
     138           0 : }
     139             : 
     140             : typedef OM_uint32 get_name_attr_f(OM_uint32 *,
     141             :                                   const CompositePrincipal *,
     142             :                                   gss_const_buffer_t,
     143             :                                   gss_const_buffer_t,
     144             :                                   gss_const_buffer_t,
     145             :                                   int *,
     146             :                                   int *,
     147             :                                   gss_buffer_t,
     148             :                                   gss_buffer_t,
     149             :                                   int *);
     150             : 
     151             : typedef OM_uint32 set_name_attr_f(OM_uint32 *,
     152             :                                   CompositePrincipal *,
     153             :                                   gss_const_buffer_t,
     154             :                                   gss_const_buffer_t,
     155             :                                   gss_const_buffer_t,
     156             :                                   int,
     157             :                                   gss_buffer_t);
     158             : 
     159             : typedef OM_uint32 del_name_attr_f(OM_uint32 *,
     160             :                                   CompositePrincipal *,
     161             :                                   gss_const_buffer_t,
     162             :                                   gss_const_buffer_t,
     163             :                                   gss_const_buffer_t);
     164             : typedef get_name_attr_f *get_name_attr_fp;
     165             : typedef set_name_attr_f *set_name_attr_fp;
     166             : typedef del_name_attr_f *del_name_attr_fp;
     167             : 
     168             : static get_name_attr_f get_realm;
     169             : static get_name_attr_f get_ncomps;
     170             : static get_name_attr_f get_peer_realm;
     171             : static get_name_attr_f get_pac;
     172             : static get_name_attr_f get_pac_buffer;
     173             : static get_name_attr_f get_authz_data;
     174             : static get_name_attr_f get_ticket_authz_data;
     175             : static get_name_attr_f get_authenticator_authz_data;
     176             : static set_name_attr_f set_authenticator_authz_data;
     177             : static get_name_attr_f get_transited;
     178             : static get_name_attr_f get_canonical_name;
     179             : 
     180             : #define NB(n) \
     181             :     GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n, n, \
     182             :     sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n) - 1, \
     183             :     sizeof(n) - 1
     184             : #define NM(n) \
     185             :     "urn:mspac:" n, n, sizeof("urn:mspac:" n) - 1, sizeof(n) - 1
     186             : 
     187             : static struct krb5_name_attrs {
     188             :     const char *fullname;
     189             :     const char *name;
     190             :     size_t fullnamelen;
     191             :     size_t namelen;
     192             :     get_name_attr_fp getter;
     193             :     set_name_attr_fp setter;
     194             :     del_name_attr_fp deleter;
     195             :     unsigned int indicate:1;
     196             :     unsigned int is_krb5_name_attr_urn:1;
     197             : } name_attrs[] = {
     198             :     /* XXX We should sort these so we can binary search them */
     199             :     { NB("realm"),          get_realm,      NULL, NULL, 1, 1 },
     200             :     { NB("name-ncomp"),     get_ncomps,     NULL, NULL, 1, 1 },
     201             :     { NB("name-ncomp#0"),   get_ncomps,     NULL, NULL, 1, 1 },
     202             :     { NB("name-ncomp#1"),   get_ncomps,     NULL, NULL, 1, 1 },
     203             :     { NB("name-ncomp#2"),   get_ncomps,     NULL, NULL, 1, 1 },
     204             :     { NB("name-ncomp#3"),   get_ncomps,     NULL, NULL, 1, 1 },
     205             :     { NB("name-ncomp#4"),   get_ncomps,     NULL, NULL, 1, 1 },
     206             :     { NB("name-ncomp#5"),   get_ncomps,     NULL, NULL, 1, 1 },
     207             :     { NB("name-ncomp#6"),   get_ncomps,     NULL, NULL, 1, 1 },
     208             :     { NB("name-ncomp#7"),   get_ncomps,     NULL, NULL, 1, 1 },
     209             :     { NB("name-ncomp#8"),   get_ncomps,     NULL, NULL, 1, 1 },
     210             :     { NB("name-ncomp#9"),   get_ncomps,     NULL, NULL, 1, 1 },
     211             :     { NB("peer-realm"),     get_peer_realm, NULL, NULL, 1, 1 },
     212             :     { NB("ticket-authz-data#pac"), get_pac, NULL, NULL, 1, 1 },
     213             :     { NM(""),                   get_pac,    NULL, NULL, 1, 0 },
     214             :     { NM("logon-info"),         get_pac_buffer,    NULL, NULL, 1, 0 },
     215             :     { NM("credentials-info"),   get_pac_buffer,    NULL, NULL, 1, 0 },
     216             :     { NM("server-checksum"),    get_pac_buffer,    NULL, NULL, 1, 0 },
     217             :     { NM("privsvr-checksum"),   get_pac_buffer,    NULL, NULL, 1, 0 },
     218             :     { NM("client-info"),        get_pac_buffer,    NULL, NULL, 1, 0 },
     219             :     { NM("delegation-info"),    get_pac_buffer,    NULL, NULL, 1, 0 },
     220             :     { NM("upn-dns-info"),       get_pac_buffer,    NULL, NULL, 1, 0 },
     221             :     { NM("ticket-checksum"),    get_pac_buffer,    NULL, NULL, 1, 0 },
     222             :     { NM("attributes-info"),    get_pac_buffer,    NULL, NULL, 1, 0 },
     223             :     { NM("requestor-sid"),      get_pac_buffer,    NULL, NULL, 1, 0 },
     224             :     { NB("ticket-authz-data#kdc-issued"),
     225             :          get_ticket_authz_data, NULL, NULL, 1, 1 },
     226             :     { NB("ticket-authz-data"),
     227             :          get_ticket_authz_data, NULL, NULL, 1, 1 },
     228             :     { NB("authenticator-authz-data"),
     229             :          get_authenticator_authz_data,
     230             :          set_authenticator_authz_data, NULL, 1, 1 },
     231             :     { NB("authz-data"),     get_authz_data,  NULL, NULL, 1, 1 },
     232             :     { NB("transit-path"),   get_transited,   NULL, NULL, 1, 1 },
     233             :     { NB("canonical-name"), get_canonical_name, NULL, NULL, 1, 1 },
     234             : };
     235             : 
     236             : OM_uint32 GSSAPI_CALLCONV
     237           0 : _gsskrb5_get_name_attribute(OM_uint32 *minor_status,
     238             :                             gss_name_t name,
     239             :                             gss_buffer_t original_attr,
     240             :                             int *authenticated,
     241             :                             int *complete,
     242             :                             gss_buffer_t value,
     243             :                             gss_buffer_t display_value,
     244             :                             int *more)
     245             : {
     246           0 :     gss_buffer_desc prefix, attr, suffix, frag;
     247           0 :     size_t i;
     248           0 :     int is_krb5_name_attr_urn = 0;
     249           0 :     int is_urn = 0;
     250             : 
     251           0 :     *minor_status = 0;
     252           0 :     if (authenticated)
     253           0 :         *authenticated = 0;
     254           0 :     if (complete)
     255           0 :         *complete = 0;
     256           0 :     if (more)
     257           0 :         *more = 0;
     258           0 :     if (value) {
     259           0 :         value->length = 0;
     260           0 :         value->value = NULL;
     261             :     }
     262           0 :     if (display_value) {
     263           0 :         display_value->length = 0;
     264           0 :         display_value->value = NULL;
     265             :     }
     266             : 
     267           0 :     suffix.value = NULL;
     268           0 :     suffix.length = 0;
     269             : 
     270           0 :     split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
     271             : 
     272           0 :     if (prefix.length || !is_urn)
     273           0 :         return GSS_S_UNAVAILABLE;
     274             : 
     275           0 :     is_krb5_name_attr_urn =
     276           0 :         ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
     277           0 :     if (is_krb5_name_attr_urn) {
     278           0 :         suffix.value =
     279           0 :             (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
     280           0 :         suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
     281             :     }
     282             : 
     283           0 :     for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
     284           0 :         if (!name_attrs[i].getter)
     285           0 :             continue;
     286           0 :         if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
     287           0 :             if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
     288           0 :                 continue;
     289           0 :         } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
     290           0 :             if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0))
     291           0 :                 continue;
     292             :         } else
     293           0 :             continue;
     294             : 
     295           0 :         return name_attrs[i].getter(minor_status,
     296             :                                     (const CompositePrincipal *)name,
     297             :                                     &prefix, &attr, &frag, authenticated,
     298             :                                     complete, value, display_value, more);
     299             :     }
     300           0 :     return GSS_S_UNAVAILABLE;
     301             : }
     302             : 
     303             : OM_uint32 GSSAPI_CALLCONV
     304           0 : _gsskrb5_set_name_attribute(OM_uint32 *minor_status,
     305             :                             gss_name_t name,
     306             :                             int complete,
     307             :                             gss_buffer_t original_attr,
     308             :                             gss_buffer_t value)
     309             : {
     310           0 :     gss_buffer_desc prefix, attr, suffix, frag;
     311           0 :     size_t i;
     312           0 :     int is_krb5_name_attr_urn = 0;
     313           0 :     int is_urn = 0;
     314             : 
     315           0 :     *minor_status = 0;
     316             : 
     317           0 :     suffix.value = NULL;
     318           0 :     suffix.length = 0;
     319             : 
     320           0 :     split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
     321             : 
     322           0 :     if (prefix.length || !is_urn)
     323           0 :         return GSS_S_UNAVAILABLE;
     324             : 
     325           0 :     is_krb5_name_attr_urn =
     326           0 :         ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
     327           0 :     if (is_krb5_name_attr_urn) {
     328           0 :         suffix.value =
     329           0 :             (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
     330           0 :         suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
     331             :     }
     332             : 
     333           0 :     for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
     334           0 :         if (!name_attrs[i].setter)
     335           0 :             continue;
     336           0 :         if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
     337           0 :             if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
     338           0 :                 continue;
     339           0 :         } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
     340           0 :             if (!attr_eq(&attr, name_attrs[i].name, name_attrs[i].namelen, 0))
     341           0 :                 continue;
     342             :         } else
     343           0 :             continue;
     344             : 
     345           0 :         return name_attrs[i].setter(minor_status, (CompositePrincipal *)name,
     346             :                                     &prefix, &attr, &frag, complete, value);
     347             :     }
     348           0 :     return GSS_S_UNAVAILABLE;
     349             : }
     350             : 
     351             : OM_uint32 GSSAPI_CALLCONV
     352           0 : _gsskrb5_delete_name_attribute(OM_uint32 *minor_status,
     353             :                                gss_name_t name,
     354             :                                gss_buffer_t original_attr)
     355             : {
     356           0 :     gss_buffer_desc prefix, attr, suffix, frag;
     357           0 :     size_t i;
     358           0 :     int is_krb5_name_attr_urn = 0;
     359           0 :     int is_urn = 0;
     360             : 
     361           0 :     *minor_status = 0;
     362             : 
     363           0 :     suffix.value = NULL;
     364           0 :     suffix.length = 0;
     365             : 
     366           0 :     split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
     367             : 
     368           0 :     if (prefix.length || !is_urn)
     369           0 :         return GSS_S_UNAVAILABLE;
     370             : 
     371           0 :     is_krb5_name_attr_urn =
     372           0 :         ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
     373           0 :     if (is_krb5_name_attr_urn) {
     374           0 :         suffix.value =
     375           0 :             (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
     376           0 :         suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
     377             :     }
     378             : 
     379           0 :     for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
     380           0 :         if (!name_attrs[i].deleter)
     381           0 :             continue;
     382           0 :         if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
     383           0 :             if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
     384           0 :                 continue;
     385           0 :         } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
     386           0 :             if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0))
     387           0 :                 continue;
     388             :         } else
     389           0 :             continue;
     390             : 
     391           0 :         return name_attrs[i].deleter(minor_status, (CompositePrincipal *)name,
     392             :                                     &prefix, &attr, &frag);
     393             :     }
     394           0 :     return GSS_S_UNAVAILABLE;
     395             : }
     396             : 
     397             : OM_uint32 GSSAPI_CALLCONV
     398           0 : _gsskrb5_inquire_name(OM_uint32 *minor_status,
     399             :                       gss_name_t name,
     400             :                       int *name_is_MN,
     401             :                       gss_OID *MN_mech,
     402             :                       gss_buffer_set_t *attrs)
     403             : {
     404           0 :     gss_buffer_desc prefix, attr, frag, a;
     405           0 :     OM_uint32 major = GSS_S_UNAVAILABLE;
     406           0 :     size_t i;
     407           0 :     int authenticated, is_urn;
     408             : 
     409           0 :     *minor_status = 0;
     410           0 :     if (name_is_MN)
     411           0 :         *name_is_MN = 1;
     412           0 :     if (MN_mech)
     413           0 :         *MN_mech = GSS_KRB5_MECHANISM;
     414           0 :     if (name == GSS_C_NO_NAME)
     415           0 :         return GSS_S_CALL_INACCESSIBLE_READ;
     416           0 :     if (attrs == NULL)
     417           0 :         return GSS_S_CALL_INACCESSIBLE_WRITE;
     418             : 
     419           0 :     for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
     420           0 :         if (!name_attrs[i].indicate)
     421           0 :             continue;
     422           0 :         a.value = (void *)(uintptr_t)name_attrs[i].fullname;
     423           0 :         a.length = name_attrs[i].fullnamelen;
     424           0 :         split_attr(&a, &prefix, &attr, &frag, &is_urn);
     425           0 :         major = name_attrs[i].getter(minor_status,
     426             :                                      (const CompositePrincipal *)name,
     427             :                                      &prefix, &attr, &frag, &authenticated,
     428             :                                      NULL, NULL, NULL, NULL);
     429           0 :         if (major == GSS_S_UNAVAILABLE)
     430           0 :             continue;
     431           0 :         if (major != GSS_S_COMPLETE)
     432           0 :             break;
     433           0 :         major = gss_add_buffer_set_member(minor_status, &a, attrs);
     434             :     }
     435           0 :     if (major == GSS_S_UNAVAILABLE)
     436           0 :         major = GSS_S_COMPLETE;
     437           0 :     return major;
     438             : }
     439             : 
     440             : OM_uint32 GSSAPI_CALLCONV
     441           0 : _gsskrb5_display_name_ext(OM_uint32 *minor_status,
     442             :                           gss_name_t name,
     443             :                           gss_OID display_as_name_type,
     444             :                           gss_buffer_t display_name)
     445             : {
     446           0 :     krb5_const_principal p = (void *)name;
     447           0 :     char *s = NULL;
     448             : 
     449           0 :     *minor_status = 0;
     450           0 :     if (display_name == NULL)
     451           0 :         return GSS_S_CALL_INACCESSIBLE_WRITE;
     452           0 :     display_name->length = 0;
     453           0 :     display_name->value = NULL;
     454             : 
     455           0 :     if (gss_oid_equal(display_as_name_type, GSS_C_NT_USER_NAME)) {
     456           0 :         if (p->name.name_string.len != 1)
     457           0 :             return GSS_S_UNAVAILABLE;
     458           0 :         return _gsskrb5_localname(minor_status, name, GSS_KRB5_MECHANISM,
     459             :                                   display_name);
     460             :     }
     461           0 :     if (!gss_oid_equal(display_as_name_type, GSS_C_NT_HOSTBASED_SERVICE) ||
     462           0 :         p->name.name_string.len != 2 ||
     463           0 :         strchr(p->name.name_string.val[0], '@') ||
     464           0 :         strchr(p->name.name_string.val[1], '.') == NULL)
     465           0 :         return GSS_S_UNAVAILABLE;
     466           0 :     if (asprintf(&s, "%s@%s", p->name.name_string.val[0],
     467           0 :                  p->name.name_string.val[1]) == -1 || s == NULL) {
     468           0 :         *minor_status = ENOMEM;
     469           0 :         return GSS_S_FAILURE;
     470             :     }
     471           0 :     display_name->length = strlen(s);
     472           0 :     display_name->value = s;
     473           0 :     return GSS_S_COMPLETE;
     474             : }
     475             : 
     476             : OM_uint32 GSSAPI_CALLCONV
     477           0 : _gsskrb5_export_name_composite(OM_uint32 *minor_status,
     478             :                                gss_name_t name,
     479             :                                gss_buffer_t exported_name)
     480             : {
     481           0 :     krb5_error_code kret;
     482           0 :     gss_buffer_desc inner = GSS_C_EMPTY_BUFFER;
     483           0 :     unsigned char *buf;
     484           0 :     size_t sz;
     485             : 
     486           0 :     if (name == NULL)
     487           0 :         return GSS_S_CALL_INACCESSIBLE_READ;
     488           0 :     if (exported_name == NULL)
     489           0 :         return GSS_S_CALL_INACCESSIBLE_WRITE;
     490             : 
     491           0 :     ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length,
     492             :                        (void *)name, &sz, kret);
     493           0 :     if (kret != 0) {
     494           0 :         *minor_status = kret;
     495           0 :         return GSS_S_FAILURE;
     496             :     }
     497             : 
     498           0 :     exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length;
     499           0 :     exported_name->value  = malloc(exported_name->length);
     500           0 :     if (exported_name->value == NULL) {
     501           0 :         free(inner.value);
     502           0 :         *minor_status = ENOMEM;
     503           0 :         return GSS_S_FAILURE;
     504             :     }
     505             : 
     506             :     /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
     507             : 
     508           0 :     buf = exported_name->value;
     509           0 :     buf[0] = 0x04;
     510           0 :     buf[1] = 0x02;
     511           0 :     buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff;
     512           0 :     buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff;
     513           0 :     buf[4] = 0x06;
     514           0 :     buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF;
     515             : 
     516           0 :     memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
     517           0 :     buf += 6 + GSS_KRB5_MECHANISM->length;
     518             : 
     519           0 :     buf[0] = (inner.length >> 24) & 0xff;
     520           0 :     buf[1] = (inner.length >> 16) & 0xff;
     521           0 :     buf[2] = (inner.length >> 8) & 0xff;
     522           0 :     buf[3] = (inner.length) & 0xff;
     523           0 :     buf += 4;
     524             : 
     525           0 :     memcpy(buf, inner.value, inner.length);
     526           0 :     free(inner.value);
     527             : 
     528           0 :     *minor_status = 0;
     529           0 :     return GSS_S_COMPLETE;
     530             : }
     531             : 
     532             : #define CHECK_ENOMEM(v, dv) \
     533             :     do { \
     534             :         if (((v) && !(v)->value) || ((dv) && !(dv)->value)) { \
     535             :             if ((v) && (v)->value) { \
     536             :                 free((v)->value); \
     537             :                 (v)->length = 0; \
     538             :                 (v)->value = NULL; \
     539             :             } \
     540             :             *minor_status = ENOMEM; \
     541             :             return GSS_S_FAILURE; \
     542             :         } \
     543             :     } while (0)
     544             : 
     545             : static OM_uint32
     546           0 : get_realm(OM_uint32 *minor_status,
     547             :           const CompositePrincipal *name,
     548             :           gss_const_buffer_t prefix,
     549             :           gss_const_buffer_t attr,
     550             :           gss_const_buffer_t frag,
     551             :           int *authenticated,
     552             :           int *complete,
     553             :           gss_buffer_t value,
     554             :           gss_buffer_t display_value,
     555             :           int *more)
     556             : {
     557           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
     558             : 
     559           0 :     if (prefix->length || frag->length || !name->realm)
     560           0 :         return GSS_S_UNAVAILABLE;
     561           0 :     if (authenticated && nameattrs && nameattrs->authenticated)
     562           0 :         *authenticated = 1;
     563           0 :     if (complete)
     564           0 :         *complete = 1;
     565           0 :     if (value && (value->value = strdup(name->realm)))
     566           0 :         value->length = strlen(name->realm);
     567           0 :     if (display_value && (display_value->value = strdup(name->realm)))
     568           0 :         display_value->length = strlen(name->realm);
     569           0 :     CHECK_ENOMEM(value, display_value);
     570           0 :     return GSS_S_COMPLETE;
     571             : }
     572             : 
     573             : static OM_uint32
     574           0 : get_ncomps(OM_uint32 *minor_status,
     575             :            const CompositePrincipal *name,
     576             :            gss_const_buffer_t prefix,
     577             :            gss_const_buffer_t attr,
     578             :            gss_const_buffer_t frag,
     579             :            int *authenticated,
     580             :            int *complete,
     581             :            gss_buffer_t value,
     582             :            gss_buffer_t display_value,
     583             :            int *more)
     584             : {
     585           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
     586           0 :     int n = -1;
     587             : 
     588           0 :     if (authenticated && nameattrs && nameattrs->authenticated)
     589           0 :         *authenticated = 1;
     590           0 :     if (complete)
     591           0 :         *complete = 1;
     592             : 
     593           0 :     if (frag->length == 1 &&
     594           0 :         ((const char *)frag->value)[0] >= '0' &&
     595           0 :         ((const char *)frag->value)[0] <= '9') {
     596           0 :         n = ((const char *)frag->value)[0] - '0';
     597           0 :     } else if (frag->length == sizeof("all") - 1 &&
     598           0 :                strncmp(frag->value, "all", sizeof("all") - 1) == 0) {
     599           0 :         if (!more || *more < -1 || *more == 0 || *more > CHAR_MAX ||
     600           0 :             *more > (int)name->name.name_string.len) {
     601           0 :             *minor_status = EINVAL;
     602           0 :             return GSS_S_UNAVAILABLE;
     603             :         }
     604           0 :         if (*more == -1) {
     605           0 :             *more = name->name.name_string.len - 1;
     606           0 :             n = 0;
     607             :         } else {
     608           0 :             n = name->name.name_string.len - *more;
     609           0 :             (*more)--;
     610             :         }
     611             :     }
     612             : 
     613           0 :     if (frag->length == 0) {
     614           0 :         char *s = NULL;
     615             : 
     616             :         /* Outut count of components */
     617           0 :         if (value && (value->value = malloc(sizeof(size_t)))) {
     618           0 :             *((size_t *)value->value) = name->name.name_string.len;
     619           0 :             value->length = sizeof(size_t);
     620             :         }
     621           0 :         if (display_value &&
     622           0 :             asprintf(&s, "%u", (unsigned int)name->name.name_string.len) > 0) {
     623           0 :             display_value->value = s;
     624           0 :             display_value->length = strlen(display_value->value);
     625             :         }
     626             :     } else {
     627             :         /*
     628             :          * Output a component.  The value and the display value are the same in
     629             :          * this case.
     630             :          */
     631           0 :         if (n < 0 || n >= name->name.name_string.len) {
     632           0 :             *minor_status = EINVAL;
     633           0 :             return GSS_S_UNAVAILABLE;
     634             :         }
     635           0 :         if (value && (value->value = strdup(name->name.name_string.val[n])))
     636           0 :             value->length = strlen(name->name.name_string.val[n]);
     637           0 :         if (display_value &&
     638           0 :             (display_value->value = strdup(name->name.name_string.val[n])))
     639           0 :             display_value->length = strlen(name->name.name_string.val[n]);
     640             :     }
     641             : 
     642           0 :     CHECK_ENOMEM(value, display_value);
     643           0 :     return GSS_S_COMPLETE;
     644             : }
     645             : 
     646             : static OM_uint32
     647           0 : get_peer_realm(OM_uint32 *minor_status,
     648             :                const CompositePrincipal *name,
     649             :                gss_const_buffer_t prefix,
     650             :                gss_const_buffer_t attr,
     651             :                gss_const_buffer_t frag,
     652             :                int *authenticated,
     653             :                int *complete,
     654             :                gss_buffer_t value,
     655             :                gss_buffer_t display_value,
     656             :                int *more)
     657             : {
     658           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
     659             : 
     660           0 :     if (prefix->length || frag->length || !nameattrs || !nameattrs->peer_realm)
     661           0 :         return GSS_S_UNAVAILABLE;
     662           0 :     if (authenticated)
     663           0 :         *authenticated = 1;
     664           0 :     if (complete)
     665           0 :         *complete = 1;
     666           0 :     if (value && (value->value = strdup(nameattrs->peer_realm[0])))
     667           0 :         value->length = strlen(value->value);
     668           0 :     if (display_value &&
     669           0 :         (display_value->value = strdup(nameattrs->peer_realm[0])))
     670           0 :         display_value->length = strlen(display_value->value);
     671             : 
     672           0 :     CHECK_ENOMEM(value, display_value);
     673           0 :     return GSS_S_COMPLETE;
     674             : }
     675             : 
     676             : static OM_uint32
     677           0 : get_pac(OM_uint32 *minor_status,
     678             :         const CompositePrincipal *name,
     679             :         gss_const_buffer_t prefix,
     680             :         gss_const_buffer_t attr,
     681             :         gss_const_buffer_t frag,
     682             :         int *authenticated,
     683             :         int *complete,
     684             :         gss_buffer_t value,
     685             :         gss_buffer_t display_value,
     686             :         int *more)
     687             : {
     688           0 :     krb5_error_code kret;
     689           0 :     krb5_context context;
     690           0 :     krb5_data data;
     691           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
     692           0 :     PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
     693           0 :     EncTicketPart *ticket = NULL;
     694             : 
     695           0 :     krb5_data_zero(&data);
     696             : 
     697           0 :     if (src == NULL ||
     698           0 :         src->element != choice_PrincipalNameAttrSrc_enc_ticket_part)
     699           0 :         return GSS_S_UNAVAILABLE;
     700             : 
     701           0 :     ticket = &src->u.enc_ticket_part;
     702             : 
     703           0 :     if (prefix->length || !authenticated || !ticket)
     704           0 :         return GSS_S_UNAVAILABLE;
     705             : 
     706           0 :     GSSAPI_KRB5_INIT(&context);
     707             : 
     708           0 :     *authenticated = nameattrs->pac_verified;
     709           0 :     if (complete)
     710           0 :         *complete = 1;
     711             : 
     712           0 :     kret = _krb5_get_ad(context, ticket->authorization_data,
     713             :                         NULL, KRB5_AUTHDATA_WIN2K_PAC,
     714             :                         value ? &data : NULL);
     715             : 
     716           0 :     if (value) {
     717           0 :         value->length = data.length;
     718           0 :         value->value = data.data;
     719             :     }
     720             : 
     721           0 :     *minor_status = kret;
     722           0 :     if (kret == ENOENT)
     723           0 :         return GSS_S_UNAVAILABLE;
     724           0 :     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
     725             : }
     726             : 
     727             : static OM_uint32
     728           0 : get_pac_buffer(OM_uint32 *minor_status,
     729             :                const CompositePrincipal *name,
     730             :                gss_const_buffer_t prefix,
     731             :                gss_const_buffer_t attr,
     732             :                gss_const_buffer_t frag,
     733             :                int *authenticated,
     734             :                int *complete,
     735             :                gss_buffer_t value,
     736             :                gss_buffer_t display_value,
     737             :                int *more)
     738             : {
     739           0 :     krb5_error_code kret;
     740           0 :     krb5_context context;
     741           0 :     krb5_data data;
     742           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
     743           0 :     krb5_data suffix;
     744             : 
     745           0 :     krb5_data_zero(&data);
     746             : 
     747           0 :     if (prefix->length || !authenticated ||
     748           0 :         !nameattrs || !nameattrs->pac)
     749           0 :         return GSS_S_UNAVAILABLE;
     750             : 
     751           0 :     GSSAPI_KRB5_INIT(&context);
     752             : 
     753           0 :     if (ATTR_EQ_PREFIX(attr, "urn:mspac:")) {
     754           0 :         suffix.length = attr->length - (sizeof("urn:mspac:") - 1);
     755           0 :         suffix.data = (char *)attr->value + sizeof("urn:mspac:") - 1;
     756           0 :     } else if (ATTR_EQ_PREFIX(frag, "pac-")) {
     757           0 :         suffix.length = frag->length - sizeof("pac-") - 1;
     758           0 :         suffix.data = (char *)frag->value + sizeof("pac-") - 1;
     759             :     } else
     760           0 :         return GSS_S_UNAVAILABLE; /* should not be reached */
     761             : 
     762           0 :     *authenticated = nameattrs->pac_verified;
     763           0 :     if (complete)
     764           0 :         *complete = 1;
     765             : 
     766           0 :     kret = _krb5_pac_get_buffer_by_name(context, nameattrs->pac, &suffix,
     767             :                                         value ? &data : NULL);
     768             : 
     769           0 :     if (value) {
     770           0 :         value->length = data.length;
     771           0 :         value->value = data.data;
     772             :     }
     773             : 
     774           0 :     *minor_status = kret;
     775           0 :     if (kret == ENOENT)
     776           0 :         return GSS_S_UNAVAILABLE;
     777           0 :     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
     778             : }
     779             : 
     780             : static OM_uint32
     781           0 : get_authz_data(OM_uint32 *minor_status,
     782             :                const CompositePrincipal *name,
     783             :                gss_const_buffer_t prefix,
     784             :                gss_const_buffer_t attr,
     785             :                gss_const_buffer_t frag,
     786             :                int *authenticated,
     787             :                int *complete,
     788             :                gss_buffer_t value,
     789             :                gss_buffer_t display_value,
     790             :                int *more)
     791             : {
     792           0 :     krb5_error_code kret = 0;
     793           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
     794           0 :     PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
     795           0 :     EncTicketPart *ticket = NULL;
     796           0 :     krb5_context context;
     797           0 :     krb5_data data;
     798           0 :     char s[22];
     799           0 :     char *end;
     800           0 :     int64_t n;
     801             : 
     802           0 :     if (src) switch (src->element) {
     803           0 :     case choice_PrincipalNameAttrSrc_enc_ticket_part:
     804           0 :         ticket = &src->u.enc_ticket_part;
     805           0 :         break;
     806           0 :     case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
     807             :     default:
     808           0 :         return GSS_S_UNAVAILABLE;
     809             :     }
     810             : 
     811           0 :     if (!nameattrs || !frag->length || frag->length > sizeof(s) - 1)
     812           0 :         return GSS_S_UNAVAILABLE;
     813             : 
     814             :     /* Output a specific AD element from the ticket or authenticator */
     815           0 :     krb5_data_zero(&data);
     816           0 :     memcpy(s, frag->value, frag->length);
     817           0 :     s[frag->length] = '\0';
     818           0 :     errno = 0;
     819           0 :     n = strtoll(s, &end, 10);
     820           0 :     if (end[0] == '\0' && (errno || n > INT_MAX || n < INT_MIN)) {
     821           0 :         *minor_status = ERANGE;
     822           0 :         return GSS_S_UNAVAILABLE;
     823             :     }
     824           0 :     if (end[0] != '\0') {
     825           0 :         *minor_status = EINVAL;
     826           0 :         return GSS_S_UNAVAILABLE;
     827             :     }
     828             : 
     829           0 :     if (authenticated)
     830           0 :         *authenticated = 0;
     831           0 :     if (complete)
     832           0 :         *complete = 1;
     833             : 
     834           0 :     GSSAPI_KRB5_INIT(&context);
     835             : 
     836           0 :     kret = ENOENT;
     837           0 :     if (ticket && ticket->authorization_data) {
     838           0 :         kret = _krb5_get_ad(context, ticket->authorization_data,
     839             :                             NULL, n, value ? &data : NULL);
     840             : 
     841             :         /* If it's from the ticket, it _may_ be authenticated: */
     842           0 :         if (kret == 0 && authenticated) {
     843           0 :             if (n == KRB5_AUTHDATA_KDC_ISSUED)
     844           0 :                 *authenticated = nameattrs->kdc_issued_verified;
     845           0 :             else if (n == KRB5_AUTHDATA_WIN2K_PAC)
     846           0 :                 *authenticated = nameattrs->pac_verified;
     847             :         }
     848             :     }
     849           0 :     if (kret == ENOENT && nameattrs->authenticator_ad &&
     850           0 :         n != KRB5_AUTHDATA_KDC_ISSUED &&
     851           0 :         n != KRB5_AUTHDATA_WIN2K_PAC) {
     852           0 :         kret = _krb5_get_ad(context, nameattrs->authenticator_ad,
     853             :                             NULL, n, value ? &data : NULL);
     854             :     }
     855             : 
     856           0 :     if (value) {
     857           0 :         value->length = data.length;
     858           0 :         value->value = data.data;
     859             :     }
     860           0 :     *minor_status = kret;
     861           0 :     if (kret == ENOENT)
     862           0 :         return GSS_S_UNAVAILABLE;
     863           0 :     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
     864             : }
     865             : 
     866             : static OM_uint32
     867           0 : get_ticket_authz_data(OM_uint32 *minor_status,
     868             :                       const CompositePrincipal *name,
     869             :                       gss_const_buffer_t prefix,
     870             :                       gss_const_buffer_t attr,
     871             :                       gss_const_buffer_t frag,
     872             :                       int *authenticated,
     873             :                       int *complete,
     874             :                       gss_buffer_t value,
     875             :                       gss_buffer_t display_value,
     876             :                       int *more)
     877             : {
     878           0 :     krb5_error_code kret = 0;
     879           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
     880           0 :     PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
     881           0 :     EncTicketPart *ticket = NULL;
     882           0 :     size_t sz;
     883             : 
     884           0 :     if (src) switch (src->element) {
     885           0 :     case choice_PrincipalNameAttrSrc_enc_ticket_part:
     886           0 :         ticket = &src->u.enc_ticket_part;
     887           0 :         break;
     888           0 :     case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
     889             :     default:
     890           0 :         return GSS_S_UNAVAILABLE;
     891             :     }
     892             : 
     893           0 :     if (!ticket)
     894           0 :         return GSS_S_UNAVAILABLE;
     895             : 
     896           0 :     if (complete)
     897           0 :         *complete = 1;
     898             : 
     899           0 :     if (frag->length == sizeof("kdc-issued") - 1 &&
     900           0 :         strncmp(frag->value, "kdc-issued", sizeof("kdc-issued") - 1) == 0) {
     901           0 :         krb5_context context;
     902           0 :         krb5_data data;
     903             : 
     904           0 :         GSSAPI_KRB5_INIT(&context);
     905           0 :         if (authenticated)
     906           0 :             *authenticated = nameattrs->kdc_issued_verified;
     907             : 
     908           0 :         kret = _krb5_get_ad(context, ticket->authorization_data,
     909             :                             NULL, KRB5_AUTHDATA_KDC_ISSUED,
     910             :                             value ? &data : NULL);
     911           0 :         if (value) {
     912           0 :             value->length = data.length;
     913           0 :             value->value = data.data;
     914             :         }
     915           0 :         if (kret == ENOENT)
     916           0 :             return GSS_S_UNAVAILABLE;
     917           0 :         *minor_status = kret;
     918           0 :         return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
     919           0 :     } else if (frag->length) {
     920           0 :         return GSS_S_UNAVAILABLE;
     921             :     }
     922             : 
     923             :     /* Just because it's in the Ticket doesn't make it authenticated */
     924           0 :     if (authenticated)
     925           0 :         *authenticated = 0;
     926             : 
     927           0 :     if (value) {
     928           0 :         ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length,
     929             :                            ticket->authorization_data, &sz, kret);
     930           0 :         *minor_status = kret;
     931             :     }
     932           0 :     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
     933             : }
     934             : 
     935             : static OM_uint32
     936           0 : get_authenticator_authz_data(OM_uint32 *minor_status,
     937             :                              const CompositePrincipal *name,
     938             :                              gss_const_buffer_t prefix,
     939             :                              gss_const_buffer_t attr,
     940             :                              gss_const_buffer_t frag,
     941             :                              int *authenticated,
     942             :                              int *complete,
     943             :                              gss_buffer_t value,
     944             :                              gss_buffer_t display_value,
     945             :                              int *more)
     946             : {
     947           0 :     krb5_error_code kret = 0;
     948           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
     949           0 :     size_t sz;
     950             : 
     951           0 :     if (!nameattrs || !nameattrs->authenticator_ad)
     952           0 :         return GSS_S_UNAVAILABLE;
     953           0 :     if (authenticated)
     954           0 :         *authenticated = 0;
     955           0 :     if (complete)
     956           0 :         *complete = 1;
     957             : 
     958           0 :     if (value) {
     959           0 :         ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length,
     960             :                            nameattrs->authenticator_ad, &sz, kret);
     961           0 :         *minor_status = kret;
     962             :     }
     963           0 :     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
     964             : }
     965             : 
     966             : static OM_uint32
     967           0 : set_authenticator_authz_data(OM_uint32 *minor_status,
     968             :                              CompositePrincipal *name,
     969             :                              gss_const_buffer_t prefix,
     970             :                              gss_const_buffer_t attr,
     971             :                              gss_const_buffer_t frag,
     972             :                              int complete,
     973             :                              gss_buffer_t value)
     974             : {
     975           0 :     AuthorizationDataElement e;
     976           0 :     krb5_error_code kret;
     977           0 :     size_t sz;
     978             : 
     979           0 :     if (!value)
     980           0 :         return GSS_S_CALL_INACCESSIBLE_READ;
     981           0 :     if (frag->length &&
     982           0 :         !ATTR_EQ(frag, "if-relevant"))
     983           0 :         return GSS_S_UNAVAILABLE;
     984             : 
     985           0 :     if ((name->nameattrs == NULL &&
     986           0 :         (name->nameattrs = calloc(1, sizeof(*name->nameattrs))) == NULL) ||
     987           0 :         (name->nameattrs->want_ad == NULL &&
     988           0 :          (name->nameattrs->want_ad =
     989           0 :           calloc(1, sizeof(*name->nameattrs->want_ad))) == NULL)) {
     990           0 :         *minor_status = ENOMEM;
     991           0 :         return GSS_S_FAILURE;
     992             :     }
     993             : 
     994           0 :     memset(&e, 0, sizeof(e));
     995           0 :     kret = decode_AuthorizationDataElement(value->value, value->length, &e,
     996             :                                            &sz);
     997           0 :     if (kret == 0) {
     998           0 :         if (frag->length) {
     999           0 :             AuthorizationData ir;
    1000             : 
    1001           0 :             ir.len = 0;
    1002           0 :             ir.val = NULL;
    1003           0 :             kret = add_AuthorizationData(&ir, &e);
    1004           0 :             free_AuthorizationDataElement(&e);
    1005           0 :             if (kret == 0) {
    1006           0 :                 e.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
    1007           0 :                 ASN1_MALLOC_ENCODE(AuthorizationData, e.ad_data.data,
    1008             :                                    e.ad_data.length, &ir, &sz, kret);
    1009           0 :                 kret = add_AuthorizationData(name->nameattrs->want_ad, &e);
    1010             :             }
    1011           0 :             free_AuthorizationData(&ir);
    1012             :         } else {
    1013           0 :             kret = add_AuthorizationData(name->nameattrs->want_ad, &e);
    1014           0 :             free_AuthorizationDataElement(&e);
    1015             :         }
    1016             :     }
    1017             : 
    1018           0 :     *minor_status = kret;
    1019           0 :     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
    1020             : }
    1021             : 
    1022             : static OM_uint32
    1023           0 : get_transited(OM_uint32 *minor_status,
    1024             :               const CompositePrincipal *name,
    1025             :               gss_const_buffer_t prefix,
    1026             :               gss_const_buffer_t attr,
    1027             :               gss_const_buffer_t frag,
    1028             :               int *authenticated,
    1029             :               int *complete,
    1030             :               gss_buffer_t value,
    1031             :               gss_buffer_t display_value,
    1032             :               int *more)
    1033             : {
    1034           0 :     krb5_error_code kret = 0;
    1035           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
    1036           0 :     PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
    1037           0 :     EncTicketPart *ticket = NULL;
    1038           0 :     size_t sz;
    1039             : 
    1040           0 :     if (src) switch (src->element) {
    1041           0 :     case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
    1042           0 :         break;
    1043           0 :     case choice_PrincipalNameAttrSrc_enc_ticket_part:
    1044           0 :         ticket = &src->u.enc_ticket_part;
    1045           0 :         break;
    1046           0 :     default:
    1047           0 :         return GSS_S_UNAVAILABLE;
    1048             :     }
    1049             : 
    1050           0 :     if (!nameattrs && !ticket)
    1051           0 :         return GSS_S_UNAVAILABLE;
    1052           0 :     if (nameattrs && !nameattrs->transited && !ticket)
    1053           0 :         return GSS_S_UNAVAILABLE;
    1054             : 
    1055           0 :     if (authenticated)
    1056           0 :         *authenticated = 1;
    1057           0 :     if (complete)
    1058           0 :         *complete = 1;
    1059             : 
    1060           0 :     if (value && ticket)
    1061           0 :         ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length,
    1062             :                            &ticket->transited, &sz, kret);
    1063           0 :     else if (value && nameattrs->transited)
    1064           0 :         ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length,
    1065             :                            nameattrs->transited, &sz, kret);
    1066           0 :     *minor_status = kret;
    1067           0 :     return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
    1068             : }
    1069             : 
    1070             : static OM_uint32
    1071           0 : get_canonical_name(OM_uint32 *minor_status,
    1072             :                    const CompositePrincipal *name,
    1073             :                    gss_const_buffer_t prefix,
    1074             :                    gss_const_buffer_t attr,
    1075             :                    gss_const_buffer_t frag,
    1076             :                    int *authenticated,
    1077             :                    int *complete,
    1078             :                    gss_buffer_t value,
    1079             :                    gss_buffer_t display_value,
    1080             :                    int *more)
    1081             : {
    1082           0 :     krb5_error_code kret = 0;
    1083           0 :     PrincipalNameAttrs *nameattrs = name->nameattrs;
    1084           0 :     PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
    1085           0 :     krb5_principal p = NULL;
    1086           0 :     krb5_context context;
    1087           0 :     EncTicketPart *ticket = NULL;
    1088           0 :     EncKDCRepPart *kdcrep = NULL;
    1089             : 
    1090           0 :     if (src) switch (src->element) {
    1091           0 :     case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
    1092           0 :         kdcrep = &src->u.enc_kdc_rep_part;
    1093           0 :         break;
    1094           0 :     case choice_PrincipalNameAttrSrc_enc_ticket_part:
    1095           0 :         ticket = &src->u.enc_ticket_part;
    1096           0 :         break;
    1097           0 :     default:
    1098           0 :         return GSS_S_UNAVAILABLE;
    1099             :     }
    1100             : 
    1101           0 :     GSSAPI_KRB5_INIT(&context);
    1102             : 
    1103           0 :     if (authenticated)
    1104           0 :         *authenticated = 1;
    1105           0 :     if (complete)
    1106           0 :         *complete = 1;
    1107             : 
    1108           0 :     if (kdcrep) {
    1109           0 :         kret = _krb5_principalname2krb5_principal(context, &p,
    1110             :                                                   kdcrep->sname,
    1111             :                                                   kdcrep->srealm);
    1112           0 :     } else if (nameattrs && nameattrs->pac &&
    1113           0 :         (_krb5_pac_get_canon_principal(context, nameattrs->pac, &p)) == 0) {
    1114           0 :         if (authenticated)
    1115           0 :             *authenticated = nameattrs->pac_verified;
    1116           0 :     } else if (ticket) {
    1117           0 :         krb5_data data;
    1118           0 :         krb5_pac pac = NULL;
    1119             : 
    1120           0 :         krb5_data_zero(&data);
    1121             : 
    1122             :         /* Use canonical name from PAC if available */
    1123           0 :         kret = _krb5_get_ad(context, ticket->authorization_data,
    1124             :                             NULL, KRB5_AUTHDATA_WIN2K_PAC, &data);
    1125           0 :         if (kret == 0)
    1126           0 :             kret = krb5_pac_parse(context, data.data, data.length, &pac);
    1127           0 :         if (kret == 0)
    1128           0 :             kret = _krb5_pac_get_canon_principal(context, pac, &p);
    1129           0 :         if (kret == 0 && authenticated)
    1130           0 :             *authenticated = nameattrs->pac_verified;
    1131           0 :         else if (kret == ENOENT)
    1132           0 :             kret = _krb5_principalname2krb5_principal(context, &p,
    1133             :                                                       ticket->cname,
    1134             :                                                       ticket->crealm);
    1135             : 
    1136           0 :         krb5_data_free(&data);
    1137           0 :         krb5_pac_free(context, pac);
    1138             :     } else
    1139           0 :         return GSS_S_UNAVAILABLE;
    1140           0 :     if (kret == 0 && value) {
    1141           0 :         OM_uint32 major;
    1142             :         /*
    1143             :          * Value is exported name token (exported composite name token
    1144             :          * should also work).
    1145             :          */
    1146           0 :         major = _gsskrb5_export_name(minor_status, (gss_name_t)p, value);
    1147           0 :         if (major != GSS_S_COMPLETE) {
    1148           0 :             krb5_free_principal(context, p);
    1149           0 :             return major;
    1150             :         }
    1151             :     }
    1152           0 :     if (kret == 0 && display_value) {
    1153             :         /* Display value is principal name display form */
    1154           0 :         kret = krb5_unparse_name(context, p,
    1155           0 :                                  (char **)&display_value->value);
    1156           0 :         if (kret == 0)
    1157           0 :             display_value->length = strlen(display_value->value);
    1158             :     }
    1159             : 
    1160           0 :     krb5_free_principal(context, p);
    1161           0 :     if (kret) {
    1162           0 :         if (value) {
    1163           0 :             free(value->value);
    1164           0 :             value->length = 0;
    1165           0 :             value->value = NULL;
    1166             :         }
    1167           0 :         *minor_status = kret;
    1168           0 :         return GSS_S_UNAVAILABLE;
    1169             :     }
    1170           0 :     return GSS_S_COMPLETE;
    1171             : }

Generated by: LCOV version 1.14