LCOV - code coverage report
Current view: top level - util - sss_krb5.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 164 378 43.4 %
Date: 2015-10-19 Functions: 9 25 36.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Sumit Bose <sbose@redhat.com>
       4             : 
       5             :     Copyright (C) 2009-2010 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : #include <stdio.h>
      21             : #include <errno.h>
      22             : #include <talloc.h>
      23             : #include <profile.h>
      24             : 
      25             : #include "config.h"
      26             : 
      27             : #include "util/util.h"
      28             : #include "util/sss_krb5.h"
      29             : 
      30             : static char *
      31          36 : sss_krb5_get_primary(TALLOC_CTX *mem_ctx,
      32             :                      const char *pattern,
      33             :                      const char *hostname)
      34             : {
      35             :     char *primary;
      36             :     char *dot;
      37             :     char *c;
      38             :     char *shortname;
      39             : 
      40          36 :     if (strcmp(pattern, "%S$") == 0) {
      41           9 :         shortname = talloc_strdup(mem_ctx, hostname);
      42           9 :         if (!shortname) return NULL;
      43             : 
      44           9 :         dot = strchr(shortname, '.');
      45           9 :         if (dot) {
      46           9 :             *dot = '\0';
      47             :         }
      48             : 
      49          55 :         for (c=shortname; *c != '\0'; ++c) {
      50          46 :             *c = toupper(*c);
      51             :         }
      52             : 
      53           9 :         primary = talloc_asprintf(mem_ctx, "%s$", shortname);
      54           9 :         talloc_free(shortname);
      55           9 :         return primary;
      56             :     }
      57             : 
      58          27 :     return talloc_asprintf(mem_ctx, pattern, hostname);
      59             : }
      60             : 
      61          18 : errno_t select_principal_from_keytab(TALLOC_CTX *mem_ctx,
      62             :                                      const char *hostname,
      63             :                                      const char *desired_realm,
      64             :                                      const char *keytab_name,
      65             :                                      char **_principal,
      66             :                                      char **_primary,
      67             :                                      char **_realm)
      68             : {
      69          18 :     krb5_error_code kerr = 0;
      70          18 :     krb5_context krb_ctx = NULL;
      71          18 :     krb5_keytab keytab = NULL;
      72          18 :     krb5_principal client_princ = NULL;
      73             :     TALLOC_CTX *tmp_ctx;
      74          18 :     char *primary = NULL;
      75          18 :     char *realm = NULL;
      76          18 :     int i = 0;
      77             :     errno_t ret;
      78             :     char *principal_string;
      79             :     const char *realm_name;
      80             :     int realm_len;
      81             : 
      82             :     /**
      83             :      * The %s conversion is passed as-is, the %S conversion is translated to
      84             :      * "short host name"
      85             :      *
      86             :      * Priority of lookup:
      87             :      * - our.hostname@REALM or host/our.hostname@REALM depending on the input
      88             :      * - SHORT.HOSTNAME$@REALM (AD domain)
      89             :      * - host/our.hostname@REALM
      90             :      * - foobar$@REALM (AD domain)
      91             :      * - host/foobar@REALM
      92             :      * - host/foo@BAR
      93             :      * - pick the first principal in the keytab
      94             :      */
      95          18 :     const char *primary_patterns[] = {"%s", "%S$", "host/%s", "*$", "host/*",
      96             :                                       "host/*", NULL};
      97          18 :     const char *realm_patterns[] =   {"%s", "%s",  "%s",      "%s", "%s",
      98             :                                       NULL,     NULL};
      99             : 
     100          18 :     DEBUG(SSSDBG_FUNC_DATA,
     101             :           "trying to select the most appropriate principal from keytab\n");
     102          18 :     tmp_ctx = talloc_new(NULL);
     103          18 :     if (!tmp_ctx) {
     104           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n");
     105           0 :         return ENOMEM;
     106             :     }
     107             : 
     108          18 :     kerr = krb5_init_context(&krb_ctx);
     109          18 :     if (kerr) {
     110           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to init kerberos context\n");
     111           0 :         ret = EFAULT;
     112           0 :         goto done;
     113             :     }
     114             : 
     115          18 :     if (keytab_name != NULL) {
     116           9 :         kerr = krb5_kt_resolve(krb_ctx, keytab_name, &keytab);
     117             :     } else {
     118           9 :         kerr = krb5_kt_default(krb_ctx, &keytab);
     119             :     }
     120          18 :     if (kerr) {
     121           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
     122             :               "Failed to read keytab [%s]: %s\n",
     123             :                KEYTAB_CLEAN_NAME,
     124             :                sss_krb5_get_error_message(krb_ctx, kerr));
     125           0 :         ret = EFAULT;
     126           0 :         goto done;
     127             :     }
     128             : 
     129          18 :     if (!desired_realm) {
     130           0 :         desired_realm = "*";
     131             :     }
     132          18 :     if (!hostname) {
     133           0 :         hostname = "*";
     134             :     }
     135             : 
     136             :     do {
     137          36 :         if (primary_patterns[i]) {
     138          36 :             primary = sss_krb5_get_primary(tmp_ctx,
     139             :                                            primary_patterns[i],
     140             :                                            hostname);
     141          36 :             if (primary == NULL) {
     142           0 :                 ret = ENOMEM;
     143           0 :                 goto done;
     144             :             }
     145             :         } else {
     146           0 :             primary = NULL;
     147             :         }
     148          36 :         if (realm_patterns[i]) {
     149          36 :             realm = talloc_asprintf(tmp_ctx, realm_patterns[i], desired_realm);
     150          36 :             if (realm == NULL) {
     151           0 :                 ret = ENOMEM;
     152           0 :                 goto done;
     153             :             }
     154             :         } else {
     155           0 :             realm = NULL;
     156             :         }
     157             : 
     158          36 :         kerr = find_principal_in_keytab(krb_ctx, keytab, primary, realm,
     159             :                                         &client_princ);
     160          36 :         talloc_zfree(primary);
     161          36 :         talloc_zfree(realm);
     162          36 :         if (kerr == 0) {
     163          18 :             break;
     164             :         }
     165          18 :         if (client_princ != NULL) {
     166           0 :             krb5_free_principal(krb_ctx, client_princ);
     167           0 :             client_princ = NULL;
     168             :         }
     169          18 :         i++;
     170          18 :     } while(primary_patterns[i-1] != NULL || realm_patterns[i-1] != NULL);
     171             : 
     172          18 :     if (kerr == 0) {
     173          18 :         if (_principal) {
     174           0 :             kerr = krb5_unparse_name(krb_ctx, client_princ, &principal_string);
     175           0 :             if (kerr) {
     176           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "krb5_unparse_name failed\n");
     177           0 :                 ret = EFAULT;
     178           0 :                 goto done;
     179             :             }
     180             : 
     181           0 :             *_principal = talloc_strdup(mem_ctx, principal_string);
     182           0 :             free(principal_string);
     183           0 :             if (!*_principal) {
     184           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed\n");
     185           0 :                 ret = ENOMEM;
     186           0 :                 goto done;
     187             :             }
     188           0 :             DEBUG(SSSDBG_FUNC_DATA, "Selected principal: %s\n", *_principal);
     189             :         }
     190             : 
     191          18 :         if (_primary) {
     192          18 :             kerr = sss_krb5_unparse_name_flags(krb_ctx, client_princ,
     193             :                                                KRB5_PRINCIPAL_UNPARSE_NO_REALM,
     194             :                                                &principal_string);
     195          18 :             if (kerr) {
     196           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "krb5_unparse_name failed\n");
     197           0 :                 ret = EFAULT;
     198           0 :                 goto done;
     199             :             }
     200             : 
     201          18 :             *_primary = talloc_strdup(mem_ctx, principal_string);
     202          18 :             free(principal_string);
     203          18 :             if (!*_primary) {
     204           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed\n");
     205           0 :                 if (_principal) talloc_zfree(*_principal);
     206           0 :                 ret = ENOMEM;
     207           0 :                 goto done;
     208             :             }
     209          18 :             DEBUG(SSSDBG_FUNC_DATA, "Selected primary: %s\n", *_primary);
     210             :         }
     211             : 
     212          18 :         if (_realm) {
     213          18 :             sss_krb5_princ_realm(krb_ctx, client_princ,
     214             :                                  &realm_name,
     215             :                                  &realm_len);
     216          18 :             if (realm_len == 0) {
     217           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "sss_krb5_princ_realm failed.\n");
     218           0 :                 if (_principal) talloc_zfree(*_principal);
     219           0 :                 if (_primary) talloc_zfree(*_primary);
     220           0 :                 ret = EINVAL;
     221           0 :                 goto done;
     222             :             }
     223             : 
     224          18 :             *_realm = talloc_asprintf(mem_ctx, "%.*s",
     225             :                                       realm_len, realm_name);
     226          18 :             if (!*_realm) {
     227           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed\n");
     228           0 :                 if (_principal) talloc_zfree(*_principal);
     229           0 :                 if (_primary) talloc_zfree(*_primary);
     230           0 :                 ret = ENOMEM;
     231           0 :                 goto done;
     232             :             }
     233          18 :             DEBUG(SSSDBG_FUNC_DATA, "Selected realm: %s\n", *_realm);
     234             :         }
     235             : 
     236          18 :         ret = EOK;
     237             :     } else {
     238           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "No suitable principal found in keytab\n");
     239           0 :         ret = ENOENT;
     240             :     }
     241             : 
     242             : done:
     243          18 :     if (ret != EOK) {
     244           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to read keytab [%s]: %s\n",
     245             :                KEYTAB_CLEAN_NAME, strerror(ret));
     246           0 :         sss_log(SSS_LOG_ERR, "Failed to read keytab [%s]: %s\n",
     247             :                 KEYTAB_CLEAN_NAME, strerror(ret));
     248             :     }
     249          18 :     if (keytab) krb5_kt_close(krb_ctx, keytab);
     250          18 :     if (krb_ctx) krb5_free_context(krb_ctx);
     251          18 :     if (client_princ != NULL) {
     252          18 :         krb5_free_principal(krb_ctx, client_princ);
     253          18 :         client_princ = NULL;
     254             :     }
     255          18 :     talloc_free(tmp_ctx);
     256          18 :     return ret;
     257             : }
     258             : 
     259             : enum matching_mode {MODE_NORMAL, MODE_PREFIX, MODE_POSTFIX};
     260             : /**
     261             :  * We only have primary and instances stored separately, we need to
     262             :  * join them to one string and compare that string.
     263             :  *
     264             :  * @param ctx kerberos context
     265             :  * @param principal principal we want to match
     266             :  * @param pattern_primary primary part of the principal we want to
     267             :  *        perform matching against. It is possible to use * wildcard
     268             :  *        at the beginning or at the end of the string. If NULL, it
     269             :  *        will act as "*"
     270             :  * @param pattern_realm realm part of the principal we want to perform
     271             :  *        the matching against. If NULL, it will act as "*"
     272             :  */
     273          54 : static bool match_principal(krb5_context ctx,
     274             :                      krb5_principal principal,
     275             :                      const char *pattern_primary,
     276             :                      const char *pattern_realm)
     277             : {
     278          54 :     char *primary = NULL;
     279          54 :     char *primary_str = NULL;
     280          54 :     int primary_str_len = 0;
     281             :     int tmp_len;
     282             :     int len_diff;
     283             :     const char *realm_name;
     284             :     int realm_len;
     285             : 
     286          54 :     enum matching_mode mode = MODE_NORMAL;
     287             :     TALLOC_CTX *tmp_ctx;
     288          54 :     bool ret = false;
     289             : 
     290          54 :     sss_krb5_princ_realm(ctx, principal, &realm_name, &realm_len);
     291          54 :     if (realm_len == 0) {
     292           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "sss_krb5_princ_realm failed.\n");
     293           0 :         return false;
     294             :     }
     295             : 
     296          54 :     tmp_ctx = talloc_new(NULL);
     297          54 :     if (!tmp_ctx) {
     298           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n");
     299           0 :         return false;
     300             :     }
     301             : 
     302          54 :     if (pattern_primary) {
     303          54 :         tmp_len = strlen(pattern_primary);
     304          54 :         if (pattern_primary[tmp_len-1] == '*') {
     305           0 :             mode = MODE_PREFIX;
     306           0 :             primary_str = talloc_strdup(tmp_ctx, pattern_primary);
     307           0 :             primary_str[tmp_len-1] = '\0';
     308           0 :             primary_str_len = tmp_len-1;
     309          54 :         } else if (pattern_primary[0] == '*') {
     310           0 :             mode = MODE_POSTFIX;
     311           0 :             primary_str = talloc_strdup(tmp_ctx, pattern_primary+1);
     312           0 :             primary_str_len = tmp_len-1;
     313             :         }
     314             : 
     315          54 :         sss_krb5_unparse_name_flags(ctx, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM,
     316             :                                     &primary);
     317             : 
     318          54 :         len_diff = strlen(primary)-primary_str_len;
     319             : 
     320         108 :         if ((mode == MODE_NORMAL &&
     321          72 :                 strcmp(primary, pattern_primary) != 0) ||
     322           0 :             (mode == MODE_PREFIX &&
     323          18 :                 strncmp(primary, primary_str, primary_str_len) != 0) ||
     324           0 :             (mode == MODE_POSTFIX &&
     325           0 :                 strcmp(primary+len_diff, primary_str) != 0)) {
     326             :             goto done;
     327             :         }
     328             :     }
     329             : 
     330          36 :     if (!pattern_realm || (realm_len == strlen(pattern_realm) &&
     331          18 :         strncmp(realm_name, pattern_realm, realm_len) == 0)) {
     332          18 :         DEBUG(SSSDBG_TRACE_LIBS,
     333             :               "Principal matched to the sample (%s@%s).\n", pattern_primary,
     334             :                                                                 pattern_realm);
     335          18 :         ret = true;
     336             :     }
     337             : 
     338             : done:
     339          54 :     free(primary);
     340          54 :     talloc_free(tmp_ctx);
     341          54 :     return ret;
     342             : }
     343             : 
     344          36 : krb5_error_code find_principal_in_keytab(krb5_context ctx,
     345             :                                          krb5_keytab keytab,
     346             :                                          const char *pattern_primary,
     347             :                                          const char *pattern_realm,
     348             :                                          krb5_principal *princ)
     349             : {
     350             :     krb5_error_code kerr;
     351             :     krb5_error_code kt_err;
     352             :     krb5_error_code kerr_d;
     353             :     krb5_kt_cursor cursor;
     354             :     krb5_keytab_entry entry;
     355          36 :     bool principal_found = false;
     356             : 
     357          36 :     memset(&cursor, 0, sizeof(cursor));
     358          36 :     kerr = krb5_kt_start_seq_get(ctx, keytab, &cursor);
     359          36 :     if (kerr != 0) {
     360           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_start_seq_get failed.\n");
     361           0 :         return kerr;
     362             :     }
     363             : 
     364          36 :     DEBUG(SSSDBG_TRACE_ALL,
     365             :           "Trying to find principal %s@%s in keytab.\n", pattern_primary, pattern_realm);
     366          36 :     memset(&entry, 0, sizeof(entry));
     367         108 :     while ((kt_err = krb5_kt_next_entry(ctx, keytab, &entry, &cursor)) == 0) {
     368          54 :         principal_found = match_principal(ctx, entry.principal, pattern_primary, pattern_realm);
     369          54 :         if (principal_found) {
     370          18 :             break;
     371             :         }
     372             : 
     373          36 :         kerr = sss_krb5_free_keytab_entry_contents(ctx, &entry);
     374          36 :         if (kerr != 0) {
     375           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Failed to free keytab entry.\n");
     376             :         }
     377          36 :         memset(&entry, 0, sizeof(entry));
     378             :     }
     379             : 
     380             :     /* Close the keytab here.  Even though we're using cursors, the file
     381             :      * handle is stored in the krb5_keytab structure, and it gets
     382             :      * overwritten by other keytab calls, creating a leak. */
     383          36 :     kerr = krb5_kt_end_seq_get(ctx, keytab, &cursor);
     384          36 :     if (kerr != 0) {
     385           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_end_seq_get failed.\n");
     386           0 :         goto done;
     387             :     }
     388             : 
     389          36 :     if (!principal_found) {
     390          18 :         kerr = KRB5_KT_NOTFOUND;
     391          18 :         DEBUG(SSSDBG_TRACE_FUNC,
     392             :               "No principal matching %s@%s found in keytab.\n",
     393             :                pattern_primary, pattern_realm);
     394          18 :         goto done;
     395             :     }
     396             : 
     397             :     /* check if we got any errors from krb5_kt_next_entry */
     398          18 :     if (kt_err != 0 && kt_err != KRB5_KT_END) {
     399           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error while reading keytab.\n");
     400           0 :         goto done;
     401             :     }
     402             : 
     403          18 :     kerr = krb5_copy_principal(ctx, entry.principal, princ);
     404          18 :     if (kerr != 0) {
     405           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "krb5_copy_principal failed.\n");
     406           0 :         goto done;
     407             :     }
     408             : 
     409          18 :     kerr = 0;
     410             : 
     411             : done:
     412          36 :     kerr_d = sss_krb5_free_keytab_entry_contents(ctx, &entry);
     413          36 :     if (kerr_d != 0) {
     414           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to free keytab entry.\n");
     415             :     }
     416             : 
     417          36 :     return kerr;
     418             : }
     419             : 
     420           0 : const char *KRB5_CALLCONV sss_krb5_get_error_message(krb5_context ctx,
     421             :                                                krb5_error_code ec)
     422             : {
     423             : #ifdef HAVE_KRB5_GET_ERROR_MESSAGE
     424           0 :     return krb5_get_error_message(ctx, ec);
     425             : #else
     426             :     int ret;
     427             :     char *s = NULL;
     428             :     int size = sizeof("Kerberos error [XXXXXXXXXXXX]");
     429             : 
     430             :     s = malloc(sizeof(char) * (size));
     431             :     if (s == NULL) {
     432             :         return NULL;
     433             :     }
     434             : 
     435             :     ret = snprintf(s, size, "Kerberos error [%12d]", ec);
     436             : 
     437             :     if (ret < 0 || ret >= size) {
     438             :         free(s);
     439             :         return NULL;
     440             :     }
     441             : 
     442             :     return s;
     443             : #endif
     444             : }
     445             : 
     446           0 : void KRB5_CALLCONV sss_krb5_free_error_message(krb5_context ctx, const char *s)
     447             : {
     448             : #ifdef HAVE_KRB5_GET_ERROR_MESSAGE
     449           0 :     krb5_free_error_message(ctx, s);
     450             : #else
     451             :     free(s);
     452             : #endif
     453             : 
     454           0 :     return;
     455             : }
     456             : 
     457           0 : krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_alloc(
     458             :                                                   krb5_context context,
     459             :                                                   krb5_get_init_creds_opt **opt)
     460             : {
     461             : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
     462           0 :     return krb5_get_init_creds_opt_alloc(context, opt);
     463             : #else
     464             :     *opt = calloc(1, sizeof(krb5_get_init_creds_opt));
     465             :     if (*opt == NULL) {
     466             :         return ENOMEM;
     467             :     }
     468             :     krb5_get_init_creds_opt_init(*opt);
     469             : 
     470             :     return 0;
     471             : #endif
     472             : }
     473             : 
     474           0 : void KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
     475             :                                                    krb5_get_init_creds_opt *opt)
     476             : {
     477             : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
     478           0 :     krb5_get_init_creds_opt_free(context, opt);
     479             : #else
     480             :     free(opt);
     481             : #endif
     482             : 
     483           0 :     return;
     484             : }
     485             : 
     486           0 : void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name)
     487             : {
     488             : #ifdef HAVE_KRB5_FREE_UNPARSED_NAME
     489           0 :     krb5_free_unparsed_name(context, name);
     490             : #else
     491             :     if (name != NULL) {
     492             :         memset(name, 0, strlen(name));
     493             :         free(name);
     494             :     }
     495             : #endif
     496           0 : }
     497             : 
     498             : 
     499           0 : krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_expire_callback(
     500             :                                                    krb5_context context,
     501             :                                                    krb5_get_init_creds_opt *opt,
     502             :                                                    krb5_expire_callback_func cb,
     503             :                                                    void *data)
     504             : {
     505             : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_EXPIRE_CALLBACK
     506           0 :     return krb5_get_init_creds_opt_set_expire_callback(context, opt, cb, data);
     507             : #else
     508             :     DEBUG(SSSDBG_FUNC_DATA,
     509             :           "krb5_get_init_creds_opt_set_expire_callback not available.\n");
     510             :     return 0;
     511             : #endif
     512             : }
     513             : 
     514           0 : errno_t check_fast(const char *str, bool *use_fast)
     515             : {
     516             : #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_FLAGS
     517           0 :     if (strcasecmp(str, "never") == 0 ) {
     518           0 :         *use_fast = false;
     519           0 :     } else if (strcasecmp(str, "try") == 0 || strcasecmp(str, "demand") == 0) {
     520           0 :         *use_fast = true;
     521             :     } else {
     522           0 :         sss_log(SSS_LOG_ALERT, "Unsupported value [%s] for option krb5_use_fast,"
     523             :                                "please use never, try, or demand.\n", str);
     524           0 :         return EINVAL;
     525             :     }
     526             : 
     527           0 :     return EOK;
     528             : #else
     529             :     sss_log(SSS_LOG_ALERT, "This build of sssd does not support FAST. "
     530             :                            "Please remove option krb5_use_fast.\n");
     531             :     return EINVAL;
     532             : #endif
     533             : }
     534             : 
     535           0 : krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_ccache_name(
     536             :                                                    krb5_context context,
     537             :                                                    krb5_get_init_creds_opt *opt,
     538             :                                                    const char *fast_ccache_name)
     539             : {
     540             : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_CCACHE_NAME
     541           0 :     return krb5_get_init_creds_opt_set_fast_ccache_name(context, opt,
     542             :                                                         fast_ccache_name);
     543             : #else
     544             :     DEBUG(SSSDBG_FUNC_DATA,
     545             :           "krb5_get_init_creds_opt_set_fast_ccache_name not available.\n");
     546             :     return 0;
     547             : #endif
     548             : }
     549             : 
     550           0 : krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_set_fast_flags(
     551             :                                                    krb5_context context,
     552             :                                                    krb5_get_init_creds_opt *opt,
     553             :                                                    krb5_flags flags)
     554             : {
     555             : #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_FLAGS
     556           0 :     return krb5_get_init_creds_opt_set_fast_flags(context, opt, flags);
     557             : #else
     558             :     DEBUG(SSSDBG_FUNC_DATA,
     559             :           "krb5_get_init_creds_opt_set_fast_flags not available.\n");
     560             :     return 0;
     561             : #endif
     562             : }
     563             : 
     564             : 
     565             : #ifndef HAVE_KRB5_UNPARSE_NAME_FLAGS
     566             : #ifndef REALM_SEP
     567             : #define REALM_SEP       '@'
     568             : #endif
     569             : #ifndef COMPONENT_SEP
     570             : #define COMPONENT_SEP   '/'
     571             : #endif
     572             : 
     573             : static int
     574             : sss_krb5_copy_component_quoting(char *dest, const krb5_data *src, int flags)
     575             : {
     576             :     int j;
     577             :     const char *cp = src->data;
     578             :     char *q = dest;
     579             :     int length = src->length;
     580             : 
     581             :     if (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) {
     582             :         memcpy(dest, src->data, src->length);
     583             :         return src->length;
     584             :     }
     585             : 
     586             :     for (j=0; j < length; j++,cp++) {
     587             :         int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
     588             :             !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
     589             : 
     590             :         switch (*cp) {
     591             :         case REALM_SEP:
     592             :             if (no_realm) {
     593             :                 *q++ = *cp;
     594             :                 break;
     595             :             }
     596             :         case COMPONENT_SEP:
     597             :         case '\\':
     598             :             *q++ = '\\';
     599             :             *q++ = *cp;
     600             :             break;
     601             :         case '\t':
     602             :             *q++ = '\\';
     603             :             *q++ = 't';
     604             :             break;
     605             :         case '\n':
     606             :             *q++ = '\\';
     607             :             *q++ = 'n';
     608             :             break;
     609             :         case '\b':
     610             :             *q++ = '\\';
     611             :             *q++ = 'b';
     612             :             break;
     613             :         case '\0':
     614             :             *q++ = '\\';
     615             :             *q++ = '0';
     616             :             break;
     617             :         default:
     618             :             *q++ = *cp;
     619             :         }
     620             :     }
     621             :     return q - dest;
     622             : }
     623             : 
     624             : static int
     625             : sss_krb5_component_length_quoted(const krb5_data *src, int flags)
     626             : {
     627             :     const char *cp = src->data;
     628             :     int length = src->length;
     629             :     int j;
     630             :     int size = length;
     631             : 
     632             :     if ((flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) == 0) {
     633             :         int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) &&
     634             :             !(flags & KRB5_PRINCIPAL_UNPARSE_SHORT);
     635             : 
     636             :         for (j = 0; j < length; j++,cp++)
     637             :             if ((!no_realm && *cp == REALM_SEP) ||
     638             :                 *cp == COMPONENT_SEP ||
     639             :                 *cp == '\0' || *cp == '\\' || *cp == '\t' ||
     640             :                 *cp == '\n' || *cp == '\b')
     641             :                 size++;
     642             :     }
     643             : 
     644             :     return size;
     645             : }
     646             : 
     647             : #endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
     648             : 
     649             : 
     650             : krb5_error_code
     651           0 : sss_krb5_parse_name_flags(krb5_context context, const char *name, int flags,
     652             :                           krb5_principal *principal)
     653             : {
     654             : #ifdef HAVE_KRB5_PARSE_NAME_FLAGS
     655           0 :     return krb5_parse_name_flags(context, name, flags, principal);
     656             : #else
     657             :     if (flags != 0) {
     658             :         DEBUG(SSSDBG_MINOR_FAILURE, "krb5_parse_name_flags not available on " \
     659             :                                      "this plattform, names are parsed " \
     660             :                                      "without flags. Some features like " \
     661             :                                      "enterprise principals might not work " \
     662             :                                      "as expected.\n");
     663             :     }
     664             : 
     665             :     return krb5_parse_name(context, name, principal);
     666             : #endif
     667             : }
     668             : 
     669             : krb5_error_code
     670          72 : sss_krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal,
     671             :                         int flags, char **name)
     672             : {
     673             : #ifdef HAVE_KRB5_UNPARSE_NAME_FLAGS
     674          72 :     return krb5_unparse_name_flags(context, principal, flags, name);
     675             : #else
     676             :     char *cp, *q;
     677             :     int i;
     678             :     int length;
     679             :     krb5_int32 nelem;
     680             :     unsigned int totalsize = 0;
     681             :     char *default_realm = NULL;
     682             :     krb5_error_code ret = 0;
     683             : 
     684             :     if (name != NULL)
     685             :         *name = NULL;
     686             : 
     687             :     if (!principal || !name)
     688             :         return KRB5_PARSE_MALFORMED;
     689             : 
     690             :     if (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) {
     691             :         /* omit realm if local realm */
     692             :         krb5_principal_data p;
     693             : 
     694             :         ret = krb5_get_default_realm(context, &default_realm);
     695             :         if (ret != 0)
     696             :             goto cleanup;
     697             : 
     698             :         krb5_princ_realm(context, &p)->length = strlen(default_realm);
     699             :         krb5_princ_realm(context, &p)->data = default_realm;
     700             : 
     701             :         if (krb5_realm_compare(context, &p, principal))
     702             :             flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM;
     703             :     }
     704             : 
     705             :     if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
     706             :         totalsize += sss_krb5_component_length_quoted(krb5_princ_realm(context,
     707             :                                                               principal),
     708             :                                              flags);
     709             :         totalsize++;
     710             :     }
     711             : 
     712             :     nelem = krb5_princ_size(context, principal);
     713             :     for (i = 0; i < (int) nelem; i++) {
     714             :         cp = krb5_princ_component(context, principal, i)->data;
     715             :         totalsize += sss_krb5_component_length_quoted(krb5_princ_component(context, principal, i), flags);
     716             :         totalsize++;
     717             :     }
     718             :     if (nelem == 0)
     719             :         totalsize++;
     720             : 
     721             :     *name = malloc(totalsize);
     722             : 
     723             :     if (!*name) {
     724             :         ret = ENOMEM;
     725             :         goto cleanup;
     726             :     }
     727             : 
     728             :     q = *name;
     729             : 
     730             :     for (i = 0; i < (int) nelem; i++) {
     731             :         cp = krb5_princ_component(context, principal, i)->data;
     732             :         length = krb5_princ_component(context, principal, i)->length;
     733             :         q += sss_krb5_copy_component_quoting(q,
     734             :                                     krb5_princ_component(context,
     735             :                                                          principal,
     736             :                                                          i),
     737             :                                     flags);
     738             :         *q++ = COMPONENT_SEP;
     739             :     }
     740             : 
     741             :     if (i > 0)
     742             :         q--;
     743             :     if ((flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) == 0) {
     744             :         *q++ = REALM_SEP;
     745             :         q += sss_krb5_copy_component_quoting(q, krb5_princ_realm(context, principal), flags);
     746             :     }
     747             :     *q++ = '\0';
     748             : 
     749             : cleanup:
     750             :     free(default_realm);
     751             : 
     752             :     return ret;
     753             : #endif /* HAVE_KRB5_UNPARSE_NAME_FLAGS */
     754             : }
     755             : 
     756           0 : void sss_krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt *opts,
     757             :                                                   int canonicalize)
     758             : {
     759             :     /* FIXME: The extra check for HAVE_KRB5_TICKET_TIMES is a workaround due to Heimdal
     760             :      * defining krb5_get_init_creds_opt_set_canonicalize() with a different set of
     761             :      * arguments. We should use a better configure check in the future.
     762             :      */
     763             : #if defined(HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CANONICALIZE) && defined(HAVE_KRB5_TICKET_TIMES)
     764           0 :     krb5_get_init_creds_opt_set_canonicalize(opts, canonicalize);
     765             : #else
     766             :     DEBUG(SSSDBG_OP_FAILURE, "Kerberos principal canonicalization is not available!\n");
     767             : #endif
     768           0 : }
     769             : 
     770             : #ifdef HAVE_KRB5_PRINCIPAL_GET_REALM
     771             : void sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
     772             :                           const char **realm, int *len)
     773             : {
     774             :     const char *realm_str = krb5_principal_get_realm(context, princ);
     775             : 
     776             :     if (realm_str != NULL) {
     777             :         *realm = realm_str;
     778             :         *len = strlen(realm_str);
     779             :     } else {
     780             :         *realm = NULL;
     781             :         *len = 0;
     782             :     }
     783             : }
     784             : #else
     785          72 : void sss_krb5_princ_realm(krb5_context context, krb5_const_principal princ,
     786             :                           const char **realm, int *len)
     787             : {
     788             :     const krb5_data *data;
     789             : 
     790          72 :     data = krb5_princ_realm(context, princ);
     791          72 :     if (data) {
     792          72 :         *realm = data->data;
     793          72 :         *len = data->length;
     794             :     } else {
     795           0 :         *realm = NULL;
     796           0 :         *len = 0;
     797             :     }
     798          72 : }
     799             : #endif
     800             : 
     801             : #ifdef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS
     802             : krb5_error_code
     803          88 : sss_krb5_free_keytab_entry_contents(krb5_context context,
     804             :                                     krb5_keytab_entry *entry)
     805             : {
     806          88 :     return krb5_free_keytab_entry_contents(context, entry);
     807             : }
     808             : #else
     809             : krb5_error_code
     810             : sss_krb5_free_keytab_entry_contents(krb5_context context,
     811             :                                     krb5_keytab_entry *entry)
     812             : {
     813             :     return krb5_kt_free_entry(context, entry);
     814             : }
     815             : #endif
     816             : 
     817             : 
     818             : #ifdef HAVE_KRB5_SET_TRACE_CALLBACK
     819             : 
     820             : #ifndef HAVE_KRB5_TRACE_INFO
     821             : /* krb5-1.10 had struct krb5_trace_info, 1.11 has type named krb5_trace_info */
     822             : typedef struct krb5_trace_info krb5_trace_info;
     823             : #endif  /* HAVE_KRB5_TRACE_INFO */
     824             : 
     825             : static void
     826           0 : sss_child_krb5_trace_cb(krb5_context context,
     827             :                         const krb5_trace_info *info, void *data)
     828             : {
     829           0 :     if (info == NULL) {
     830             :         /* Null info means destroy the callback data. */
     831           0 :         return;
     832             :     }
     833             : 
     834           0 :     DEBUG(SSSDBG_TRACE_ALL, "%s\n", info->message);
     835             : }
     836             : 
     837             : errno_t
     838           0 : sss_child_set_krb5_tracing(krb5_context ctx)
     839             : {
     840           0 :     return krb5_set_trace_callback(ctx, sss_child_krb5_trace_cb, NULL);
     841             : }
     842             : #else /* HAVE_KRB5_SET_TRACE_CALLBACK */
     843             : errno_t
     844             : sss_child_set_krb5_tracing(krb5_context ctx)
     845             : {
     846             :     DEBUG(SSSDBG_CONF_SETTINGS, "krb5 tracing is not available\n");
     847             :     return 0;
     848             : }
     849             : #endif /* HAVE_KRB5_SET_TRACE_CALLBACK */
     850             : 
     851           0 : krb5_error_code sss_krb5_find_authdata(krb5_context context,
     852             :                                        krb5_authdata *const *ticket_authdata,
     853             :                                        krb5_authdata *const *ap_req_authdata,
     854             :                                        krb5_authdatatype ad_type,
     855             :                                        krb5_authdata ***results)
     856             : {
     857             : #ifdef HAVE_KRB5_FIND_AUTHDATA
     858           0 :     return krb5_find_authdata(context, ticket_authdata, ap_req_authdata,
     859             :                               ad_type, results);
     860             : #else
     861             :     return ENOTSUP;
     862             : #endif
     863             : }
     864             : 
     865           0 : krb5_error_code sss_extract_pac(krb5_context ctx,
     866             :                                 krb5_ccache ccache,
     867             :                                 krb5_principal server_principal,
     868             :                                 krb5_principal client_principal,
     869             :                                 krb5_keytab keytab,
     870             :                                 krb5_authdata ***_pac_authdata)
     871             : {
     872             : #ifdef HAVE_PAC_RESPONDER
     873             :     krb5_error_code kerr;
     874             :     krb5_creds mcred;
     875             :     krb5_creds cred;
     876           0 :     krb5_authdata **pac_authdata = NULL;
     877           0 :     krb5_pac pac = NULL;
     878             :     int ret;
     879           0 :     krb5_ticket *ticket = NULL;
     880             :     krb5_keytab_entry entry;
     881             : 
     882           0 :     memset(&entry, 0, sizeof(entry));
     883           0 :     memset(&mcred, 0, sizeof(mcred));
     884           0 :     memset(&cred, 0, sizeof(mcred));
     885             : 
     886           0 :     mcred.server = server_principal;
     887           0 :     mcred.client = client_principal;
     888             : 
     889           0 :     kerr = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcred, &cred);
     890           0 :     if (kerr != 0) {
     891           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_cc_retrieve_cred failed.\n");
     892           0 :         goto done;
     893             :     }
     894             : 
     895           0 :     kerr = krb5_decode_ticket(&cred.ticket, &ticket);
     896           0 :     if (kerr != 0) {
     897           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_decode_ticket failed.\n");
     898           0 :         goto done;
     899             :     }
     900             : 
     901           0 :     kerr = krb5_server_decrypt_ticket_keytab(ctx, keytab, ticket);
     902           0 :     if (kerr != 0) {
     903           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_server_decrypt_ticket_keytab failed.\n");
     904           0 :         goto done;
     905             :     }
     906             : 
     907           0 :     kerr = sss_krb5_find_authdata(ctx,
     908           0 :                                   ticket->enc_part2->authorization_data, NULL,
     909             :                                   KRB5_AUTHDATA_WIN2K_PAC, &pac_authdata);
     910           0 :     if (kerr != 0) {
     911           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_find_authdata failed.\n");
     912           0 :         goto done;
     913             :     }
     914             : 
     915           0 :     if (pac_authdata == NULL || pac_authdata[0] == NULL) {
     916           0 :         DEBUG(SSSDBG_OP_FAILURE, "No PAC authdata available.\n");
     917           0 :         kerr = ENOENT;
     918           0 :         goto done;
     919             :     }
     920             : 
     921           0 :     if (pac_authdata[1] != NULL) {
     922           0 :         DEBUG(SSSDBG_OP_FAILURE, "More than one PAC autdata found.\n");
     923           0 :         kerr = EINVAL;
     924           0 :         goto done;
     925             :     }
     926             : 
     927           0 :     kerr = krb5_pac_parse(ctx, pac_authdata[0]->contents,
     928           0 :                           pac_authdata[0]->length, &pac);
     929           0 :     if (kerr != 0) {
     930           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_pac_parse failed.\n");
     931           0 :         goto done;
     932             :     }
     933             : 
     934           0 :     kerr = krb5_kt_get_entry(ctx, keytab, ticket->server,
     935           0 :                              ticket->enc_part.kvno, ticket->enc_part.enctype,
     936             :                              &entry);
     937           0 :     if (kerr != 0) {
     938           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_get_entry failed.\n");
     939           0 :         goto done;
     940             :     }
     941             : 
     942           0 :     kerr = krb5_pac_verify(ctx, pac, 0, NULL, &entry.key, NULL);
     943           0 :     if (kerr != 0) {
     944           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_pac_verify failed.\n");
     945           0 :         goto done;
     946             :     }
     947             : 
     948           0 :     ret = unsetenv("_SSS_LOOPS");
     949           0 :     if (ret != EOK) {
     950           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to unset _SSS_LOOPS, "
     951             :                   "sss_pac_make_request will most certainly fail.\n");
     952             :     }
     953             : 
     954           0 :     *_pac_authdata = pac_authdata;
     955           0 :     kerr = 0;
     956             : 
     957             : done:
     958           0 :     if (kerr != 0) {
     959           0 :         krb5_free_authdata(ctx, pac_authdata);
     960             :     }
     961           0 :     if (entry.magic != 0) {
     962           0 :         krb5_free_keytab_entry_contents(ctx, &entry);
     963             :     }
     964           0 :     krb5_pac_free(ctx, pac);
     965           0 :     if (ticket != NULL) {
     966           0 :         krb5_free_ticket(ctx, ticket);
     967             :     }
     968             : 
     969           0 :     krb5_free_cred_contents(ctx, &cred);
     970           0 :     return kerr;
     971             : #else
     972             :     return ENOTSUP;
     973             : #endif
     974             : }
     975             : 
     976           0 : char * sss_get_ccache_name_for_principal(TALLOC_CTX *mem_ctx,
     977             :                                          krb5_context ctx,
     978             :                                          krb5_principal principal,
     979             :                                          const char *location)
     980             : {
     981             : #ifdef HAVE_KRB5_CC_COLLECTION
     982             :     krb5_error_code kerr;
     983           0 :     krb5_ccache tmp_cc = NULL;
     984           0 :     char *tmp_ccname = NULL;
     985           0 :     char *ret_ccname = NULL;
     986             : 
     987           0 :     DEBUG(SSSDBG_TRACE_ALL,
     988             :           "Location: [%s]\n", location);
     989             : 
     990           0 :     kerr = krb5_cc_set_default_name(ctx, location);
     991           0 :     if (kerr != 0) {
     992           0 :         KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr);
     993           0 :         return NULL;
     994             :     }
     995             : 
     996           0 :     kerr = krb5_cc_cache_match(ctx, principal, &tmp_cc);
     997           0 :     if (kerr != 0) {
     998           0 :         const char *err_msg = sss_krb5_get_error_message(ctx, kerr);
     999           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    1000             :               "krb5_cc_cache_match failed: [%d][%s]\n", kerr, err_msg);
    1001           0 :         sss_krb5_free_error_message(ctx, err_msg);
    1002           0 :         return NULL;
    1003             :     }
    1004             : 
    1005           0 :     kerr = krb5_cc_get_full_name(ctx, tmp_cc, &tmp_ccname);
    1006           0 :     if (kerr != 0) {
    1007           0 :         KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr);
    1008           0 :         goto done;
    1009             :     }
    1010             : 
    1011           0 :     DEBUG(SSSDBG_TRACE_ALL,
    1012             :           "tmp_ccname: [%s]\n", tmp_ccname);
    1013             : 
    1014           0 :     ret_ccname = talloc_strdup(mem_ctx, tmp_ccname);
    1015           0 :     if (ret_ccname == NULL) {
    1016           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed (ENOMEM).\n");
    1017             :     }
    1018             : 
    1019             : done:
    1020           0 :     if (tmp_cc != NULL) {
    1021           0 :         kerr = krb5_cc_close(ctx, tmp_cc);
    1022           0 :         if (kerr != 0) {
    1023           0 :             KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr);
    1024             :         }
    1025             :     }
    1026           0 :     krb5_free_string(ctx, tmp_ccname);
    1027             : 
    1028           0 :     return ret_ccname;
    1029             : #else
    1030             :     return NULL;
    1031             : #endif /* HAVE_KRB5_CC_COLLECTION */
    1032             : }
    1033             : 
    1034           4 : krb5_error_code sss_krb5_kt_have_content(krb5_context context,
    1035             :                                          krb5_keytab keytab)
    1036             : {
    1037             : #ifdef HAVE_KRB5_KT_HAVE_CONTENT
    1038           4 :     return krb5_kt_have_content(context, keytab);
    1039             : #else
    1040             :     krb5_keytab_entry entry;
    1041             :     krb5_kt_cursor cursor;
    1042             :     krb5_error_code kerr;
    1043             :     krb5_error_code kerr_end;
    1044             : 
    1045             :     kerr = krb5_kt_start_seq_get(context, keytab, &cursor);
    1046             :     if (kerr != 0) {
    1047             :         DEBUG(SSSDBG_OP_FAILURE,
    1048             :               "krb5_kt_start_seq_get failed, assuming no entries.\n");
    1049             :         return KRB5_KT_NOTFOUND;
    1050             :     }
    1051             : 
    1052             :     kerr = krb5_kt_next_entry(context, keytab, &entry, &cursor);
    1053             :     kerr_end = krb5_kt_end_seq_get(context, keytab, &cursor);
    1054             :     if (kerr != 0) {
    1055             :         DEBUG(SSSDBG_OP_FAILURE,
    1056             :               "krb5_kt_next_entry failed, assuming no entries.\n");
    1057             :         return KRB5_KT_NOTFOUND;
    1058             :     }
    1059             :     kerr = krb5_free_keytab_entry_contents(context, &entry);
    1060             : 
    1061             :     if (kerr_end != 0) {
    1062             :         DEBUG(SSSDBG_TRACE_FUNC,
    1063             :               "krb5_kt_end_seq_get failed, ignored.\n");
    1064             :     }
    1065             :     if (kerr != 0) {
    1066             :         DEBUG(SSSDBG_TRACE_FUNC,
    1067             :               "krb5_free_keytab_entry_contents failed, ignored.\n");
    1068             :     }
    1069             : 
    1070             :     return 0;
    1071             : #endif
    1072             : }
    1073             : 
    1074             : #define KDC_PROXY_INDICATOR "https://"
    1075             : #define KDC_PROXY_INDICATOR_LEN (sizeof(KDC_PROXY_INDICATOR) - 1)
    1076             : 
    1077           4 : bool sss_krb5_realm_has_proxy(const char *realm)
    1078             : {
    1079           4 :     krb5_context context = NULL;
    1080             :     krb5_error_code kerr;
    1081           4 :     struct _profile_t *profile = NULL;
    1082           4 :     const char  *profile_path[4] = {"realms", NULL, "kdc", NULL};
    1083           4 :     char **list = NULL;
    1084           4 :     bool res = false;
    1085             :     size_t c;
    1086             : 
    1087           4 :     if (realm == NULL) {
    1088           1 :         return false;
    1089             :     }
    1090             : 
    1091           3 :     kerr = krb5_init_context(&context);
    1092           3 :     if (kerr != 0) {
    1093           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_init_context failed.\n");
    1094           0 :         return false;
    1095             :     }
    1096             : 
    1097           3 :     kerr = krb5_get_profile(context, &profile);
    1098           3 :     if (kerr != 0) {
    1099           0 :         DEBUG(SSSDBG_OP_FAILURE, "krb5_get_profile failed.\n");
    1100           0 :         goto done;
    1101             :     }
    1102             : 
    1103           3 :     profile_path[1] = realm;
    1104             : 
    1105           3 :     kerr = profile_get_values(profile, profile_path, &list);
    1106           3 :     if (kerr == PROF_NO_RELATION || kerr == PROF_NO_SECTION) {
    1107           1 :         kerr = 0;
    1108           1 :         goto done;
    1109           2 :     } else if (kerr != 0) {
    1110           0 :         DEBUG(SSSDBG_OP_FAILURE, "profile_get_values failed.\n");
    1111           0 :         goto done;
    1112             :     }
    1113             : 
    1114           3 :     for (c = 0; list[c] != NULL; c++) {
    1115           2 :         if (strncasecmp(KDC_PROXY_INDICATOR, list[c],
    1116             :                         KDC_PROXY_INDICATOR_LEN) == 0) {
    1117           1 :             DEBUG(SSSDBG_TRACE_ALL,
    1118             :                   "Found KDC Proxy indicator [%s] in [%s].\n",
    1119             :                   KDC_PROXY_INDICATOR, list[c]);
    1120           1 :             res = true;
    1121           1 :             break;
    1122             :         }
    1123             :     }
    1124             : 
    1125             : done:
    1126           3 :     profile_free_list(list);
    1127           3 :     profile_release(profile);
    1128           3 :     krb5_free_context(context);
    1129             : 
    1130           3 :     return res;
    1131             : }

Generated by: LCOV version 1.10