LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/krb5 - transited.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 106 397 26.7 %
Date: 2024-04-21 15:09:00 Functions: 7 15 46.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2001, 2003 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 "krb5_locl.h"
      35             : 
      36             : /* this is an attempt at one of the most horrible `compression'
      37             :    schemes that has ever been invented; it's so amazingly brain-dead
      38             :    that words can not describe it, and all this just to save a few
      39             :    silly bytes */
      40             : 
      41             : struct tr_realm {
      42             :     char *realm;
      43             :     unsigned leading_space:1;
      44             :     unsigned leading_slash:1;
      45             :     unsigned trailing_dot:1;
      46             :     struct tr_realm *next;
      47             : };
      48             : 
      49             : static void
      50           0 : free_realms(struct tr_realm *r)
      51             : {
      52           0 :     struct tr_realm *p;
      53           0 :     while(r){
      54           0 :         p = r;
      55           0 :         r = r->next;
      56           0 :         free(p->realm);
      57           0 :         free(p);
      58             :     }
      59           0 : }
      60             : 
      61             : static int
      62           0 : make_path(krb5_context context, struct tr_realm *r,
      63             :           const char *from, const char *to)
      64             : {
      65           0 :     struct tr_realm *tmp;
      66           0 :     const char *p;
      67             : 
      68           0 :     if(strlen(from) < strlen(to)){
      69           0 :         const char *str;
      70           0 :         str = from;
      71           0 :         from = to;
      72           0 :         to = str;
      73             :     }
      74             : 
      75           0 :     if(strcmp(from + strlen(from) - strlen(to), to) == 0){
      76           0 :         p = from;
      77           0 :         while(1){
      78           0 :             p = strchr(p, '.');
      79           0 :             if(p == NULL) {
      80           0 :                 krb5_clear_error_message (context);
      81           0 :                 return KRB5KDC_ERR_POLICY;
      82             :             }
      83           0 :             p++;
      84           0 :             if(strcmp(p, to) == 0)
      85           0 :                 break;
      86           0 :             tmp = calloc(1, sizeof(*tmp));
      87           0 :             if(tmp == NULL)
      88           0 :                 return krb5_enomem(context);
      89           0 :             tmp->next = r->next;
      90           0 :             r->next = tmp;
      91           0 :             tmp->realm = strdup(p);
      92           0 :             if(tmp->realm == NULL){
      93           0 :                 r->next = tmp->next;
      94           0 :                 free(tmp);
      95           0 :                 return krb5_enomem(context);
      96             :             }
      97             :         }
      98           0 :     }else if(strncmp(from, to, strlen(to)) == 0){
      99           0 :         p = from + strlen(from);
     100           0 :         while(1){
     101           0 :             while(p >= from && *p != '/') p--;
     102           0 :             if(p == from)
     103           0 :                 return KRB5KDC_ERR_POLICY;
     104             : 
     105           0 :             if(strncmp(to, from, p - from) == 0)
     106           0 :                 break;
     107           0 :             tmp = calloc(1, sizeof(*tmp));
     108           0 :             if(tmp == NULL)
     109           0 :                 return krb5_enomem(context);
     110           0 :             tmp->next = r->next;
     111           0 :             r->next = tmp;
     112           0 :             tmp->realm = malloc(p - from + 1);
     113           0 :             if(tmp->realm == NULL){
     114           0 :                 r->next = tmp->next;
     115           0 :                 free(tmp);
     116           0 :                 return krb5_enomem(context);
     117             :             }
     118           0 :             memcpy(tmp->realm, from, p - from);
     119           0 :             tmp->realm[p - from] = '\0';
     120           0 :             p--;
     121             :         }
     122             :     } else {
     123           0 :         krb5_clear_error_message (context);
     124           0 :         return KRB5KDC_ERR_POLICY;
     125             :     }
     126             : 
     127           0 :     return 0;
     128             : }
     129             : 
     130             : static int
     131           0 : make_paths(krb5_context context,
     132             :            struct tr_realm *realms, const char *client_realm,
     133             :            const char *server_realm)
     134             : {
     135           0 :     struct tr_realm *r;
     136           0 :     int ret;
     137           0 :     const char *prev_realm = client_realm;
     138           0 :     const char *next_realm = NULL;
     139           0 :     for(r = realms; r; r = r->next){
     140             :         /* it *might* be that you can have more than one empty
     141             :            component in a row, at least that's how I interpret the
     142             :            "," exception in 1510 */
     143           0 :         if(r->realm[0] == '\0'){
     144           0 :             while(r->next && r->next->realm[0] == '\0')
     145           0 :                 r = r->next;
     146           0 :             if(r->next)
     147           0 :                 next_realm = r->next->realm;
     148             :             else
     149           0 :                 next_realm = server_realm;
     150           0 :             ret = make_path(context, r, prev_realm, next_realm);
     151           0 :             if(ret){
     152           0 :                 free_realms(realms);
     153           0 :                 return ret;
     154             :             }
     155             :         }
     156           0 :         prev_realm = r->realm;
     157             :     }
     158           0 :     return 0;
     159             : }
     160             : 
     161             : static int
     162           0 : expand_realms(krb5_context context,
     163             :               struct tr_realm *realms, const char *client_realm)
     164             : {
     165           0 :     struct tr_realm *r;
     166           0 :     const char *prev_realm = NULL;
     167           0 :     for(r = realms; r; r = r->next){
     168           0 :         if(r->trailing_dot){
     169           0 :             char *tmp;
     170           0 :             size_t len;
     171             : 
     172           0 :             if(prev_realm == NULL)
     173           0 :                 prev_realm = client_realm;
     174             : 
     175           0 :             len = strlen(r->realm) + strlen(prev_realm) + 1;
     176             : 
     177           0 :             tmp = realloc(r->realm, len);
     178           0 :             if(tmp == NULL){
     179           0 :                 free_realms(realms);
     180           0 :                 return krb5_enomem(context);
     181             :             }
     182           0 :             r->realm = tmp;
     183           0 :             strlcat(r->realm, prev_realm, len);
     184           0 :         }else if(r->leading_slash && !r->leading_space && prev_realm){
     185             :             /* yet another exception: if you use x500-names, the
     186             :                leading realm doesn't have to be "quoted" with a space */
     187           0 :             char *tmp;
     188           0 :             size_t len = strlen(r->realm) + strlen(prev_realm) + 1;
     189             : 
     190           0 :             tmp = malloc(len);
     191           0 :             if(tmp == NULL){
     192           0 :                 free_realms(realms);
     193           0 :                 return krb5_enomem(context);
     194             :             }
     195           0 :             strlcpy(tmp, prev_realm, len);
     196           0 :             strlcat(tmp, r->realm, len);
     197           0 :             free(r->realm);
     198           0 :             r->realm = tmp;
     199             :         }
     200           0 :         prev_realm = r->realm;
     201             :     }
     202           0 :     return 0;
     203             : }
     204             : 
     205             : static struct tr_realm *
     206           0 : make_realm(char *realm)
     207             : {
     208           0 :     struct tr_realm *r;
     209           0 :     char *p, *q;
     210           0 :     int quote = 0;
     211           0 :     r = calloc(1, sizeof(*r));
     212           0 :     if(r == NULL){
     213           0 :         free(realm);
     214           0 :         return NULL;
     215             :     }
     216           0 :     r->realm = realm;
     217           0 :     for(p = q = r->realm; *p; p++){
     218           0 :         if(p == r->realm && *p == ' '){
     219           0 :             r->leading_space = 1;
     220           0 :             continue;
     221             :         }
     222           0 :         if(q == r->realm && *p == '/')
     223           0 :             r->leading_slash = 1;
     224           0 :         if(quote){
     225           0 :             *q++ = *p;
     226           0 :             quote = 0;
     227           0 :             continue;
     228             :         }
     229           0 :         if(*p == '\\'){
     230           0 :             quote = 1;
     231           0 :             continue;
     232             :         }
     233           0 :         if(p[0] == '.' && p[1] == '\0')
     234           0 :             r->trailing_dot = 1;
     235           0 :         *q++ = *p;
     236             :     }
     237           0 :     *q = '\0';
     238           0 :     return r;
     239             : }
     240             : 
     241             : static struct tr_realm*
     242           0 : append_realm(struct tr_realm *head, struct tr_realm *r)
     243             : {
     244           0 :     struct tr_realm *p;
     245           0 :     if(head == NULL){
     246           0 :         r->next = NULL;
     247           0 :         return r;
     248             :     }
     249           0 :     p = head;
     250           0 :     while(p->next) p = p->next;
     251           0 :     p->next = r;
     252           0 :     return head;
     253             : }
     254             : 
     255             : static int
     256           0 : decode_realms(krb5_context context,
     257             :               const char *tr, int length, struct tr_realm **realms)
     258             : {
     259           0 :     struct tr_realm *r = NULL;
     260             : 
     261           0 :     char *tmp;
     262           0 :     int quote = 0;
     263           0 :     const char *start = tr;
     264           0 :     int i;
     265             : 
     266           0 :     for(i = 0; i < length; i++){
     267           0 :         if(quote){
     268           0 :             quote = 0;
     269           0 :             continue;
     270             :         }
     271           0 :         if(tr[i] == '\\'){
     272           0 :             quote = 1;
     273           0 :             continue;
     274             :         }
     275           0 :         if(tr[i] == ','){
     276           0 :             tmp = malloc(tr + i - start + 1);
     277           0 :             if(tmp == NULL) {
     278           0 :                 free_realms(*realms);
     279           0 :                 *realms = NULL;
     280           0 :                 return krb5_enomem(context);
     281             :             }
     282           0 :             memcpy(tmp, start, tr + i - start);
     283           0 :             tmp[tr + i - start] = '\0';
     284           0 :             r = make_realm(tmp);
     285           0 :             if(r == NULL){
     286           0 :                 free_realms(*realms);
     287           0 :                 *realms = NULL;
     288           0 :                 return krb5_enomem(context);
     289             :             }
     290           0 :             *realms = append_realm(*realms, r);
     291           0 :             start = tr + i + 1;
     292             :         }
     293             :     }
     294           0 :     tmp = malloc(tr + i - start + 1);
     295           0 :     if(tmp == NULL){
     296           0 :         free_realms(*realms);
     297           0 :         *realms = NULL;
     298           0 :         return krb5_enomem(context);
     299             :     }
     300           0 :     memcpy(tmp, start, tr + i - start);
     301           0 :     tmp[tr + i - start] = '\0';
     302           0 :     r = make_realm(tmp);
     303           0 :     if(r == NULL){
     304           0 :         free_realms(*realms);
     305           0 :         *realms = NULL;
     306           0 :         return krb5_enomem(context);
     307             :     }
     308           0 :     *realms = append_realm(*realms, r);
     309             : 
     310           0 :     return 0;
     311             : }
     312             : 
     313             : 
     314             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     315       49297 : krb5_domain_x500_decode(krb5_context context,
     316             :                         krb5_data tr, char ***realms, unsigned int *num_realms,
     317             :                         const char *client_realm, const char *server_realm)
     318             : {
     319       49297 :     struct tr_realm *r = NULL;
     320        1658 :     struct tr_realm *p, **q;
     321        1658 :     int ret;
     322             : 
     323       49297 :     if(tr.length == 0) {
     324       49297 :         *realms = NULL;
     325       49297 :         *num_realms = 0;
     326       49297 :         return 0;
     327             :     }
     328             : 
     329             :     /* split string in components */
     330           0 :     ret = decode_realms(context, tr.data, tr.length, &r);
     331           0 :     if(ret)
     332           0 :         return ret;
     333             : 
     334             :     /* apply prefix rule */
     335           0 :     ret = expand_realms(context, r, client_realm);
     336           0 :     if(ret)
     337           0 :         return ret;
     338             : 
     339           0 :     ret = make_paths(context, r, client_realm, server_realm);
     340           0 :     if(ret)
     341           0 :         return ret;
     342             : 
     343             :     /* remove empty components and count realms */
     344           0 :     *num_realms = 0;
     345           0 :     for(q = &r; *q; ){
     346           0 :         if((*q)->realm[0] == '\0'){
     347           0 :             p = *q;
     348           0 :             *q = (*q)->next;
     349           0 :             free(p->realm);
     350           0 :             free(p);
     351             :         }else{
     352           0 :             q = &(*q)->next;
     353           0 :             (*num_realms)++;
     354             :         }
     355             :     }
     356           0 :     if (*num_realms + 1 > UINT_MAX/sizeof(**realms))
     357           0 :         return ERANGE;
     358             : 
     359             :     {
     360           0 :         char **R;
     361           0 :         R = malloc((*num_realms + 1) * sizeof(*R));
     362           0 :         *realms = R;
     363           0 :         while(r){
     364           0 :             *R++ = r->realm;
     365           0 :             p = r->next;
     366           0 :             free(r);
     367           0 :             r = p;
     368             :         }
     369           0 :         if (*realms == NULL)
     370           0 :             return krb5_enomem(context);
     371             :     }
     372           0 :     return 0;
     373             : }
     374             : 
     375             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     376       49297 : krb5_domain_x500_encode(char **realms, unsigned int num_realms,
     377             :                         krb5_data *encoding)
     378             : {
     379       49297 :     char *s = NULL;
     380       49297 :     int len = 0;
     381        1658 :     unsigned int i;
     382       49297 :     krb5_data_zero(encoding);
     383       49297 :     if (num_realms == 0)
     384       47639 :         return 0;
     385           0 :     for(i = 0; i < num_realms; i++){
     386           0 :         len += strlen(realms[i]);
     387           0 :         if(realms[i][0] == '/')
     388           0 :             len++;
     389             :     }
     390           0 :     len += num_realms - 1;
     391           0 :     s = malloc(len + 1);
     392           0 :     if (s == NULL)
     393           0 :         return ENOMEM;
     394           0 :     *s = '\0';
     395           0 :     for(i = 0; i < num_realms; i++){
     396           0 :         if(i)
     397           0 :             strlcat(s, ",", len + 1);
     398           0 :         if(realms[i][0] == '/')
     399           0 :             strlcat(s, " ", len + 1);
     400           0 :         strlcat(s, realms[i], len + 1);
     401             :     }
     402           0 :     encoding->data = s;
     403           0 :     encoding->length = strlen(s);
     404           0 :     return 0;
     405             : }
     406             : 
     407             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
     408      100453 : _krb5_free_capath(krb5_context context, char **capath)
     409             : {
     410        3316 :     char **s;
     411             : 
     412      100609 :     for (s = capath; s && *s; ++s)
     413         156 :         free(*s);
     414      100453 :     free(capath);
     415      100453 : }
     416             : 
     417             : struct hier_iter {
     418             :     const char *local_realm;
     419             :     const char *server_realm;
     420             :     const char *lr;     /* Pointer into tail of local realm */
     421             :     const char *sr;     /* Pointer into tail of server realm */
     422             :     size_t llen;        /* Length of local_realm */
     423             :     size_t slen;        /* Length of server_realm */
     424             :     size_t len;         /* Length of common suffix */
     425             :     size_t num;         /* Path element count */
     426             : };
     427             : 
     428             : /*
     429             :  * Step up from local_realm to common suffix, or else down to server_realm.
     430             :  */
     431             : static const char *
     432         416 : hier_next(struct hier_iter *state)
     433             : {
     434         416 :     const char *lr = state->lr;
     435         416 :     const char *sr = state->sr;
     436         416 :     const char *lsuffix = state->local_realm + state->llen - state->len;
     437         416 :     const char *server_realm = state->server_realm;
     438             : 
     439         416 :     if (lr != NULL) {
     440        1344 :         while (lr < lsuffix)
     441        1240 :             if (*lr++ == '.')
     442         190 :                 return state->lr = lr;
     443         104 :         state->lr = NULL;
     444             :     }
     445         226 :     if (sr != NULL) {
     446        1252 :         while (--sr >= server_realm)
     447        1148 :             if (sr == server_realm || sr[-1] == '.')
     448         122 :                 return state->sr = sr;
     449         104 :         state->sr = NULL;
     450             :     }
     451         104 :     return NULL;
     452             : }
     453             : 
     454             : static void
     455       49297 : hier_init(struct hier_iter *state, const char *local_realm, const char *server_realm)
     456             : {
     457        1658 :     size_t llen;
     458        1658 :     size_t slen;
     459       49297 :     size_t len = 0;
     460        1658 :     const char *lr;
     461        1658 :     const char *sr;
     462             : 
     463       49297 :     state->local_realm = local_realm;
     464       49297 :     state->server_realm = server_realm;
     465       49297 :     state->llen = llen = strlen(local_realm);
     466       49297 :     state->slen = slen = strlen(server_realm);
     467       49297 :     state->len = 0;
     468       49297 :     state->num = 0;
     469             : 
     470       49297 :     if (slen == 0 || llen == 0)
     471           0 :         return;
     472             : 
     473             :     /* Find first difference from the back */
     474       49297 :     for (lr = local_realm + llen, sr = server_realm + slen;
     475     1100093 :          lr != local_realm && sr != server_realm;
     476     1050796 :          --lr, --sr) {
     477     1050855 :         if (lr[-1] != sr[-1])
     478          59 :             break;
     479     1050796 :         if (lr[-1] == '.')
     480      123286 :             len = llen - (lr - local_realm);
     481             :     }
     482             : 
     483             :     /* Nothing in common? */
     484       49297 :     if (*lr == '\0')
     485           7 :         return;
     486             : 
     487             :     /* Everything in common? */
     488       49290 :     if (llen == slen && lr == local_realm)
     489       47580 :         return;
     490             : 
     491             :     /* Is one realm is a suffix of the other? */
     492          52 :     if ((llen < slen && lr == local_realm && sr[-1] == '.') ||
     493          25 :         (llen > slen && sr == server_realm && lr[-1] == '.'))
     494           0 :         len = llen - (lr - local_realm);
     495             : 
     496          52 :     state->len = len;
     497             :     /* `lr` starts at local realm and walks up the tree to common suffix */
     498          52 :     state->lr = local_realm;
     499             :     /* `sr` starts at common suffix in server realm and walks down the tree */
     500          52 :     state->sr = server_realm + slen - len;
     501             : 
     502             :     /* Count elements and reset */
     503         208 :     while (hier_next(state) != NULL)
     504         156 :         ++state->num;
     505          52 :     state->lr = local_realm;
     506          52 :     state->sr = server_realm + slen - len;
     507             : }
     508             : 
     509             : /*
     510             :  * Find a referral path from client_realm to server_realm via local_realm.
     511             :  * Either via [capaths] or hierarchicaly.
     512             :  */
     513             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     514       49297 : _krb5_find_capath(krb5_context context,
     515             :                   const char *client_realm,
     516             :                   const char *local_realm,
     517             :                   const char *server_realm,
     518             :                   krb5_boolean use_hierarchical,
     519             :                   char ***rpath,
     520             :                   size_t *npath)
     521             : {
     522        1658 :     char **confpath;
     523        1658 :     char **capath;
     524        1658 :     struct hier_iter hier_state;
     525        1658 :     char **rp;
     526        1658 :     const char *r;
     527             : 
     528       49297 :     *rpath = NULL;
     529       49297 :     *npath = 0;
     530             : 
     531       49297 :     confpath = krb5_config_get_strings(context, NULL, "capaths",
     532             :                                        client_realm, server_realm, NULL);
     533       49297 :     if (confpath == NULL)
     534       49297 :         confpath = krb5_config_get_strings(context, NULL, "capaths",
     535             :                                            local_realm, server_realm, NULL);
     536             :     /*
     537             :      * With a [capaths] setting from the client to the server we look for our
     538             :      * own realm in the list.  If our own realm is not present, we return the
     539             :      * full list.  Otherwise, we return our realm's successors, or possibly
     540             :      * NULL.  Ignoring a [capaths] settings risks loops plus would violate
     541             :      * explicit policy and the principle of least surpise.
     542             :      */
     543       49297 :     if (confpath != NULL) {
     544           0 :         char **start = confpath;
     545             :         size_t i;
     546             :         size_t n;
     547             : 
     548           0 :         for (rp = start; *rp; rp++)
     549           0 :             if (strcmp(*rp, local_realm) == 0)
     550           0 :                 start = rp+1;
     551           0 :         n = rp - start;
     552             : 
     553           0 :         if (n == 0) {
     554           0 :             krb5_config_free_strings(confpath);
     555           0 :             return 0;
     556             :         }
     557             : 
     558           0 :         capath = calloc(n + 1, sizeof(*capath));
     559           0 :         if (capath == NULL) {
     560           0 :             krb5_config_free_strings(confpath);
     561           0 :             return krb5_enomem(context);
     562             :         }
     563             : 
     564           0 :         for (i = 0, rp = start; *rp; rp++) {
     565           0 :             if ((capath[i++] = strdup(*rp)) == NULL) {
     566           0 :                 _krb5_free_capath(context, capath);
     567           0 :                 krb5_config_free_strings(confpath);
     568           0 :                 return krb5_enomem(context);
     569             :             }
     570             :         }
     571           0 :         krb5_config_free_strings(confpath);
     572           0 :         capath[i] = NULL;
     573           0 :         *rpath = capath;
     574           0 :         *npath = n;
     575           0 :         return 0;
     576             :     }
     577             : 
     578             :     /* The use_hierarchical flag makes hierarchical path lookup unconditional */
     579       98594 :     if (! use_hierarchical &&
     580       49297 :         ! krb5_config_get_bool_default(context, NULL, TRUE, "libdefaults",
     581             :                                        "allow_hierarchical_capaths", NULL))
     582           0 :         return 0;
     583             : 
     584             :     /*
     585             :      * When validating transit paths, local_realm == client_realm.  Otherwise,
     586             :      * with hierarchical referrals, they may differ, and we may be building a
     587             :      * path forward from our own realm!
     588             :      */
     589       49297 :     hier_init(&hier_state, local_realm, server_realm);
     590       49297 :     if (hier_state.num == 0)
     591       47587 :         return 0;
     592             : 
     593          52 :     rp = capath = calloc(hier_state.num + 1, sizeof(*capath));
     594          52 :     if (capath == NULL)
     595           0 :         return krb5_enomem(context);
     596         208 :     while ((r = hier_next(&hier_state)) != NULL) {
     597         156 :         if ((*rp++ = strdup(r)) == NULL) {
     598           0 :             _krb5_free_capath(context, capath);
     599           0 :             return krb5_enomem(context);
     600             :         }
     601             :     }
     602             : 
     603          52 :     *rp = NULL;
     604          52 :     *rpath = capath;
     605          52 :     *npath = hier_state.num;
     606          52 :     return 0;
     607             : }
     608             : 
     609             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     610       49297 : krb5_check_transited(krb5_context context,
     611             :                      krb5_const_realm client_realm,
     612             :                      krb5_const_realm server_realm,
     613             :                      krb5_realm *realms,
     614             :                      unsigned int num_realms,
     615             :                      int *bad_realm)
     616             : {
     617       49297 :     krb5_error_code ret = 0;
     618       49297 :     char **capath = NULL;
     619       49297 :     size_t num_capath = 0;
     620       49297 :     size_t i = 0;
     621       49297 :     size_t j = 0;
     622             : 
     623             :     /* In transit checks hierarchical capaths are optional */
     624       49297 :     ret = _krb5_find_capath(context, client_realm, client_realm, server_realm,
     625             :                             FALSE, &capath, &num_capath);
     626       49297 :     if (ret)
     627           0 :         return ret;
     628             : 
     629       49297 :     for (i = 0; i < num_realms; i++) {
     630           0 :         for (j = 0; j < num_capath && capath[j]; ++j) {
     631             :             /* `capath[j]' can't be NULL, but compilers be dumb */
     632           0 :             if (strcmp(realms[i], capath[j]) == 0)
     633           0 :                 break;
     634             :         }
     635           0 :         if (j == num_capath || !capath[j]) {
     636           0 :             _krb5_free_capath(context, capath);
     637           0 :             krb5_set_error_message (context, KRB5KRB_AP_ERR_ILL_CR_TKT,
     638           0 :                                     N_("no transit allowed "
     639             :                                        "through realm %s from %s to %s", ""),
     640           0 :                                        realms[i], client_realm, server_realm);
     641           0 :             if (bad_realm)
     642           0 :                 *bad_realm = i;
     643           0 :             return KRB5KRB_AP_ERR_ILL_CR_TKT;
     644             :         }
     645             :     }
     646             : 
     647       49297 :     _krb5_free_capath(context, capath);
     648       49297 :     return 0;
     649             : }
     650             : 
     651             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     652           0 : krb5_check_transited_realms(krb5_context context,
     653             :                             const char *const *realms,
     654             :                             unsigned int num_realms,
     655             :                             int *bad_realm)
     656             : {
     657           0 :     size_t i;
     658           0 :     int ret = 0;
     659           0 :     char **bad_realms = krb5_config_get_strings(context, NULL,
     660             :                                                 "libdefaults",
     661             :                                                 "transited_realms_reject",
     662             :                                                 NULL);
     663           0 :     if(bad_realms == NULL)
     664           0 :         return 0;
     665             : 
     666           0 :     for(i = 0; i < num_realms; i++) {
     667             :         char **p;
     668           0 :         for(p = bad_realms; *p; p++)
     669           0 :             if(strcmp(*p, realms[i]) == 0) {
     670           0 :                 ret = KRB5KRB_AP_ERR_ILL_CR_TKT;
     671           0 :                 krb5_set_error_message (context, ret,
     672           0 :                                         N_("no transit allowed "
     673             :                                            "through realm %s", ""),
     674             :                                         *p);
     675           0 :                 if(bad_realm)
     676           0 :                     *bad_realm = i;
     677           0 :                 break;
     678             :             }
     679             :     }
     680           0 :     krb5_config_free_strings(bad_realms);
     681           0 :     return ret;
     682             : }
     683             : 
     684             : #if 0
     685             : int
     686             : main(int argc, char **argv)
     687             : {
     688             :     krb5_data x;
     689             :     char **r;
     690             :     int num, i;
     691             :     x.data = argv[1];
     692             :     x.length = strlen(x.data);
     693             :     if(domain_expand(x, &r, &num, argv[2], argv[3]))
     694             :         exit(1);
     695             :     for(i = 0; i < num; i++)
     696             :         printf("%s\n", r[i]);
     697             :     return 0;
     698             : }
     699             : #endif

Generated by: LCOV version 1.14