LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/gssapi/krb5 - accept_sec_context.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 245 416 58.9 %
Date: 2024-04-21 15:09:00 Functions: 6 9 66.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "gsskrb5_locl.h"
      35             : 
      36             : HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER;
      37             : krb5_keytab _gsskrb5_keytab;
      38             : 
      39             : static krb5_error_code
      40           0 : validate_keytab(krb5_context context, const char *name, krb5_keytab *id)
      41             : {
      42           0 :     krb5_error_code ret;
      43             : 
      44           0 :     ret = krb5_kt_resolve(context, name, id);
      45           0 :     if (ret)
      46           0 :         return ret;
      47             : 
      48           0 :     ret = krb5_kt_have_content(context, *id);
      49           0 :     if (ret) {
      50           0 :         krb5_kt_close(context, *id);
      51           0 :         *id = NULL;
      52             :     }
      53             : 
      54           0 :     return ret;
      55             : }
      56             : 
      57             : OM_uint32
      58           0 : _gsskrb5_register_acceptor_identity(OM_uint32 *min_stat, const char *identity)
      59             : {
      60           0 :     krb5_context context;
      61           0 :     krb5_error_code ret;
      62             : 
      63           0 :     *min_stat = 0;
      64             : 
      65           0 :     ret = _gsskrb5_init(&context);
      66           0 :     if(ret)
      67           0 :         return GSS_S_FAILURE;
      68             : 
      69           0 :     HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);
      70             : 
      71           0 :     if(_gsskrb5_keytab != NULL) {
      72           0 :         krb5_kt_close(context, _gsskrb5_keytab);
      73           0 :         _gsskrb5_keytab = NULL;
      74             :     }
      75           0 :     if (identity == NULL) {
      76           0 :         ret = krb5_kt_default(context, &_gsskrb5_keytab);
      77             :     } else {
      78             :         /*
      79             :          * First check if we can the keytab as is and if it has content...
      80             :          */
      81           0 :         ret = validate_keytab(context, identity, &_gsskrb5_keytab);
      82             :         /*
      83             :          * if it doesn't, lets prepend FILE: and try again
      84             :          */
      85           0 :         if (ret) {
      86           0 :             char *p = NULL;
      87           0 :             ret = asprintf(&p, "FILE:%s", identity);
      88           0 :             if(ret < 0 || p == NULL) {
      89           0 :                 HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
      90           0 :                 return GSS_S_FAILURE;
      91             :             }
      92           0 :             ret = validate_keytab(context, p, &_gsskrb5_keytab);
      93           0 :             free(p);
      94             :         }
      95             :     }
      96           0 :     HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
      97           0 :     if(ret) {
      98           0 :         *min_stat = ret;
      99           0 :         return GSS_S_FAILURE;
     100             :     }
     101           0 :     return GSS_S_COMPLETE;
     102             : }
     103             : 
     104             : void
     105      127971 : _gsskrb5i_is_cfx(krb5_context context, gsskrb5_ctx ctx, int acceptor)
     106             : {
     107        2642 :     krb5_keyblock *key;
     108             : 
     109      127971 :     if (acceptor) {
     110      104358 :         if (ctx->auth_context->local_subkey)
     111       51249 :             key = ctx->auth_context->local_subkey;
     112             :         else
     113       52228 :             key = ctx->auth_context->remote_subkey;
     114             :     } else {
     115       23613 :         if (ctx->auth_context->remote_subkey)
     116       22733 :             key = ctx->auth_context->remote_subkey;
     117             :         else
     118           0 :             key = ctx->auth_context->local_subkey;
     119             :     }
     120      127971 :     if (key == NULL)
     121           0 :         key = ctx->auth_context->keyblock;
     122             : 
     123      127971 :     if (key == NULL)
     124           0 :         return;
     125             : 
     126      127971 :     switch (key->keytype) {
     127        4418 :     case ETYPE_DES_CBC_CRC:
     128             :     case ETYPE_DES_CBC_MD4:
     129             :     case ETYPE_DES_CBC_MD5:
     130             :     case ETYPE_DES3_CBC_MD5:
     131             :     case ETYPE_OLD_DES3_CBC_SHA1:
     132             :     case ETYPE_DES3_CBC_SHA1:
     133             :     case ETYPE_ARCFOUR_HMAC_MD5:
     134             :     case ETYPE_ARCFOUR_HMAC_MD5_56:
     135        4418 :         break;
     136      123553 :     default :
     137      123553 :         ctx->more_flags |= IS_CFX;
     138             : 
     139      123553 :         if ((acceptor && ctx->auth_context->local_subkey) ||
     140       22471 :             (!acceptor && ctx->auth_context->remote_subkey))
     141       72997 :             ctx->more_flags |= ACCEPTOR_SUBKEY;
     142      120911 :         break;
     143             :     }
     144      127971 :     if (ctx->crypto)
     145       52130 :         krb5_crypto_destroy(context, ctx->crypto);
     146             :     /* XXX We really shouldn't ignore this; will come back to this */
     147      127971 :     (void) krb5_crypto_init(context, key, 0, &ctx->crypto);
     148             : }
     149             : 
     150             : 
     151             : static OM_uint32
     152       48843 : gsskrb5_accept_delegated_token(OM_uint32 *minor_status,
     153             :                                gsskrb5_ctx ctx,
     154             :                                krb5_context context,
     155             :                                gss_cred_id_t *delegated_cred_handle)
     156             : {
     157       48843 :     krb5_ccache ccache = NULL;
     158         881 :     krb5_error_code kret;
     159       48843 :     int32_t ac_flags, ret = GSS_S_COMPLETE;
     160         881 :     gsskrb5_cred handle;
     161             : 
     162       48843 :     *minor_status = 0;
     163             : 
     164             :     /* XXX Create a new delegated_cred_handle? */
     165       48843 :     if (delegated_cred_handle == NULL)
     166           0 :         return GSS_S_COMPLETE;
     167             : 
     168       48843 :     *delegated_cred_handle = NULL;
     169       48843 :     kret = krb5_cc_resolve(context, "MEMORY:anonymous", &ccache);
     170       48843 :     if (kret == 0)
     171       48843 :         kret = krb5_cc_initialize(context, ccache, ctx->source);
     172       48843 :     if (kret == 0) {
     173       48843 :         (void) krb5_auth_con_removeflags(context,
     174             :                                          ctx->auth_context,
     175             :                                          KRB5_AUTH_CONTEXT_DO_TIME,
     176             :                                          &ac_flags);
     177       48843 :         kret = krb5_rd_cred2(context,
     178             :                              ctx->auth_context,
     179             :                              ccache,
     180             :                              &ctx->fwd_data);
     181       48843 :         (void) krb5_auth_con_setflags(context,
     182             :                                       ctx->auth_context,
     183             :                                       ac_flags);
     184             :     }
     185       48843 :     if (kret) {
     186           0 :         ctx->flags &= ~GSS_C_DELEG_FLAG;
     187           0 :         ret = GSS_S_FAILURE;
     188           0 :         *minor_status = kret;
     189           0 :         goto out;
     190             :     }
     191             : 
     192       48843 :     ret = _gsskrb5_krb5_import_cred(minor_status,
     193             :                                     &ccache,
     194             :                                     NULL,
     195             :                                     NULL,
     196             :                                     delegated_cred_handle);
     197       48843 :     if (ret != GSS_S_COMPLETE)
     198           0 :         goto out;
     199             : 
     200       48843 :     handle = (gsskrb5_cred) *delegated_cred_handle;
     201       48843 :     handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
     202             : 
     203             :     /*
     204             :      * A root TGT is one of the form krbtgt/REALM@SAME-REALM.
     205             :      *
     206             :      * A destination TGT is a root TGT for the same realm as the acceptor
     207             :      * service's realm.
     208             :      *
     209             :      * Normally clients delegate a root TGT for the client's realm.
     210             :      *
     211             :      * In some deployments clients may want to delegate destination TGTs as
     212             :      * a form of constrained delegation: so that the destination service
     213             :      * cannot use the delegated credential to impersonate the client
     214             :      * principal to services in its home realm (due to KDC lineage/transit
     215             :      * checks).  In those deployments there may not even be a route back to
     216             :      * the KDCs of the client's realm, and attempting to use a
     217             :      * non-destination TGT might even lead to timeouts.
     218             :      *
     219             :      * We could simply pretend not to have obtained a credential, except
     220             :      * that a) we don't (yet) have an app name here for the appdefault we
     221             :      * need to check, b) the application really wants to be able to log a
     222             :      * message about the delegated credential being no good.
     223             :      *
     224             :      * Thus we leave it to _gsskrb5_store_cred_into2() to decide what to do
     225             :      * with non-destination TGTs.  To do that, it needs the realm of the
     226             :      * acceptor service, which we record here.
     227             :      */
     228       49724 :     handle->destination_realm =
     229       48843 :         strdup(krb5_principal_get_realm(context, ctx->target));
     230       48843 :     if (handle->destination_realm == NULL) {
     231           0 :         _gsskrb5_release_cred(minor_status, delegated_cred_handle);
     232           0 :         *minor_status = krb5_enomem(context);
     233           0 :         ret = GSS_S_FAILURE;
     234           0 :         goto out;
     235             :     }
     236             : 
     237       48843 : out:
     238       48843 :     if (ccache) {
     239           0 :         krb5_cc_close(context, ccache);
     240             :     }
     241       48843 :     return ret;
     242             : }
     243             : 
     244             : static OM_uint32
     245       52228 : gsskrb5_acceptor_ready(OM_uint32 * minor_status,
     246             :                        gsskrb5_ctx ctx,
     247             :                        krb5_context context,
     248             :                        gss_cred_id_t *delegated_cred_handle)
     249             : {
     250         881 :     OM_uint32 ret;
     251         881 :     int32_t seq_number;
     252       52228 :     int is_cfx = 0;
     253             : 
     254       52228 :     krb5_auth_con_getremoteseqnumber (context,
     255             :                                       ctx->auth_context,
     256             :                                       &seq_number);
     257             : 
     258       52228 :     _gsskrb5i_is_cfx(context, ctx, 1);
     259       52228 :     is_cfx = (ctx->more_flags & IS_CFX);
     260             : 
     261       52228 :     ret = _gssapi_msg_order_create(minor_status,
     262             :                                    &ctx->order,
     263             :                                    _gssapi_msg_order_f(ctx->flags),
     264             :                                    seq_number, 0, is_cfx);
     265       52228 :     if (ret)
     266           0 :         return ret;
     267             : 
     268             :     /*
     269             :      * If requested, set local sequence num to remote sequence if this
     270             :      * isn't a mutual authentication context
     271             :      */
     272       52228 :     if (!(ctx->flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(ctx->flags)) {
     273          98 :         krb5_auth_con_setlocalseqnumber(context,
     274             :                                         ctx->auth_context,
     275             :                                         seq_number);
     276             :     }
     277             : 
     278             :     /*
     279             :      * We should handle the delegation ticket, in case it's there
     280             :      */
     281       52228 :     if (ctx->fwd_data.length > 0 && (ctx->flags & GSS_C_DELEG_FLAG)) {
     282       48843 :         ret = gsskrb5_accept_delegated_token(minor_status,
     283             :                                              ctx,
     284             :                                              context,
     285             :                                              delegated_cred_handle);
     286       48843 :         if (ret != GSS_S_COMPLETE)
     287           0 :             return ret;
     288             :     } else {
     289             :         /* Well, looks like it wasn't there after all */
     290        3385 :         ctx->flags &= ~GSS_C_DELEG_FLAG;
     291             :     }
     292             : 
     293       52228 :     ctx->state = ACCEPTOR_READY;
     294       52228 :     ctx->more_flags |= OPEN;
     295             : 
     296       52228 :     return GSS_S_COMPLETE;
     297             : }
     298             : 
     299             : static OM_uint32
     300           0 : send_error_token(OM_uint32 *minor_status,
     301             :                  krb5_context context,
     302             :                  krb5_error_code kret,
     303             :                  krb5_principal server,
     304             :                  krb5_data *indata,
     305             :                  gss_buffer_t output_token)
     306             : {
     307           0 :     krb5_principal ap_req_server = NULL;
     308           0 :     krb5_error_code ret;
     309           0 :     krb5_data outbuf;
     310             :     /* this e_data value encodes KERB_AP_ERR_TYPE_SKEW_RECOVERY which
     311             :        tells windows to try again with the corrected timestamp. See
     312             :        [MS-KILE] 2.2.1 KERB-ERROR-DATA */
     313           0 :     krb5_data e_data = { 7, rk_UNCONST("\x30\x05\xa1\x03\x02\x01\x02") };
     314             : 
     315             :     /* build server from request if the acceptor had not selected one */
     316           0 :     if (server == NULL) {
     317           0 :         AP_REQ ap_req;
     318             : 
     319           0 :         ret = krb5_decode_ap_req(context, indata, &ap_req);
     320           0 :         if (ret) {
     321           0 :             *minor_status = ret;
     322           0 :             return GSS_S_FAILURE;
     323             :         }
     324           0 :         ret = _krb5_principalname2krb5_principal(context,
     325             :                                                   &ap_req_server,
     326             :                                                   ap_req.ticket.sname,
     327             :                                                   ap_req.ticket.realm);
     328           0 :         free_AP_REQ(&ap_req);
     329           0 :         if (ret) {
     330           0 :             *minor_status = ret;
     331           0 :             return GSS_S_FAILURE;
     332             :         }
     333           0 :         server = ap_req_server;
     334             :     }
     335             : 
     336           0 :     ret = krb5_mk_error(context, kret, NULL, &e_data, NULL,
     337             :                         server, NULL, NULL, &outbuf);
     338           0 :     if (ap_req_server)
     339           0 :         krb5_free_principal(context, ap_req_server);
     340           0 :     if (ret) {
     341           0 :         *minor_status = ret;
     342           0 :         return GSS_S_FAILURE;
     343             :     }
     344             : 
     345           0 :     ret = _gsskrb5_encapsulate(minor_status,
     346             :                                &outbuf,
     347             :                                output_token,
     348             :                                "\x03\x00",
     349             :                                GSS_KRB5_MECHANISM);
     350           0 :     krb5_data_free (&outbuf);
     351           0 :     if (ret)
     352           0 :         return ret;
     353             : 
     354           0 :     *minor_status = 0;
     355           0 :     return GSS_S_CONTINUE_NEEDED;
     356             : }
     357             : 
     358             : 
     359             : static OM_uint32
     360       52247 : gsskrb5_acceptor_start(OM_uint32 * minor_status,
     361             :                        gsskrb5_ctx ctx,
     362             :                        krb5_context context,
     363             :                        gss_const_cred_id_t acceptor_cred_handle,
     364             :                        const gss_buffer_t input_token_buffer,
     365             :                        const gss_channel_bindings_t input_chan_bindings,
     366             :                        gss_name_t * src_name,
     367             :                        gss_OID * mech_type,
     368             :                        gss_buffer_t output_token,
     369             :                        OM_uint32 * ret_flags,
     370             :                        OM_uint32 * time_rec,
     371             :                        gss_cred_id_t * delegated_cred_handle)
     372             : {
     373         881 :     krb5_error_code kret;
     374       52247 :     OM_uint32 ret = GSS_S_COMPLETE;
     375         881 :     krb5_data indata;
     376         881 :     krb5_flags ap_options;
     377       52247 :     krb5_keytab keytab = NULL;
     378       52247 :     int is_cfx = 0;
     379       52247 :     int close_kt = 0;
     380       52247 :     const gsskrb5_cred acceptor_cred = (gsskrb5_cred)acceptor_cred_handle;
     381             : 
     382             :     /*
     383             :      * We may, or may not, have an escapsulation.
     384             :      */
     385       52247 :     ret = _gsskrb5_decapsulate (minor_status,
     386             :                                 input_token_buffer,
     387             :                                 &indata,
     388             :                                 "\x01\x00",
     389             :                                 GSS_KRB5_MECHANISM);
     390             : 
     391       52247 :     if (ret) {
     392             :         /* Could be a raw AP-REQ (check for APPLICATION tag) */
     393       31976 :         if (input_token_buffer->length == 0 ||
     394       31976 :             ((const uint8_t *)input_token_buffer->value)[0] != 0x6E) {
     395           0 :             *minor_status = ASN1_MISPLACED_FIELD;
     396           0 :             return GSS_S_DEFECTIVE_TOKEN;
     397             :         }
     398             : 
     399             :         /* Assume that there is no OID wrapping. */
     400       31976 :         indata.length   = input_token_buffer->length;
     401       31976 :         indata.data     = input_token_buffer->value;
     402             :     }
     403             : 
     404             :     /*
     405             :      * We need to get our keytab
     406             :      */
     407       52247 :     if (acceptor_cred == NULL) {
     408           0 :         HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);
     409           0 :         if (_gsskrb5_keytab != NULL) {
     410           0 :             char *name = NULL;
     411           0 :             kret = krb5_kt_get_full_name(context, _gsskrb5_keytab, &name);
     412           0 :             if (kret == 0) {
     413           0 :                 kret = krb5_kt_resolve(context, name, &keytab);
     414           0 :                 krb5_xfree(name);
     415             :             }
     416           0 :             if (kret == 0)
     417           0 :                 close_kt = 1;
     418             :             else
     419           0 :                 keytab = NULL;
     420             :         }
     421             :         HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
     422       52247 :     } else if (acceptor_cred->keytab != NULL) {
     423       52247 :         keytab = acceptor_cred->keytab;
     424             :     }
     425             : 
     426             :     /*
     427             :      * We need to check the ticket and create the AP-REP packet
     428             :      */
     429             : 
     430             :     {
     431       52247 :         krb5_rd_req_in_ctx in = NULL;
     432       52247 :         krb5_rd_req_out_ctx out = NULL;
     433       52247 :         krb5_principal server = NULL;
     434             : 
     435       52247 :         if (acceptor_cred)
     436       52247 :             server = acceptor_cred->principal;
     437             : 
     438       52247 :         kret = krb5_rd_req_in_ctx_alloc(context, &in);
     439       52247 :         if (kret == 0)
     440       52247 :             kret = krb5_rd_req_in_set_keytab(context, in, keytab);
     441       52247 :         if (kret) {
     442           0 :             if (in)
     443           0 :                 krb5_rd_req_in_ctx_free(context, in);
     444           0 :             if (close_kt)
     445           0 :                 krb5_kt_close(context, keytab);
     446           0 :             *minor_status = kret;
     447          19 :             return GSS_S_FAILURE;
     448             :         }
     449             : 
     450       53128 :         kret = krb5_rd_req_ctx(context,
     451       52247 :                                &ctx->auth_context,
     452             :                                &indata,
     453             :                                server,
     454             :                                in, &out);
     455       52247 :         krb5_rd_req_in_ctx_free(context, in);
     456       52247 :         if (close_kt)
     457           0 :             krb5_kt_close(context, keytab);
     458       52247 :         if (kret == KRB5KRB_AP_ERR_SKEW || kret == KRB5KRB_AP_ERR_TKT_NYV) {
     459             :             /*
     460             :              * No reply in non-MUTUAL mode, but we don't know that its
     461             :              * non-MUTUAL mode yet, thats inside the 8003 checksum, so
     462             :              * lets only send the error token on clock skew, that
     463             :              * limit when send error token for non-MUTUAL.
     464             :              */
     465           0 :             krb5_auth_con_free(context, ctx->auth_context);
     466           0 :             krb5_auth_con_free(context, ctx->deleg_auth_context);
     467           0 :             ctx->deleg_auth_context = NULL;
     468           0 :             ctx->auth_context = NULL;
     469           0 :             return send_error_token(minor_status, context, kret,
     470             :                                     server, &indata, output_token);
     471       52247 :         } else if (kret) {
     472          19 :             *minor_status = kret;
     473          19 :             return GSS_S_FAILURE;
     474             :         }
     475             : 
     476             :         /*
     477             :          * we need to remember some data on the context_handle.
     478             :          */
     479       52228 :         kret = krb5_rd_req_out_get_ap_req_options(context, out,
     480             :                                                   &ap_options);
     481       52228 :         if (kret == 0)
     482       52228 :             kret = krb5_rd_req_out_get_ticket(context, out,
     483       52228 :                                               &ctx->ticket);
     484       52228 :         if (kret == 0)
     485       52228 :             kret = krb5_rd_req_out_get_keyblock(context, out,
     486             :                                                 &ctx->service_keyblock);
     487       52228 :         ctx->endtime = ctx->ticket->ticket.endtime;
     488             : 
     489       52228 :         krb5_rd_req_out_ctx_free(context, out);
     490       52228 :         if (kret) {
     491           0 :             ret = GSS_S_FAILURE;
     492           0 :             *minor_status = kret;
     493           0 :             return ret;
     494             :         }
     495             :     }
     496             : 
     497             : 
     498             :     /*
     499             :      * We need to copy the principal names to the context and the
     500             :      * calling layer.
     501             :      */
     502       53109 :     kret = krb5_copy_principal(context,
     503       52228 :                                ctx->ticket->client,
     504             :                                &ctx->source);
     505       52228 :     if (kret) {
     506           0 :         ret = GSS_S_FAILURE;
     507           0 :         *minor_status = kret;
     508           0 :         return ret;
     509             :     }
     510             : 
     511       53109 :     kret = krb5_copy_principal(context,
     512       52228 :                                ctx->ticket->server,
     513             :                                &ctx->target);
     514       52228 :     if (kret) {
     515           0 :         ret = GSS_S_FAILURE;
     516           0 :         *minor_status = kret;
     517           0 :         return ret;
     518             :     }
     519             : 
     520             :     /*
     521             :      * We need to setup some compat stuff, this assumes that
     522             :      * context_handle->target is already set.
     523             :      */
     524       52228 :     ret = _gss_DES3_get_mic_compat(minor_status, ctx, context);
     525       52228 :     if (ret)
     526           0 :         return ret;
     527             : 
     528       52228 :     if (src_name != NULL) {
     529       53109 :         kret = krb5_copy_principal (context,
     530       52228 :                                     ctx->ticket->client,
     531             :                                     (gsskrb5_name*)src_name);
     532       52228 :         if (kret) {
     533           0 :             ret = GSS_S_FAILURE;
     534           0 :             *minor_status = kret;
     535           0 :             return ret;
     536             :         }
     537             :     }
     538             : 
     539             :     /*
     540             :      * We need to get the flags out of the 8003 checksum.
     541             :      */
     542             : 
     543             :     {
     544         881 :         krb5_authenticator authenticator;
     545             : 
     546       52228 :         kret = krb5_auth_con_getauthenticator(context,
     547             :                                               ctx->auth_context,
     548             :                                               &authenticator);
     549       52228 :         if(kret) {
     550           0 :             ret = GSS_S_FAILURE;
     551           0 :             *minor_status = kret;
     552           0 :             return ret;
     553             :         }
     554             : 
     555       52228 :         if (authenticator->cksum != NULL
     556       52196 :             && authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) {
     557       52130 :             ret = _gsskrb5_verify_8003_checksum(context,
     558             :                                                 minor_status,
     559             :                                                 input_chan_bindings,
     560             :                                                 authenticator,
     561             :                                                 &ctx->flags,
     562             :                                                 &ctx->fwd_data);
     563             : 
     564       52130 :             if (ret) {
     565           0 :                 krb5_free_authenticator(context, &authenticator);
     566           0 :                 return ret;
     567             :             }
     568             :         } else {
     569          98 :             if (authenticator->cksum != NULL) {
     570           0 :                 krb5_crypto crypto;
     571             : 
     572          66 :                 kret = krb5_crypto_init(context,
     573          66 :                                         ctx->auth_context->keyblock,
     574             :                                         0, &crypto);
     575          66 :                 if (kret) {
     576           0 :                     krb5_free_authenticator(context, &authenticator);
     577           0 :                     ret = GSS_S_FAILURE;
     578           0 :                     *minor_status = kret;
     579           0 :                     return ret;
     580             :                 }
     581             : 
     582             :                 /*
     583             :                  * Windows accepts Samba3's use of a kerberos, rather than
     584             :                  * GSSAPI checksum here
     585             :                  */
     586             : 
     587          66 :                 _krb5_crypto_set_flags(context, crypto, KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM);
     588          66 :                 kret = krb5_verify_checksum(context,
     589             :                                             crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0,
     590          66 :                                             authenticator->cksum);
     591          66 :                 krb5_crypto_destroy(context, crypto);
     592             : 
     593          66 :                 if (kret) {
     594           0 :                     krb5_free_authenticator(context, &authenticator);
     595           0 :                     ret = GSS_S_BAD_SIG;
     596           0 :                     *minor_status = kret;
     597           0 :                     return ret;
     598             :                 }
     599             :             }
     600             : 
     601             :             /*
     602             :              * If there is no checksum or a kerberos checksum (which Windows
     603             :              * and Samba accept), we use the ap_options to guess the mutual
     604             :              * flag.
     605             :              */
     606             : 
     607          98 :             ctx->flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
     608          98 :             if (ap_options & AP_OPTS_MUTUAL_REQUIRED)
     609           0 :                 ctx->flags |= GSS_C_MUTUAL_FLAG;
     610             :         }
     611       52228 :         krb5_free_authenticator(context, &authenticator);
     612             :     }
     613             : 
     614       52228 :     if(ctx->flags & GSS_C_MUTUAL_FLAG) {
     615         881 :         krb5_data outbuf;
     616       52130 :         int use_subkey = 0;
     617             : 
     618       52130 :         _gsskrb5i_is_cfx(context, ctx, 1);
     619       52130 :         is_cfx = (ctx->more_flags & IS_CFX);
     620             : 
     621       52130 :         if (is_cfx || (ap_options & AP_OPTS_USE_SUBKEY)) {
     622       51249 :             use_subkey = 1;
     623             :         } else {
     624           0 :             krb5_keyblock *rkey;
     625             : 
     626             :             /*
     627             :              * If there is a initiator subkey, copy that to acceptor
     628             :              * subkey to match Windows behavior
     629             :              */
     630           0 :             kret = krb5_auth_con_getremotesubkey(context,
     631             :                                                  ctx->auth_context,
     632             :                                                  &rkey);
     633           0 :             if (kret == 0) {
     634           0 :                 kret = krb5_auth_con_setlocalsubkey(context,
     635             :                                                     ctx->auth_context,
     636             :                                                     rkey);
     637           0 :                 if (kret == 0)
     638           0 :                     use_subkey = 1;
     639             :             }
     640           0 :             krb5_free_keyblock(context, rkey);
     641             :         }
     642       51249 :         if (use_subkey) {
     643       52130 :             ctx->more_flags |= ACCEPTOR_SUBKEY;
     644       52130 :             krb5_auth_con_addflags(context, ctx->auth_context,
     645             :                                    KRB5_AUTH_CONTEXT_USE_SUBKEY,
     646             :                                    NULL);
     647             :         }
     648             : 
     649       52130 :         kret = krb5_mk_rep(context,
     650             :                            ctx->auth_context,
     651             :                            &outbuf);
     652       52130 :         if (kret) {
     653           0 :             *minor_status = kret;
     654           0 :             return GSS_S_FAILURE;
     655             :         }
     656             : 
     657       52130 :         if (IS_DCE_STYLE(ctx)) {
     658       31959 :             output_token->length = outbuf.length;
     659       31959 :             output_token->value = outbuf.data;
     660             :         } else {
     661       20171 :             ret = _gsskrb5_encapsulate(minor_status,
     662             :                                        &outbuf,
     663             :                                        output_token,
     664             :                                        "\x02\x00",
     665             :                                        GSS_KRB5_MECHANISM);
     666       20171 :             krb5_data_free (&outbuf);
     667       20171 :             if (ret)
     668           0 :                 return ret;
     669             :         }
     670             :     }
     671             : 
     672       52228 :     ctx->flags |= GSS_C_TRANS_FLAG;
     673             : 
     674             :     /* Remember the flags */
     675             : 
     676       52228 :     ctx->endtime = ctx->ticket->ticket.endtime;
     677       52228 :     ctx->more_flags |= OPEN;
     678             : 
     679       52228 :     if (mech_type)
     680       52228 :         *mech_type = GSS_KRB5_MECHANISM;
     681             : 
     682       52228 :     if (time_rec) {
     683       52228 :         ret = _gsskrb5_lifetime_left(minor_status,
     684             :                                      context,
     685       51347 :                                      ctx->endtime,
     686             :                                      time_rec);
     687       52228 :         if (ret) {
     688           0 :             return ret;
     689             :         }
     690             :     }
     691             : 
     692             :     /*
     693             :      * When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from
     694             :      * the client.
     695             :      */
     696       52228 :     if (IS_DCE_STYLE(ctx)) {
     697             :         /*
     698             :          * Return flags to caller, but we haven't processed
     699             :          * delgations yet
     700             :          */
     701       31959 :         if (ret_flags)
     702       31959 :             *ret_flags = (ctx->flags & ~GSS_C_DELEG_FLAG);
     703             : 
     704       31959 :         ctx->state = ACCEPTOR_WAIT_FOR_DCESTYLE;
     705       31959 :         return GSS_S_CONTINUE_NEEDED;
     706             :     }
     707             : 
     708       20269 :     ret = gsskrb5_acceptor_ready(minor_status, ctx, context,
     709             :                                  delegated_cred_handle);
     710             : 
     711       20269 :     if (ret_flags)
     712       20269 :         *ret_flags = ctx->flags;
     713             : 
     714       19484 :     return ret;
     715             : }
     716             : 
     717             : static OM_uint32
     718       31959 : acceptor_wait_for_dcestyle(OM_uint32 * minor_status,
     719             :                            gsskrb5_ctx ctx,
     720             :                            krb5_context context,
     721             :                            gss_const_cred_id_t acceptor_cred_handle,
     722             :                            const gss_buffer_t input_token_buffer,
     723             :                            const gss_channel_bindings_t input_chan_bindings,
     724             :                            gss_name_t * src_name,
     725             :                            gss_OID * mech_type,
     726             :                            gss_buffer_t output_token,
     727             :                            OM_uint32 * ret_flags,
     728             :                            OM_uint32 * time_rec,
     729             :                            gss_cred_id_t * delegated_cred_handle)
     730             : {
     731          96 :     OM_uint32 ret;
     732          96 :     krb5_error_code kret;
     733          96 :     krb5_data inbuf;
     734          96 :     int32_t r_seq_number, l_seq_number;
     735             : 
     736             :     /*
     737             :      * We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP
     738             :      */
     739             : 
     740       31959 :     inbuf.length = input_token_buffer->length;
     741       31959 :     inbuf.data = input_token_buffer->value;
     742             : 
     743             :     /*
     744             :      * We need to remeber the old remote seq_number, then check if the
     745             :      * client has replied with our local seq_number, and then reset
     746             :      * the remote seq_number to the old value
     747             :      */
     748             :     {
     749       31959 :         kret = krb5_auth_con_getlocalseqnumber(context,
     750             :                                                ctx->auth_context,
     751             :                                                &l_seq_number);
     752       31959 :         if (kret) {
     753           0 :             *minor_status = kret;
     754           0 :             return GSS_S_FAILURE;
     755             :         }
     756             : 
     757       31959 :         kret = krb5_auth_con_getremoteseqnumber(context,
     758             :                                                 ctx->auth_context,
     759             :                                                 &r_seq_number);
     760       31959 :         if (kret) {
     761           0 :             *minor_status = kret;
     762           0 :             return GSS_S_FAILURE;
     763             :         }
     764             : 
     765       31959 :         kret = krb5_auth_con_setremoteseqnumber(context,
     766             :                                                 ctx->auth_context,
     767             :                                                 l_seq_number);
     768       31959 :         if (kret) {
     769           0 :             *minor_status = kret;
     770           0 :             return GSS_S_FAILURE;
     771             :         }
     772             :     }
     773             : 
     774             :     /*
     775             :      * We need to verify the AP_REP, but we need to flag that this is
     776             :      * DCE_STYLE, so don't check the timestamps this time, but put the
     777             :      * flag DO_TIME back afterward.
     778             :     */
     779             :     {
     780          96 :         krb5_ap_rep_enc_part *repl;
     781          96 :         int32_t auth_flags;
     782             : 
     783       31959 :         krb5_auth_con_removeflags(context,
     784             :                                   ctx->auth_context,
     785             :                                   KRB5_AUTH_CONTEXT_DO_TIME,
     786             :                                   &auth_flags);
     787             : 
     788       31959 :         kret = krb5_rd_rep(context, ctx->auth_context, &inbuf, &repl);
     789       31959 :         if (kret) {
     790           0 :             *minor_status = kret;
     791           0 :             return GSS_S_FAILURE;
     792             :         }
     793       31959 :         krb5_free_ap_rep_enc_part(context, repl);
     794       31959 :         krb5_auth_con_setflags(context, ctx->auth_context, auth_flags);
     795             :     }
     796             : 
     797             :     /* We need to check the liftime */
     798             :     {
     799          96 :         OM_uint32 lifetime_rec;
     800             : 
     801       32055 :         ret = _gsskrb5_lifetime_left(minor_status,
     802             :                                      context,
     803       31959 :                                      ctx->endtime,
     804             :                                      &lifetime_rec);
     805       31959 :         if (ret) {
     806           0 :             return ret;
     807             :         }
     808       31959 :         if (lifetime_rec == 0) {
     809           0 :             return GSS_S_CONTEXT_EXPIRED;
     810             :         }
     811             : 
     812       31959 :         if (time_rec) *time_rec = lifetime_rec;
     813             :     }
     814             : 
     815             :     /* We need to give the caller the flags which are in use */
     816       31959 :     if (ret_flags) *ret_flags = ctx->flags;
     817             : 
     818       31959 :     if (src_name) {
     819       32055 :         kret = krb5_copy_principal(context,
     820       31959 :                                    ctx->source,
     821             :                                    (gsskrb5_name*)src_name);
     822       31959 :         if (kret) {
     823           0 :             *minor_status = kret;
     824           0 :             return GSS_S_FAILURE;
     825             :         }
     826             :     }
     827             : 
     828             :     /*
     829             :      * After the krb5_rd_rep() the remote and local seq_number should
     830             :      * be the same, because the client just replies the seq_number
     831             :      * from our AP-REP in its AP-REP, but then the client uses the
     832             :      * seq_number from its AP-REQ for GSS_wrap()
     833             :      */
     834             :     {
     835          96 :         int32_t tmp_r_seq_number, tmp_l_seq_number;
     836             : 
     837       31959 :         kret = krb5_auth_con_getremoteseqnumber(context,
     838             :                                                 ctx->auth_context,
     839             :                                                 &tmp_r_seq_number);
     840       31959 :         if (kret) {
     841           0 :             *minor_status = kret;
     842           0 :             return GSS_S_FAILURE;
     843             :         }
     844             : 
     845       31959 :         kret = krb5_auth_con_getlocalseqnumber(context,
     846             :                                                ctx->auth_context,
     847             :                                                &tmp_l_seq_number);
     848       31959 :         if (kret) {
     849             : 
     850           0 :             *minor_status = kret;
     851           0 :             return GSS_S_FAILURE;
     852             :         }
     853             : 
     854             :         /*
     855             :          * Here we check if the client has responsed with our local seq_number,
     856             :          */
     857       31959 :         if (tmp_r_seq_number != tmp_l_seq_number) {
     858           0 :             return GSS_S_UNSEQ_TOKEN;
     859             :         }
     860             :     }
     861             : 
     862             :     /*
     863             :      * We need to reset the remote seq_number, because the client will use,
     864             :      * the old one for the GSS_wrap() calls
     865             :      */
     866             :     {
     867       31959 :         kret = krb5_auth_con_setremoteseqnumber(context,
     868             :                                                 ctx->auth_context,
     869             :                                                 r_seq_number);
     870       31959 :         if (kret) {
     871           0 :             *minor_status = kret;
     872           0 :             return GSS_S_FAILURE;
     873             :         }
     874             :     }
     875             : 
     876       31959 :     return gsskrb5_acceptor_ready(minor_status, ctx, context,
     877             :                                   delegated_cred_handle);
     878             : }
     879             : 
     880             : 
     881             : OM_uint32 GSSAPI_CALLCONV
     882       84206 : _gsskrb5_accept_sec_context(OM_uint32 * minor_status,
     883             :                             gss_ctx_id_t * context_handle,
     884             :                             gss_const_cred_id_t acceptor_cred_handle,
     885             :                             const gss_buffer_t input_token_buffer,
     886             :                             const gss_channel_bindings_t input_chan_bindings,
     887             :                             gss_name_t * src_name,
     888             :                             gss_OID * mech_type,
     889             :                             gss_buffer_t output_token,
     890             :                             OM_uint32 * ret_flags,
     891             :                             OM_uint32 * time_rec,
     892             :                             gss_cred_id_t * delegated_cred_handle)
     893             : {
     894         977 :     krb5_context context;
     895         977 :     OM_uint32 ret;
     896         977 :     gsskrb5_ctx ctx;
     897             : 
     898       84206 :     GSSAPI_KRB5_INIT(&context);
     899             : 
     900       84206 :     output_token->length = 0;
     901       84206 :     output_token->value = NULL;
     902             : 
     903       84206 :     if (src_name != NULL)
     904       84206 :         *src_name = NULL;
     905       84206 :     if (mech_type)
     906       84206 :         *mech_type = GSS_KRB5_MECHANISM;
     907             : 
     908       84206 :     if (*context_handle == GSS_C_NO_CONTEXT) {
     909       52247 :         ret = _gsskrb5_create_ctx(minor_status,
     910             :                                   context_handle,
     911             :                                   context,
     912             :                                   input_chan_bindings,
     913             :                                   ACCEPTOR_START);
     914       52247 :         if (ret)
     915           0 :             return ret;
     916             :     }
     917             : 
     918       84206 :     ctx = (gsskrb5_ctx)*context_handle;
     919             : 
     920             : 
     921             :     /*
     922             :      * TODO: check the channel_bindings
     923             :      * (above just sets them to krb5 layer)
     924             :      */
     925             : 
     926         977 :     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
     927             : 
     928       84206 :     switch (ctx->state) {
     929       52247 :     case ACCEPTOR_START:
     930       52247 :         ret = gsskrb5_acceptor_start(minor_status,
     931             :                                      ctx,
     932             :                                      context,
     933             :                                      acceptor_cred_handle,
     934             :                                      input_token_buffer,
     935             :                                      input_chan_bindings,
     936             :                                      src_name,
     937             :                                      mech_type,
     938             :                                      output_token,
     939             :                                      ret_flags,
     940             :                                      time_rec,
     941             :                                      delegated_cred_handle);
     942       52247 :         break;
     943       31959 :     case ACCEPTOR_WAIT_FOR_DCESTYLE:
     944       31959 :         ret = acceptor_wait_for_dcestyle(minor_status,
     945             :                                          ctx,
     946             :                                          context,
     947             :                                          acceptor_cred_handle,
     948             :                                          input_token_buffer,
     949             :                                          input_chan_bindings,
     950             :                                          src_name,
     951             :                                          mech_type,
     952             :                                          output_token,
     953             :                                          ret_flags,
     954             :                                          time_rec,
     955             :                                          delegated_cred_handle);
     956       31959 :         break;
     957           0 :     case ACCEPTOR_READY:
     958             :         /*
     959             :          * If we get there, the caller have called
     960             :          * gss_accept_sec_context() one time too many.
     961             :          */
     962           0 :         ret =  GSS_S_BAD_STATUS;
     963           0 :         break;
     964           0 :     default:
     965             :         /* TODO: is this correct here? --metze */
     966           0 :         ret =  GSS_S_BAD_STATUS;
     967           0 :         break;
     968             :     }
     969             : 
     970         977 :     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
     971             : 
     972       84206 :     if (GSS_ERROR(ret)) {
     973           0 :         OM_uint32 min2;
     974          19 :         _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER);
     975             :     }
     976             : 
     977       83229 :     return ret;
     978             : }

Generated by: LCOV version 1.14