LCOV - code coverage report
Current view: top level - source4/heimdal/lib/krb5 - ticket.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 136 314 43.3 %
Date: 2021-09-23 10:06:22 Functions: 7 12 58.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  *
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  *
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  *
      19             :  * 3. Neither the name of the Institute nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  */
      35             : 
      36             : #include "krb5_locl.h"
      37             : 
      38             : /**
      39             :  * Free ticket and content
      40             :  *
      41             :  * @param context a Kerberos 5 context
      42             :  * @param ticket ticket to free
      43             :  *
      44             :  * @return Returns 0 to indicate success.  Otherwise an kerberos et
      45             :  * error code is returned, see krb5_get_error_message().
      46             :  *
      47             :  * @ingroup krb5
      48             :  */
      49             : 
      50             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
      51      133055 : krb5_free_ticket(krb5_context context,
      52             :                  krb5_ticket *ticket)
      53             : {
      54      133055 :     free_EncTicketPart(&ticket->ticket);
      55      133055 :     krb5_free_principal(context, ticket->client);
      56      133055 :     krb5_free_principal(context, ticket->server);
      57      133055 :     free(ticket);
      58      133055 :     return 0;
      59             : }
      60             : 
      61             : /**
      62             :  * Copy ticket and content
      63             :  *
      64             :  * @param context a Kerberos 5 context
      65             :  * @param from ticket to copy
      66             :  * @param to new copy of ticket, free with krb5_free_ticket()
      67             :  *
      68             :  * @return Returns 0 to indicate success.  Otherwise an kerberos et
      69             :  * error code is returned, see krb5_get_error_message().
      70             :  *
      71             :  * @ingroup krb5
      72             :  */
      73             : 
      74             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
      75       46185 : krb5_copy_ticket(krb5_context context,
      76             :                  const krb5_ticket *from,
      77             :                  krb5_ticket **to)
      78             : {
      79             :     krb5_error_code ret;
      80             :     krb5_ticket *tmp;
      81             : 
      82       46185 :     *to = NULL;
      83       46185 :     tmp = malloc(sizeof(*tmp));
      84       46185 :     if(tmp == NULL) {
      85           0 :         krb5_set_error_message(context, ENOMEM,
      86           0 :                                N_("malloc: out of memory", ""));
      87           0 :         return ENOMEM;
      88             :     }
      89       46185 :     if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
      90           0 :         free(tmp);
      91           0 :         return ret;
      92             :     }
      93       46185 :     ret = krb5_copy_principal(context, from->client, &tmp->client);
      94       46185 :     if(ret){
      95           0 :         free_EncTicketPart(&tmp->ticket);
      96           0 :         free(tmp);
      97           0 :         return ret;
      98             :     }
      99       46185 :     ret = krb5_copy_principal(context, from->server, &tmp->server);
     100       46185 :     if(ret){
     101           0 :         krb5_free_principal(context, tmp->client);
     102           0 :         free_EncTicketPart(&tmp->ticket);
     103           0 :         free(tmp);
     104           0 :         return ret;
     105             :     }
     106       46185 :     *to = tmp;
     107       46185 :     return 0;
     108             : }
     109             : 
     110             : /**
     111             :  * Return client principal in ticket
     112             :  *
     113             :  * @param context a Kerberos 5 context
     114             :  * @param ticket ticket to copy
     115             :  * @param client client principal, free with krb5_free_principal()
     116             :  *
     117             :  * @return Returns 0 to indicate success.  Otherwise an kerberos et
     118             :  * error code is returned, see krb5_get_error_message().
     119             :  *
     120             :  * @ingroup krb5
     121             :  */
     122             : 
     123             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     124        1445 : krb5_ticket_get_client(krb5_context context,
     125             :                        const krb5_ticket *ticket,
     126             :                        krb5_principal *client)
     127             : {
     128        1445 :     return krb5_copy_principal(context, ticket->client, client);
     129             : }
     130             : 
     131             : /**
     132             :  * Return server principal in ticket
     133             :  *
     134             :  * @param context a Kerberos 5 context
     135             :  * @param ticket ticket to copy
     136             :  * @param server server principal, free with krb5_free_principal()
     137             :  *
     138             :  * @return Returns 0 to indicate success.  Otherwise an kerberos et
     139             :  * error code is returned, see krb5_get_error_message().
     140             :  *
     141             :  * @ingroup krb5
     142             :  */
     143             : 
     144             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     145           0 : krb5_ticket_get_server(krb5_context context,
     146             :                        const krb5_ticket *ticket,
     147             :                        krb5_principal *server)
     148             : {
     149           0 :     return krb5_copy_principal(context, ticket->server, server);
     150             : }
     151             : 
     152             : /**
     153             :  * Return end time of ticket
     154             :  *
     155             :  * @param context a Kerberos 5 context
     156             :  * @param ticket ticket to copy
     157             :  *
     158             :  * @return end time of ticket
     159             :  *
     160             :  * @ingroup krb5
     161             :  */
     162             : 
     163             : KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL
     164           0 : krb5_ticket_get_endtime(krb5_context context,
     165             :                         const krb5_ticket *ticket)
     166             : {
     167           0 :     return ticket->ticket.endtime;
     168             : }
     169             : 
     170             : /**
     171             :  * Get the flags from the Kerberos ticket
     172             :  *
     173             :  * @param context Kerberos context
     174             :  * @param ticket Kerberos ticket
     175             :  *
     176             :  * @return ticket flags
     177             :  *
     178             :  * @ingroup krb5_ticket
     179             :  */
     180             : KRB5_LIB_FUNCTION unsigned long KRB5_LIB_CALL
     181           0 : krb5_ticket_get_flags(krb5_context context,
     182             :                       const krb5_ticket *ticket)
     183             : {
     184           0 :     return TicketFlags2int(ticket->ticket.flags);
     185             : }
     186             : 
     187             : static int
     188      276858 : find_type_in_ad(krb5_context context,
     189             :                 int type,
     190             :                 krb5_data *data,
     191             :                 krb5_boolean *found,
     192             :                 krb5_boolean failp,
     193             :                 krb5_keyblock *sessionkey,
     194             :                 const AuthorizationData *ad,
     195             :                 int level)
     196             : {
     197      276858 :     krb5_error_code ret = 0;
     198             :     size_t i;
     199             : 
     200      276858 :     if (level > 9) {
     201           0 :         ret = ENOENT; /* XXX */
     202           0 :         krb5_set_error_message(context, ret,
     203           0 :                                N_("Authorization data nested deeper "
     204             :                                   "then %d levels, stop searching", ""),
     205             :                                level);
     206           0 :         goto out;
     207             :     }
     208             : 
     209             :     /*
     210             :      * Only copy out the element the first time we get to it, we need
     211             :      * to run over the whole authorization data fields to check if
     212             :      * there are any container clases we need to care about.
     213             :      */
     214      641574 :     for (i = 0; i < ad->len; i++) {
     215      369144 :         if (!*found && ad->val[i].ad_type == type) {
     216       92286 :             ret = der_copy_octet_string(&ad->val[i].ad_data, data);
     217       92286 :             if (ret) {
     218           0 :                 krb5_set_error_message(context, ret,
     219           0 :                                        N_("malloc: out of memory", ""));
     220           0 :                 goto out;
     221             :             }
     222       92286 :             *found = TRUE;
     223       92286 :             continue;
     224             :         }
     225      276858 :         switch (ad->val[i].ad_type) {
     226      184572 :         case KRB5_AUTHDATA_IF_RELEVANT: {
     227             :             AuthorizationData child;
     228      184572 :             ret = decode_AuthorizationData(ad->val[i].ad_data.data,
     229      181620 :                                            ad->val[i].ad_data.length,
     230             :                                            &child,
     231             :                                            NULL);
     232      184572 :             if (ret) {
     233           0 :                 krb5_set_error_message(context, ret,
     234           0 :                                        N_("Failed to decode "
     235             :                                           "IF_RELEVANT with %d", ""),
     236             :                                        (int)ret);
     237           0 :                 goto out;
     238             :             }
     239      184572 :             ret = find_type_in_ad(context, type, data, found, FALSE,
     240             :                                   sessionkey, &child, level + 1);
     241      184572 :             free_AuthorizationData(&child);
     242      184572 :             if (ret)
     243           0 :                 goto out;
     244      184572 :             break;
     245             :         }
     246             : #if 0 /* XXX test */
     247             :         case KRB5_AUTHDATA_KDC_ISSUED: {
     248             :             AD_KDCIssued child;
     249             : 
     250             :             ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
     251             :                                       ad->val[i].ad_data.length,
     252             :                                       &child,
     253             :                                       NULL);
     254             :             if (ret) {
     255             :                 krb5_set_error_message(context, ret,
     256             :                                        N_("Failed to decode "
     257             :                                           "AD_KDCIssued with %d", ""),
     258             :                                        ret);
     259             :                 goto out;
     260             :             }
     261             :             if (failp) {
     262             :                 krb5_boolean valid;
     263             :                 krb5_data buf;
     264             :                 size_t len;
     265             : 
     266             :                 ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length,
     267             :                                    &child.elements, &len, ret);
     268             :                 if (ret) {
     269             :                     free_AD_KDCIssued(&child);
     270             :                     krb5_clear_error_message(context);
     271             :                     goto out;
     272             :                 }
     273             :                 if(buf.length != len)
     274             :                     krb5_abortx(context, "internal error in ASN.1 encoder");
     275             : 
     276             :                 ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
     277             :                                              &child.ad_checksum, &valid);
     278             :                 krb5_data_free(&buf);
     279             :                 if (ret) {
     280             :                     free_AD_KDCIssued(&child);
     281             :                     goto out;
     282             :                 }
     283             :                 if (!valid) {
     284             :                     krb5_clear_error_message(context);
     285             :                     ret = ENOENT;
     286             :                     free_AD_KDCIssued(&child);
     287             :                     goto out;
     288             :                 }
     289             :             }
     290             :             ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
     291             :                                   &child.elements, level + 1);
     292             :             free_AD_KDCIssued(&child);
     293             :             if (ret)
     294             :                 goto out;
     295             :             break;
     296             :         }
     297             : #endif
     298           0 :         case KRB5_AUTHDATA_AND_OR:
     299           0 :             if (!failp)
     300           0 :                 break;
     301           0 :             ret = ENOENT; /* XXX */
     302           0 :             krb5_set_error_message(context, ret,
     303           0 :                                    N_("Authorization data contains "
     304             :                                       "AND-OR element that is unknown to the "
     305             :                                       "application", ""));
     306           0 :             goto out;
     307       92286 :         default:
     308       92286 :             if (!failp)
     309       90810 :                 break;
     310           0 :             ret = ENOENT; /* XXX */
     311           0 :             krb5_set_error_message(context, ret,
     312           0 :                                    N_("Authorization data contains "
     313             :                                       "unknown type (%d) ", ""),
     314           0 :                                    ad->val[i].ad_type);
     315           0 :             goto out;
     316             :         }
     317        1476 :     }
     318      276858 : out:
     319      276858 :     if (ret) {
     320           0 :         if (*found) {
     321           0 :             krb5_data_free(data);
     322           0 :             *found = 0;
     323             :         }
     324             :     }
     325      276858 :     return ret;
     326             : }
     327             : 
     328             : /**
     329             :  * Extract the authorization data type of type from the ticket. Store
     330             :  * the field in data. This function is to use for kerberos
     331             :  * applications.
     332             :  *
     333             :  * @param context a Kerberos 5 context
     334             :  * @param ticket Kerberos ticket
     335             :  * @param type type to fetch
     336             :  * @param data returned data, free with krb5_data_free()
     337             :  *
     338             :  * @ingroup krb5
     339             :  */
     340             : 
     341             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     342       92286 : krb5_ticket_get_authorization_data_type(krb5_context context,
     343             :                                         krb5_ticket *ticket,
     344             :                                         int type,
     345             :                                         krb5_data *data)
     346             : {
     347             :     AuthorizationData *ad;
     348             :     krb5_error_code ret;
     349       92286 :     krb5_boolean found = FALSE;
     350             : 
     351       92286 :     krb5_data_zero(data);
     352             : 
     353       92286 :     ad = ticket->ticket.authorization_data;
     354       92286 :     if (ticket->ticket.authorization_data == NULL) {
     355           0 :         krb5_set_error_message(context, ENOENT,
     356           0 :                                N_("Ticket have not authorization data", ""));
     357           0 :         return ENOENT; /* XXX */
     358             :     }
     359             : 
     360       92286 :     ret = find_type_in_ad(context, type, data, &found, TRUE,
     361       92286 :                           &ticket->ticket.key, ad, 0);
     362       92286 :     if (ret)
     363           0 :         return ret;
     364       92286 :     if (!found) {
     365           0 :         krb5_set_error_message(context, ENOENT,
     366           0 :                                N_("Ticket have not "
     367             :                                   "authorization data of type %d", ""),
     368             :                                type);
     369           0 :         return ENOENT; /* XXX */
     370             :     }
     371       90810 :     return 0;
     372             : }
     373             : 
     374             : static krb5_error_code
     375           0 : check_server_referral(krb5_context context,
     376             :                       krb5_kdc_rep *rep,
     377             :                       unsigned flags,
     378             :                       krb5_const_principal requested,
     379             :                       krb5_const_principal returned,
     380             :                       krb5_keyblock * key)
     381             : {
     382             :     krb5_error_code ret;
     383             :     PA_ServerReferralData ref;
     384             :     krb5_crypto session;
     385             :     EncryptedData ed;
     386             :     size_t len;
     387             :     krb5_data data;
     388             :     PA_DATA *pa;
     389           0 :     int i = 0, cmp;
     390             : 
     391           0 :     if (rep->kdc_rep.padata == NULL)
     392           0 :         goto noreferral;
     393             : 
     394           0 :     pa = krb5_find_padata(rep->kdc_rep.padata->val,
     395           0 :                           rep->kdc_rep.padata->len,
     396             :                           KRB5_PADATA_SERVER_REFERRAL, &i);
     397           0 :     if (pa == NULL)
     398           0 :         goto noreferral;
     399             : 
     400           0 :     memset(&ed, 0, sizeof(ed));
     401           0 :     memset(&ref, 0, sizeof(ref));
     402             : 
     403           0 :     ret = decode_EncryptedData(pa->padata_value.data,
     404             :                                pa->padata_value.length,
     405             :                                &ed, &len);
     406           0 :     if (ret)
     407           0 :         return ret;
     408           0 :     if (len != pa->padata_value.length) {
     409           0 :         free_EncryptedData(&ed);
     410           0 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
     411           0 :                                N_("Referral EncryptedData wrong for realm %s",
     412             :                                   "realm"), requested->realm);
     413           0 :         return KRB5KRB_AP_ERR_MODIFIED;
     414             :     }
     415             : 
     416           0 :     ret = krb5_crypto_init(context, key, 0, &session);
     417           0 :     if (ret) {
     418           0 :         free_EncryptedData(&ed);
     419           0 :         return ret;
     420             :     }
     421             : 
     422           0 :     ret = krb5_decrypt_EncryptedData(context, session,
     423             :                                      KRB5_KU_PA_SERVER_REFERRAL,
     424             :                                      &ed, &data);
     425           0 :     free_EncryptedData(&ed);
     426           0 :     krb5_crypto_destroy(context, session);
     427           0 :     if (ret)
     428           0 :         return ret;
     429             : 
     430           0 :     ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
     431           0 :     if (ret) {
     432           0 :         krb5_data_free(&data);
     433           0 :         return ret;
     434             :     }
     435           0 :     krb5_data_free(&data);
     436             : 
     437           0 :     if (strcmp(requested->realm, returned->realm) != 0) {
     438           0 :         free_PA_ServerReferralData(&ref);
     439           0 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
     440           0 :                                N_("server ref realm mismatch, "
     441             :                                   "requested realm %s got back %s", ""),
     442             :                                requested->realm, returned->realm);
     443           0 :         return KRB5KRB_AP_ERR_MODIFIED;
     444             :     }
     445             : 
     446           0 :     if (krb5_principal_is_krbtgt(context, returned)) {
     447           0 :         const char *realm = returned->name.name_string.val[1];
     448             : 
     449           0 :         if (ref.referred_realm == NULL
     450           0 :             || strcmp(*ref.referred_realm, realm) != 0)
     451             :         {
     452           0 :             free_PA_ServerReferralData(&ref);
     453           0 :             krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
     454           0 :                                    N_("tgt returned with wrong ref", ""));
     455           0 :             return KRB5KRB_AP_ERR_MODIFIED;
     456             :         }
     457           0 :     } else if (krb5_principal_compare(context, returned, requested) == 0) {
     458           0 :         free_PA_ServerReferralData(&ref);
     459           0 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
     460           0 :                                N_("req princ no same as returned", ""));
     461           0 :         return KRB5KRB_AP_ERR_MODIFIED;
     462             :     }
     463             : 
     464           0 :     if (ref.requested_principal_name) {
     465           0 :         cmp = _krb5_principal_compare_PrincipalName(context,
     466             :                                                     requested,
     467             :                                                     ref.requested_principal_name);
     468           0 :         if (!cmp) {
     469           0 :             free_PA_ServerReferralData(&ref);
     470           0 :             krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
     471           0 :                                    N_("referred principal not same "
     472             :                                       "as requested", ""));
     473           0 :             return KRB5KRB_AP_ERR_MODIFIED;
     474             :         }
     475           0 :     } else if (flags & EXTRACT_TICKET_AS_REQ) {
     476           0 :         free_PA_ServerReferralData(&ref);
     477           0 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
     478           0 :                                N_("Requested principal missing on AS-REQ", ""));
     479           0 :         return KRB5KRB_AP_ERR_MODIFIED;
     480             :     }
     481             : 
     482           0 :     free_PA_ServerReferralData(&ref);
     483             : 
     484           0 :     return ret;
     485           0 : noreferral:
     486             :     /*
     487             :      * Expect excact match or that we got a krbtgt
     488             :      */
     489           0 :     if (krb5_principal_compare(context, requested, returned) != TRUE &&
     490           0 :         (krb5_realm_compare(context, requested, returned) != TRUE &&
     491           0 :          krb5_principal_is_krbtgt(context, returned) != TRUE))
     492             :     {
     493           0 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
     494           0 :                                N_("Not same server principal returned "
     495             :                                   "as requested", ""));
     496           0 :         return KRB5KRB_AP_ERR_MODIFIED;
     497             :     }
     498           0 :     return 0;
     499             : }
     500             : 
     501             : 
     502             : /*
     503             :  * Verify referral data
     504             :  */
     505             : 
     506             : 
     507             : static krb5_error_code
     508           0 : check_client_referral(krb5_context context,
     509             :                       krb5_kdc_rep *rep,
     510             :                       krb5_const_principal requested,
     511             :                       krb5_const_principal mapped,
     512             :                       krb5_keyblock const * key)
     513             : {
     514           0 :     if (krb5_principal_compare(context, requested, mapped) == FALSE) {
     515           0 :         krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
     516           0 :                                N_("Not same client principal returned "
     517             :                                   "as requested", ""));
     518           0 :         return KRB5KRB_AP_ERR_MODIFIED;
     519             :     }
     520           0 :     return 0;
     521             : }
     522             : 
     523             : 
     524             : static krb5_error_code KRB5_CALLCONV
     525       13985 : decrypt_tkt (krb5_context context,
     526             :              krb5_keyblock *key,
     527             :              krb5_key_usage usage,
     528             :              krb5_const_pointer decrypt_arg,
     529             :              krb5_kdc_rep *dec_rep)
     530             : {
     531             :     krb5_error_code ret;
     532             :     krb5_data data;
     533             :     size_t size;
     534             :     krb5_crypto crypto;
     535             : 
     536       13985 :     ret = krb5_crypto_init(context, key, 0, &crypto);
     537       13985 :     if (ret)
     538           0 :         return ret;
     539             : 
     540       13985 :     ret = krb5_decrypt_EncryptedData (context,
     541             :                                       crypto,
     542             :                                       usage,
     543       13985 :                                       &dec_rep->kdc_rep.enc_part,
     544             :                                       &data);
     545       13985 :     krb5_crypto_destroy(context, crypto);
     546             : 
     547       13985 :     if (ret)
     548           0 :         return ret;
     549             : 
     550       13985 :     ret = decode_EncASRepPart(data.data,
     551             :                               data.length,
     552       13985 :                               &dec_rep->enc_part,
     553             :                               &size);
     554       13985 :     if (ret)
     555           0 :         ret = decode_EncTGSRepPart(data.data,
     556             :                                    data.length,
     557           0 :                                    &dec_rep->enc_part,
     558             :                                    &size);
     559       13985 :     krb5_data_free (&data);
     560       13985 :     if (ret) {
     561           0 :         krb5_set_error_message(context, ret,
     562           0 :                                N_("Failed to decode encpart in ticket", ""));
     563           0 :         return ret;
     564             :     }
     565       13690 :     return 0;
     566             : }
     567             : 
     568             : int
     569       54695 : _krb5_extract_ticket(krb5_context context,
     570             :                      krb5_kdc_rep *rep,
     571             :                      krb5_creds *creds,
     572             :                      krb5_keyblock *key,
     573             :                      krb5_const_pointer keyseed,
     574             :                      krb5_key_usage key_usage,
     575             :                      krb5_addresses *addrs,
     576             :                      unsigned nonce,
     577             :                      unsigned flags,
     578             :                      krb5_decrypt_proc decrypt_proc,
     579             :                      krb5_const_pointer decryptarg)
     580             : {
     581             :     krb5_error_code ret;
     582             :     krb5_principal tmp_principal;
     583       54695 :     size_t len = 0;
     584             :     time_t tmp_time;
     585             :     krb5_timestamp sec_now;
     586             : 
     587             :     /* decrypt */
     588             : 
     589       54695 :     if (decrypt_proc == NULL)
     590       13985 :         decrypt_proc = decrypt_tkt;
     591             : 
     592       54695 :     ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
     593       54695 :     if (ret)
     594           0 :         goto out;
     595             : 
     596             :     /* save session key */
     597             : 
     598       54695 :     creds->session.keyvalue.length = 0;
     599       54695 :     creds->session.keyvalue.data   = NULL;
     600       54695 :     creds->session.keytype = rep->enc_part.key.keytype;
     601      109390 :     ret = krb5_data_copy (&creds->session.keyvalue,
     602       54695 :                           rep->enc_part.key.keyvalue.data,
     603             :                           rep->enc_part.key.keyvalue.length);
     604       54695 :     if (ret) {
     605           0 :         krb5_clear_error_message(context);
     606           0 :         goto out;
     607             :     }
     608             : 
     609             :     /*
     610             :      * HACK:
     611             :      * this is really a ugly hack, to support using the Netbios Domain Name
     612             :      * as realm against windows KDC's, they always return the full realm
     613             :      * based on the DNS Name.
     614             :      */
     615       54695 :     flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
     616       54695 :     flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
     617             : 
     618             :     /* compare client and save */
     619       54695 :     ret = _krb5_principalname2krb5_principal (context,
     620             :                                               &tmp_principal,
     621             :                                               rep->kdc_rep.cname,
     622             :                                               rep->kdc_rep.crealm);
     623       54695 :     if (ret)
     624           0 :         goto out;
     625             : 
     626             :     /* check client referral and save principal */
     627             :     /* anonymous here ? */
     628       53311 :     if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
     629           0 :         ret = check_client_referral(context, rep,
     630           0 :                                     creds->client,
     631             :                                     tmp_principal,
     632           0 :                                     &creds->session);
     633           0 :         if (ret) {
     634           0 :             krb5_free_principal (context, tmp_principal);
     635           0 :             goto out;
     636             :         }
     637             :     }
     638       54695 :     krb5_free_principal (context, creds->client);
     639       54695 :     creds->client = tmp_principal;
     640             : 
     641             :     /* check server referral and save principal */
     642       54695 :     ret = _krb5_principalname2krb5_principal (context,
     643             :                                               &tmp_principal,
     644             :                                               rep->enc_part.sname,
     645             :                                               rep->enc_part.srealm);
     646       54695 :     if (ret)
     647           0 :         goto out;
     648       53311 :     if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
     649           0 :         ret = check_server_referral(context,
     650             :                                     rep,
     651             :                                     flags,
     652           0 :                                     creds->server,
     653             :                                     tmp_principal,
     654             :                                     &creds->session);
     655           0 :         if (ret) {
     656           0 :             krb5_free_principal (context, tmp_principal);
     657           0 :             goto out;
     658             :         }
     659             :     }
     660       54695 :     krb5_free_principal(context, creds->server);
     661       54695 :     creds->server = tmp_principal;
     662             : 
     663             :     /* verify names */
     664       54695 :     if(flags & EXTRACT_TICKET_MATCH_REALM){
     665       12977 :         const char *srealm = krb5_principal_get_realm(context, creds->server);
     666       12977 :         const char *crealm = krb5_principal_get_realm(context, creds->client);
     667             : 
     668       25954 :         if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
     669       12977 :             strcmp(rep->enc_part.srealm, crealm) != 0)
     670             :         {
     671           0 :             ret = KRB5KRB_AP_ERR_MODIFIED;
     672           0 :             krb5_clear_error_message(context);
     673           0 :             goto out;
     674             :         }
     675             :     }
     676             : 
     677             :     /* compare nonces */
     678             : 
     679       54695 :     if (nonce != (unsigned)rep->enc_part.nonce) {
     680           0 :         ret = KRB5KRB_AP_ERR_MODIFIED;
     681           0 :         krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
     682           0 :         goto out;
     683             :     }
     684             : 
     685             :     /* set kdc-offset */
     686             : 
     687       54695 :     krb5_timeofday (context, &sec_now);
     688       54695 :     if (rep->enc_part.flags.initial
     689       13985 :         && (flags & EXTRACT_TICKET_TIMESYNC)
     690       13985 :         && context->kdc_sec_offset == 0
     691       13985 :         && krb5_config_get_bool (context, NULL,
     692             :                                  "libdefaults",
     693             :                                  "kdc_timesync",
     694             :                                  NULL)) {
     695           0 :         context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
     696           0 :         krb5_timeofday (context, &sec_now);
     697             :     }
     698             : 
     699             :     /* check all times */
     700             : 
     701       54695 :     if (rep->enc_part.starttime) {
     702       40710 :         tmp_time = *rep->enc_part.starttime;
     703             :     } else
     704       13985 :         tmp_time = rep->enc_part.authtime;
     705             : 
     706       54695 :     if (creds->times.starttime == 0
     707       54695 :         && abs(tmp_time - sec_now) > context->max_skew) {
     708           0 :         ret = KRB5KRB_AP_ERR_SKEW;
     709           0 :         krb5_set_error_message (context, ret,
     710           0 :                                 N_("time skew (%d) larger than max (%d)", ""),
     711           0 :                                abs(tmp_time - sec_now),
     712           0 :                                (int)context->max_skew);
     713           0 :         goto out;
     714             :     }
     715             : 
     716       54695 :     if (creds->times.starttime != 0
     717           0 :         && tmp_time != creds->times.starttime) {
     718           0 :         krb5_clear_error_message (context);
     719           0 :         ret = KRB5KRB_AP_ERR_MODIFIED;
     720           0 :         goto out;
     721             :     }
     722             : 
     723       54695 :     creds->times.starttime = tmp_time;
     724             : 
     725       54695 :     if (rep->enc_part.renew_till) {
     726          65 :         tmp_time = *rep->enc_part.renew_till;
     727             :     } else
     728       53246 :         tmp_time = 0;
     729             : 
     730       54695 :     if (creds->times.renew_till != 0
     731          35 :         && tmp_time > creds->times.renew_till) {
     732           0 :         krb5_clear_error_message (context);
     733           0 :         ret = KRB5KRB_AP_ERR_MODIFIED;
     734           0 :         goto out;
     735             :     }
     736             : 
     737       54695 :     creds->times.renew_till = tmp_time;
     738             : 
     739       54695 :     creds->times.authtime = rep->enc_part.authtime;
     740             : 
     741       54695 :     if (creds->times.endtime != 0
     742       14035 :         && rep->enc_part.endtime > creds->times.endtime) {
     743           0 :         krb5_clear_error_message (context);
     744           0 :         ret = KRB5KRB_AP_ERR_MODIFIED;
     745           0 :         goto out;
     746             :     }
     747             : 
     748       54695 :     creds->times.endtime  = rep->enc_part.endtime;
     749             : 
     750       54695 :     if(rep->enc_part.caddr)
     751           3 :         krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
     752       54692 :     else if(addrs)
     753       40710 :         krb5_copy_addresses (context, addrs, &creds->addresses);
     754             :     else {
     755       13982 :         creds->addresses.len = 0;
     756       13982 :         creds->addresses.val = NULL;
     757             :     }
     758       54695 :     creds->flags.b = rep->enc_part.flags;
     759             : 
     760       54695 :     creds->authdata.len = 0;
     761       54695 :     creds->authdata.val = NULL;
     762             : 
     763             :     /* extract ticket */
     764       54695 :     ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
     765             :                        &rep->kdc_rep.ticket, &len, ret);
     766       54695 :     if(ret)
     767           0 :         goto out;
     768       54695 :     if (creds->ticket.length != len)
     769           0 :         krb5_abortx(context, "internal error in ASN.1 encoder");
     770       54695 :     creds->second_ticket.length = 0;
     771       54695 :     creds->second_ticket.data   = NULL;
     772             : 
     773             : 
     774       54695 : out:
     775       56079 :     memset (rep->enc_part.key.keyvalue.data, 0,
     776             :             rep->enc_part.key.keyvalue.length);
     777       54695 :     return ret;
     778             : }

Generated by: LCOV version 1.13