LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/gssapi/krb5 - init_sec_context.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 307 482 63.7 %
Date: 2024-04-21 15:09:00 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2008 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             : static OM_uint32
      37             : gsskrb5_set_authorization_data(OM_uint32 *,
      38             :                                krb5_context,
      39             :                                krb5_auth_context,
      40             :                                gss_const_name_t);
      41             : 
      42             : /*
      43             :  * copy the addresses from `input_chan_bindings' (if any) to
      44             :  * the auth context `ac'
      45             :  */
      46             : 
      47             : static OM_uint32
      48      152998 : set_addresses (krb5_context context,
      49             :                krb5_auth_context ac,
      50             :                const gss_channel_bindings_t input_chan_bindings)
      51             : {
      52             :     /* Port numbers are expected to be in application_data.value,
      53             :      * initator's port first */
      54             : 
      55        3862 :     krb5_address initiator_addr, acceptor_addr;
      56        3862 :     krb5_error_code kret;
      57             : 
      58      152998 :     if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS
      59           0 :         || input_chan_bindings->application_data.length !=
      60             :         2 * sizeof(ac->local_port))
      61      149136 :         return 0;
      62             : 
      63           0 :     memset(&initiator_addr, 0, sizeof(initiator_addr));
      64           0 :     memset(&acceptor_addr, 0, sizeof(acceptor_addr));
      65             : 
      66           0 :     ac->local_port =
      67           0 :         *(int16_t *) input_chan_bindings->application_data.value;
      68             : 
      69           0 :     ac->remote_port =
      70           0 :         *((int16_t *) input_chan_bindings->application_data.value + 1);
      71             : 
      72           0 :     kret = _gsskrb5i_address_to_krb5addr(context,
      73             :                                          input_chan_bindings->acceptor_addrtype,
      74             :                                          &input_chan_bindings->acceptor_address,
      75           0 :                                          ac->remote_port,
      76             :                                          &acceptor_addr);
      77           0 :     if (kret)
      78           0 :         return kret;
      79             : 
      80           0 :     kret = _gsskrb5i_address_to_krb5addr(context,
      81             :                                          input_chan_bindings->initiator_addrtype,
      82             :                                          &input_chan_bindings->initiator_address,
      83           0 :                                          ac->local_port,
      84             :                                          &initiator_addr);
      85           0 :     if (kret) {
      86           0 :         krb5_free_address (context, &acceptor_addr);
      87           0 :         return kret;
      88             :     }
      89             : 
      90           0 :     kret = krb5_auth_con_setaddrs(context,
      91             :                                   ac,
      92             :                                   &initiator_addr,  /* local address */
      93             :                                   &acceptor_addr);  /* remote address */
      94             : 
      95           0 :     krb5_free_address (context, &initiator_addr);
      96           0 :     krb5_free_address (context, &acceptor_addr);
      97             : 
      98             : #if 0
      99             :     free(input_chan_bindings->application_data.value);
     100             :     input_chan_bindings->application_data.value = NULL;
     101             :     input_chan_bindings->application_data.length = 0;
     102             : #endif
     103             : 
     104           0 :     return kret;
     105             : }
     106             : 
     107             : OM_uint32
     108       76499 : _gsskrb5_create_ctx(
     109             :         OM_uint32 * minor_status,
     110             :         gss_ctx_id_t * context_handle,
     111             :         krb5_context context,
     112             :         const gss_channel_bindings_t input_chan_bindings,
     113             :         enum gss_ctx_id_t_state state)
     114             : {
     115        1931 :     krb5_error_code kret;
     116        1931 :     gsskrb5_ctx ctx;
     117             : 
     118       76499 :     *context_handle = NULL;
     119             : 
     120       76499 :     ctx = malloc(sizeof(*ctx));
     121       76499 :     if (ctx == NULL) {
     122           0 :         *minor_status = ENOMEM;
     123           0 :         return GSS_S_FAILURE;
     124             :     }
     125       76499 :     ctx->auth_context                = NULL;
     126       76499 :     ctx->deleg_auth_context  = NULL;
     127       76499 :     ctx->source                      = NULL;
     128       76499 :     ctx->target                      = NULL;
     129       76499 :     ctx->kcred                       = NULL;
     130       76499 :     ctx->ccache                      = NULL;
     131       76499 :     ctx->state                       = state;
     132       76499 :     ctx->flags                       = 0;
     133       76499 :     ctx->more_flags          = 0;
     134       76499 :     ctx->service_keyblock    = NULL;
     135       76499 :     ctx->ticket                      = NULL;
     136       76499 :     krb5_data_zero(&ctx->fwd_data);
     137       76499 :     ctx->endtime             = 0;
     138       76499 :     ctx->order                       = NULL;
     139       76499 :     ctx->crypto                      = NULL;
     140        1931 :     HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex);
     141             : 
     142       76499 :     kret = krb5_auth_con_init (context, &ctx->auth_context);
     143       76499 :     if (kret) {
     144           0 :         *minor_status = kret;
     145           0 :         HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
     146           0 :         free(ctx);
     147           0 :         return GSS_S_FAILURE;
     148             :     }
     149             : 
     150       76499 :     kret = krb5_auth_con_init (context, &ctx->deleg_auth_context);
     151       76499 :     if (kret) {
     152           0 :         *minor_status = kret;
     153           0 :         krb5_auth_con_free(context, ctx->auth_context);
     154           0 :         HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
     155           0 :         free(ctx);
     156           0 :         return GSS_S_FAILURE;
     157             :     }
     158             : 
     159       76499 :     kret = set_addresses(context, ctx->auth_context, input_chan_bindings);
     160       76499 :     if (kret) {
     161           0 :         *minor_status = kret;
     162             : 
     163           0 :         krb5_auth_con_free(context, ctx->auth_context);
     164           0 :         krb5_auth_con_free(context, ctx->deleg_auth_context);
     165             : 
     166           0 :         HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
     167           0 :         free(ctx);
     168           0 :         return GSS_S_BAD_BINDINGS;
     169             :     }
     170             : 
     171       76499 :     kret = set_addresses(context, ctx->deleg_auth_context, input_chan_bindings);
     172       76499 :     if (kret) {
     173           0 :         *minor_status = kret;
     174             : 
     175           0 :         krb5_auth_con_free(context, ctx->auth_context);
     176           0 :         krb5_auth_con_free(context, ctx->deleg_auth_context);
     177             : 
     178           0 :         HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
     179           0 :         free(ctx);
     180           0 :         return GSS_S_BAD_BINDINGS;
     181             :     }
     182             : 
     183             :     /*
     184             :      * We need a sequence number
     185             :      */
     186             : 
     187       76499 :     krb5_auth_con_addflags(context,
     188             :                            ctx->auth_context,
     189             :                            KRB5_AUTH_CONTEXT_DO_SEQUENCE |
     190             :                            KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED,
     191             :                            NULL);
     192             : 
     193             :     /*
     194             :      * We need a sequence number
     195             :      */
     196             : 
     197       76499 :     krb5_auth_con_addflags(context,
     198             :                            ctx->deleg_auth_context,
     199             :                            KRB5_AUTH_CONTEXT_DO_SEQUENCE |
     200             :                            KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED,
     201             :                            NULL);
     202             : 
     203       76499 :     *context_handle = (gss_ctx_id_t)ctx;
     204             : 
     205       76499 :     return GSS_S_COMPLETE;
     206             : }
     207             : 
     208             : 
     209             : static OM_uint32
     210       24237 : gsskrb5_get_creds(
     211             :         OM_uint32 * minor_status,
     212             :         krb5_context context,
     213             :         krb5_ccache ccache,
     214             :         gsskrb5_ctx ctx,
     215             :         gss_const_name_t target_name,
     216             :         OM_uint32 time_req,
     217             :         OM_uint32 * time_rec)
     218             : {
     219        1035 :     OM_uint32 ret;
     220        1035 :     krb5_error_code kret;
     221        1035 :     krb5_creds this_cred;
     222        1035 :     OM_uint32 lifetime_rec;
     223             : 
     224       24237 :     if (ctx->target) {
     225           0 :         krb5_free_principal(context, ctx->target);
     226           0 :         ctx->target = NULL;
     227             :     }
     228       24237 :     if (ctx->kcred) {
     229           0 :         krb5_free_creds(context, ctx->kcred);
     230           0 :         ctx->kcred = NULL;
     231             :     }
     232             : 
     233       24237 :     ret = _gsskrb5_canon_name(minor_status, context, target_name,
     234             :                               &ctx->target);
     235       24237 :     if (ret)
     236           0 :         return ret;
     237             : 
     238       24237 :     memset(&this_cred, 0, sizeof(this_cred));
     239       24237 :     this_cred.client = ctx->source;
     240       24237 :     this_cred.server = ctx->target;
     241             : 
     242       24237 :     if (time_req && time_req != GSS_C_INDEFINITE) {
     243          12 :         krb5_timestamp ts;
     244             : 
     245          50 :         krb5_timeofday (context, &ts);
     246          50 :         this_cred.times.endtime = ts + time_req;
     247             :     } else {
     248       23164 :         this_cred.times.endtime   = 0;
     249             :     }
     250             : 
     251       24237 :     this_cred.session.keytype = KEYTYPE_NULL;
     252             : 
     253       24237 :     kret = krb5_get_credentials(context,
     254             :                                 0,
     255             :                                 ccache,
     256             :                                 &this_cred,
     257             :                                 &ctx->kcred);
     258       24237 :     if (kret) {
     259          25 :         *minor_status = kret;
     260          25 :         return GSS_S_FAILURE;
     261             :     }
     262             : 
     263       24212 :     krb5_free_principal(context, ctx->target);
     264       24212 :     kret = krb5_copy_principal(context, ctx->kcred->server, &ctx->target);
     265       24212 :     if (kret) {
     266           0 :         *minor_status = kret;
     267           0 :         return GSS_S_FAILURE;
     268             :     }
     269             : 
     270       24212 :     ctx->endtime = ctx->kcred->times.endtime;
     271             : 
     272       24212 :     ret = _gsskrb5_lifetime_left(minor_status, context,
     273       23177 :                                  ctx->endtime, &lifetime_rec);
     274       24212 :     if (ret) return ret;
     275             : 
     276       24212 :     if (lifetime_rec == 0) {
     277           0 :         *minor_status = 0;
     278           0 :         return GSS_S_CONTEXT_EXPIRED;
     279             :     }
     280             : 
     281       24212 :     if (time_rec) *time_rec = lifetime_rec;
     282             : 
     283       23177 :     return GSS_S_COMPLETE;
     284             : }
     285             : 
     286             : static OM_uint32
     287       23613 : gsskrb5_initiator_ready(
     288             :         OM_uint32 * minor_status,
     289             :         gsskrb5_ctx ctx,
     290             :         krb5_context context)
     291             : {
     292         880 :     OM_uint32 ret;
     293         880 :     int32_t seq_number;
     294       23613 :     int is_cfx = 0;
     295       23613 :     OM_uint32 flags = ctx->flags;
     296             : 
     297       23613 :     krb5_free_creds(context, ctx->kcred);
     298       23613 :     ctx->kcred = NULL;
     299             : 
     300       23613 :     if (ctx->more_flags & CLOSE_CCACHE)
     301          21 :         krb5_cc_close(context, ctx->ccache);
     302       23613 :     ctx->ccache = NULL;
     303             : 
     304       23613 :     krb5_auth_con_getremoteseqnumber (context, ctx->auth_context, &seq_number);
     305             : 
     306       23613 :     _gsskrb5i_is_cfx(context, ctx, 0);
     307       23613 :     is_cfx = (ctx->more_flags & IS_CFX);
     308             : 
     309       23613 :     ret = _gssapi_msg_order_create(minor_status,
     310             :                                    &ctx->order,
     311             :                                    _gssapi_msg_order_f(flags),
     312             :                                    seq_number, 0, is_cfx);
     313       23613 :     if (ret) return ret;
     314             : 
     315       23613 :     ctx->state       = INITIATOR_READY;
     316       23613 :     ctx->more_flags  |= OPEN;
     317             : 
     318       23613 :     return GSS_S_COMPLETE;
     319             : }
     320             : 
     321             : /*
     322             :  * handle delegated creds in init-sec-context
     323             :  */
     324             : 
     325             : static void
     326       23103 : do_delegation (krb5_context context,
     327             :                krb5_auth_context ac,
     328             :                krb5_ccache ccache,
     329             :                krb5_creds *cred,
     330             :                krb5_data *fwd_data,
     331             :                uint32_t flagmask,
     332             :                uint32_t *flags)
     333             : {
     334        1035 :     krb5_error_code kret;
     335        1035 :     krb5_principal client;
     336        1035 :     const char *host;
     337             : 
     338       23103 :     krb5_data_zero (fwd_data);
     339             : 
     340       23103 :     kret = krb5_cc_get_principal(context, ccache, &client);
     341       23103 :     if (kret)
     342           0 :         goto out;
     343             : 
     344             :     /* We can't generally enforce server.name_type == KRB5_NT_SRV_HST */
     345       23103 :     if (cred->server->name.name_string.len < 2)
     346          64 :         goto out;
     347       23039 :     host = krb5_principal_get_comp_string(context, cred->server, 1);
     348             : 
     349             : #define FWDABLE 1
     350       23039 :     kret = krb5_fwd_tgt_creds(context, ac, host, client, cred->server, ccache,
     351             :                               FWDABLE, fwd_data);
     352             : 
     353       23103 :  out:
     354       23103 :     if (kret)
     355          11 :         *flags &= ~flagmask;
     356             :     else
     357       23092 :         *flags |= flagmask;
     358             : 
     359       23103 :     if (client)
     360       23103 :         krb5_free_principal(context, client);
     361       23103 : }
     362             : 
     363             : /*
     364             :  * first stage of init-sec-context
     365             :  */
     366             : 
     367             : static OM_uint32
     368       24237 : init_auth
     369             : (OM_uint32 * minor_status,
     370             :  gsskrb5_cred cred,
     371             :  gsskrb5_ctx ctx,
     372             :  krb5_context context,
     373             :  gss_const_name_t name,
     374             :  const gss_OID mech_type,
     375             :  OM_uint32 req_flags,
     376             :  OM_uint32 time_req,
     377             :  const gss_buffer_t input_token,
     378             :  gss_OID * actual_mech_type,
     379             :  gss_buffer_t output_token,
     380             :  OM_uint32 * ret_flags,
     381             :  OM_uint32 * time_rec
     382             :     )
     383             : {
     384       24237 :     OM_uint32 ret = GSS_S_FAILURE;
     385        1035 :     krb5_error_code kret;
     386        1035 :     krb5_data fwd_data;
     387        1035 :     OM_uint32 lifetime_rec;
     388             : 
     389       24237 :     krb5_data_zero(&fwd_data);
     390             : 
     391       24237 :     *minor_status = 0;
     392             : 
     393       24237 :     if (actual_mech_type)
     394       22500 :         *actual_mech_type = GSS_KRB5_MECHANISM;
     395             : 
     396       24237 :     if (cred == NULL) {
     397          21 :         kret = krb5_cc_default (context, &ctx->ccache);
     398          21 :         if (kret) {
     399           0 :             *minor_status = kret;
     400           0 :             ret = GSS_S_FAILURE;
     401           0 :             goto failure;
     402             :         }
     403          21 :         ctx->more_flags |= CLOSE_CCACHE;
     404             :     } else
     405       24216 :         ctx->ccache = cred->ccache;
     406             : 
     407       24237 :     kret = krb5_cc_get_principal (context, ctx->ccache, &ctx->source);
     408       24237 :     if (kret) {
     409           0 :         *minor_status = kret;
     410           0 :         ret = GSS_S_FAILURE;
     411           0 :         goto failure;
     412             :     }
     413             : 
     414             :     /*
     415             :      * This is hideous glue for (NFS) clients that wants to limit the
     416             :      * available enctypes to what it can support (encryption in
     417             :      * kernel).
     418             :      */
     419       24237 :     if (cred && cred->enctypes)
     420       22349 :         krb5_set_default_in_tkt_etypes(context, cred->enctypes);
     421             : 
     422       24237 :     ret = gsskrb5_get_creds(minor_status, context, ctx->ccache,
     423             :                             ctx, name, time_req, time_rec);
     424       24237 :     if (ret)
     425          25 :         goto failure;
     426             : 
     427       24212 :     ret = gsskrb5_set_authorization_data(minor_status, context,
     428             :                                          ctx->auth_context, name);
     429       24212 :     if (ret)
     430           0 :         goto failure;
     431             : 
     432       24212 :     ctx->endtime = ctx->kcred->times.endtime;
     433             : 
     434       24212 :     ret = _gss_DES3_get_mic_compat(minor_status, ctx, context);
     435       24212 :     if (ret)
     436           0 :         goto failure;
     437             : 
     438       25247 :     ret = _gsskrb5_lifetime_left(minor_status,
     439             :                                  context,
     440       24212 :                                  ctx->endtime,
     441             :                                  &lifetime_rec);
     442       24212 :     if (ret)
     443           0 :         goto failure;
     444             : 
     445       24212 :     if (lifetime_rec == 0) {
     446           0 :         *minor_status = 0;
     447           0 :         ret = GSS_S_CONTEXT_EXPIRED;
     448           0 :         goto failure;
     449             :     }
     450             : 
     451       24212 :     krb5_auth_con_setkey(context,
     452             :                          ctx->auth_context,
     453       24212 :                          &ctx->kcred->session);
     454             : 
     455       25247 :     kret = krb5_auth_con_generatelocalsubkey(context,
     456             :                                              ctx->auth_context,
     457       24212 :                                              &ctx->kcred->session);
     458       24212 :     if(kret) {
     459           0 :         *minor_status = kret;
     460           0 :         ret = GSS_S_FAILURE;
     461           0 :         goto failure;
     462             :     }
     463             : 
     464       23177 :     return GSS_S_COMPLETE;
     465             : 
     466          25 : failure:
     467          25 :     if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE))
     468           0 :         krb5_cc_close(context, ctx->ccache);
     469          25 :     ctx->ccache = NULL;
     470             : 
     471          25 :     return ret;
     472             : 
     473             : }
     474             : 
     475             : static OM_uint32
     476       24212 : init_auth_restart
     477             : (OM_uint32 * minor_status,
     478             :  gsskrb5_cred cred,
     479             :  gsskrb5_ctx ctx,
     480             :  krb5_context context,
     481             :  OM_uint32 req_flags,
     482             :  const gss_channel_bindings_t input_chan_bindings,
     483             :  const gss_buffer_t input_token,
     484             :  gss_OID * actual_mech_type,
     485             :  gss_buffer_t output_token,
     486             :  OM_uint32 * ret_flags,
     487             :  OM_uint32 * time_rec
     488             :     )
     489             : {
     490       24212 :     OM_uint32 ret = GSS_S_FAILURE;
     491        1035 :     krb5_error_code kret;
     492        1035 :     krb5_flags ap_options;
     493        1035 :     krb5_data outbuf;
     494        1035 :     uint32_t flags;
     495        1035 :     krb5_data authenticator;
     496        1035 :     Checksum cksum;
     497        1035 :     krb5_enctype enctype;
     498        1035 :     krb5_data fwd_data, timedata;
     499       24212 :     int32_t offset = 0, oldoffset = 0;
     500        1035 :     uint32_t flagmask;
     501             : 
     502       24212 :     krb5_data_zero(&outbuf);
     503       24212 :     krb5_data_zero(&fwd_data);
     504             : 
     505       24212 :     *minor_status = 0;
     506             : 
     507             :     /*
     508             :      * Check if our configuration requires us to follow the KDC's
     509             :      * guidance.  If so, we transmogrify the GSS_C_DELEG_FLAG into
     510             :      * the GSS_C_DELEG_POLICY_FLAG.
     511             :      */
     512       24212 :     if ((context->flags & KRB5_CTX_F_ENFORCE_OK_AS_DELEGATE)
     513           0 :         && (req_flags & GSS_C_DELEG_FLAG)) {
     514           0 :         req_flags &= ~GSS_C_DELEG_FLAG;
     515           0 :         req_flags |= GSS_C_DELEG_POLICY_FLAG;
     516             :     }
     517             : 
     518             :     /*
     519             :      * If the credential doesn't have ok-as-delegate, check if there
     520             :      * is a realm setting and use that.
     521             :      */
     522       24212 :     if (!ctx->kcred->flags.b.ok_as_delegate) {
     523           0 :         krb5_data data;
     524             : 
     525        1083 :         ret = krb5_cc_get_config(context, ctx->ccache, NULL,
     526             :                                  "realm-config", &data);
     527        1083 :         if (ret == 0) {
     528             :             /* XXX 1 is use ok-as-delegate */
     529           0 :             if (data.length < 1 || ((((unsigned char *)data.data)[0]) & 1) == 0)
     530           0 :                 req_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG);
     531           0 :             krb5_data_free(&data);
     532             :         }
     533             :     }
     534             : 
     535       24212 :     flagmask = 0;
     536             : 
     537             :     /* if we used GSS_C_DELEG_POLICY_FLAG, trust KDC */
     538       24212 :     if ((req_flags & GSS_C_DELEG_POLICY_FLAG)
     539       24156 :         && ctx->kcred->flags.b.ok_as_delegate)
     540       23103 :         flagmask |= GSS_C_DELEG_FLAG | GSS_C_DELEG_POLICY_FLAG;
     541             :     /* if there still is a GSS_C_DELEG_FLAG, use that */
     542       24212 :     if (req_flags & GSS_C_DELEG_FLAG)
     543           0 :         flagmask |= GSS_C_DELEG_FLAG;
     544             : 
     545             : 
     546       24212 :     flags = 0;
     547       24212 :     ap_options = 0;
     548       24212 :     if (flagmask & GSS_C_DELEG_FLAG) {
     549       23103 :         do_delegation (context,
     550             :                        ctx->deleg_auth_context,
     551             :                        ctx->ccache, ctx->kcred,
     552             :                        &fwd_data, flagmask, &flags);
     553             :     }
     554             : 
     555       24212 :     if (req_flags & GSS_C_MUTUAL_FLAG) {
     556       24212 :         flags |= GSS_C_MUTUAL_FLAG;
     557       24212 :         ap_options |= AP_OPTS_MUTUAL_REQUIRED;
     558             :     }
     559             : 
     560       24212 :     if (req_flags & GSS_C_REPLAY_FLAG)
     561       24212 :         flags |= GSS_C_REPLAY_FLAG;
     562       24212 :     if (req_flags & GSS_C_SEQUENCE_FLAG)
     563       24191 :         flags |= GSS_C_SEQUENCE_FLAG;
     564             : #if 0
     565             :     if (req_flags & GSS_C_ANON_FLAG)
     566             :         ;                               /* XXX */
     567             : #endif
     568       24212 :     if (req_flags & GSS_C_DCE_STYLE) {
     569             :         /* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */
     570        3669 :         flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG;
     571        3669 :         ap_options |= AP_OPTS_MUTUAL_REQUIRED;
     572             :     }
     573       24212 :     if (req_flags & GSS_C_IDENTIFY_FLAG)
     574           0 :         flags |= GSS_C_IDENTIFY_FLAG;
     575       24212 :     if (req_flags & GSS_C_EXTENDED_ERROR_FLAG)
     576           0 :         flags |= GSS_C_EXTENDED_ERROR_FLAG;
     577             : 
     578       24212 :     if (req_flags & GSS_C_CONF_FLAG) {
     579       15326 :         flags |= GSS_C_CONF_FLAG;
     580             :     }
     581       24212 :     if (req_flags & GSS_C_INTEG_FLAG) {
     582       24026 :         flags |= GSS_C_INTEG_FLAG;
     583             :     }
     584       24212 :     if (cred == NULL || !(cred->cred_flags & GSS_CF_NO_CI_FLAGS)) {
     585         172 :         flags |= GSS_C_CONF_FLAG;
     586         172 :         flags |= GSS_C_INTEG_FLAG;
     587             :     }
     588       24212 :     flags |= GSS_C_TRANS_FLAG;
     589             : 
     590       24212 :     if (ret_flags)
     591       24212 :         *ret_flags = flags;
     592       24212 :     ctx->flags = flags;
     593       24212 :     ctx->more_flags |= LOCAL;
     594             : 
     595       24212 :     ret = _gsskrb5_create_8003_checksum (minor_status,
     596             :                                          input_chan_bindings,
     597             :                                          flags,
     598             :                                          &fwd_data,
     599             :                                          &cksum);
     600       24212 :     krb5_data_free (&fwd_data);
     601       24212 :     if (ret)
     602           0 :         goto failure;
     603             : 
     604       24212 :     enctype = ctx->auth_context->keyblock->keytype;
     605             : 
     606       24212 :     ret = krb5_cc_get_config(context, ctx->ccache, ctx->target,
     607             :                              "time-offset", &timedata);
     608       24212 :     if (ret == 0) {
     609           0 :         if (timedata.length == 4) {
     610           0 :             const u_char *p = timedata.data;
     611           0 :             offset = ((uint32_t)p[0] << 24)
     612           0 :                    | ((uint32_t)p[1] << 16)
     613           0 :                    | ((uint32_t)p[2] << 8)
     614           0 :                    | ((uint32_t)p[3] << 0);
     615             :         }
     616           0 :         krb5_data_free(&timedata);
     617             :     }
     618             : 
     619       23177 :     if (offset) {
     620           0 :         krb5_get_kdc_sec_offset (context, &oldoffset, NULL);
     621           0 :         krb5_set_kdc_sec_offset (context, offset, -1);
     622             :     }
     623             : 
     624       24212 :     kret = _krb5_build_authenticator(context,
     625             :                                      ctx->auth_context,
     626             :                                      enctype,
     627             :                                      ctx->kcred,
     628             :                                      &cksum,
     629             :                                      &authenticator,
     630             :                                      KRB5_KU_AP_REQ_AUTH);
     631             : 
     632       24212 :     if (kret) {
     633           0 :         if (offset)
     634           0 :             krb5_set_kdc_sec_offset (context, oldoffset, -1);
     635           0 :         *minor_status = kret;
     636           0 :         ret = GSS_S_FAILURE;
     637           0 :         goto failure;
     638             :     }
     639             : 
     640       24212 :     kret = krb5_build_ap_req (context,
     641             :                               enctype,
     642             :                               ctx->kcred,
     643             :                               ap_options,
     644             :                               authenticator,
     645             :                               &outbuf);
     646       24212 :     if (offset)
     647           0 :         krb5_set_kdc_sec_offset (context, oldoffset, -1);
     648       24212 :     if (kret) {
     649           0 :         *minor_status = kret;
     650           0 :         ret = GSS_S_FAILURE;
     651           0 :         goto failure;
     652             :     }
     653             : 
     654       24212 :     if (flags & GSS_C_DCE_STYLE) {
     655        3669 :         output_token->value = outbuf.data;
     656        3669 :         output_token->length = outbuf.length;
     657             :     } else {
     658       20543 :         ret = _gsskrb5_encapsulate (minor_status, &outbuf, output_token,
     659             :                                     (u_char *)(intptr_t)"\x01\x00",
     660             :                                     GSS_KRB5_MECHANISM);
     661       20543 :         krb5_data_free (&outbuf);
     662       20543 :         if (ret)
     663           0 :             goto failure;
     664             :     }
     665             : 
     666       24212 :     free_Checksum(&cksum);
     667             : 
     668       24212 :     if (flags & GSS_C_MUTUAL_FLAG) {
     669       24212 :         ctx->state = INITIATOR_WAIT_FOR_MUTUAL;
     670       24212 :         return GSS_S_CONTINUE_NEEDED;
     671             :     }
     672             : 
     673           0 :     return gsskrb5_initiator_ready(minor_status, ctx, context);
     674           0 : failure:
     675           0 :     if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE))
     676           0 :         krb5_cc_close(context, ctx->ccache);
     677           0 :     ctx->ccache = NULL;
     678             : 
     679           0 :     return ret;
     680             : }
     681             : 
     682             : static krb5_error_code
     683           0 : handle_error_packet(krb5_context context,
     684             :                     gsskrb5_ctx ctx,
     685             :                     krb5_data indata)
     686             : {
     687           0 :     krb5_error_code kret;
     688           0 :     KRB_ERROR error;
     689             : 
     690           0 :     kret = krb5_rd_error(context, &indata, &error);
     691           0 :     if (kret == 0) {
     692           0 :         kret = krb5_error_from_rd_error(context, &error, NULL);
     693             : 
     694             :         /* save the time skrew for this host */
     695           0 :         if (kret == KRB5KRB_AP_ERR_SKEW) {
     696           0 :             krb5_data timedata;
     697           0 :             unsigned char p[4];
     698           0 :             int32_t t = error.stime - time(NULL);
     699             : 
     700           0 :             p[0] = (t >> 24) & 0xFF;
     701           0 :             p[1] = (t >> 16) & 0xFF;
     702           0 :             p[2] = (t >> 8)  & 0xFF;
     703           0 :             p[3] = (t >> 0)  & 0xFF;
     704             : 
     705           0 :             timedata.data = p;
     706           0 :             timedata.length = sizeof(p);
     707             : 
     708           0 :             krb5_cc_set_config(context, ctx->ccache, ctx->target,
     709             :                                "time-offset", &timedata);
     710             : 
     711           0 :             if ((ctx->more_flags & RETRIED) == 0)
     712           0 :                  ctx->state = INITIATOR_RESTART;
     713           0 :             ctx->more_flags |= RETRIED;
     714             :         }
     715           0 :         free_KRB_ERROR (&error);
     716             :     }
     717           0 :     return kret;
     718             : }
     719             : 
     720             : 
     721             : static OM_uint32
     722       23613 : repl_mutual
     723             : (OM_uint32 * minor_status,
     724             :  gsskrb5_ctx ctx,
     725             :  krb5_context context,
     726             :  const gss_OID mech_type,
     727             :  OM_uint32 req_flags,
     728             :  OM_uint32 time_req,
     729             :  const gss_channel_bindings_t input_chan_bindings,
     730             :  const gss_buffer_t input_token,
     731             :  gss_OID * actual_mech_type,
     732             :  gss_buffer_t output_token,
     733             :  OM_uint32 * ret_flags,
     734             :  OM_uint32 * time_rec
     735             :     )
     736             : {
     737         880 :     OM_uint32 ret;
     738         880 :     krb5_error_code kret;
     739         880 :     krb5_data indata;
     740         880 :     krb5_ap_rep_enc_part *repl;
     741             : 
     742       23613 :     output_token->length = 0;
     743       23613 :     output_token->value = NULL;
     744             : 
     745       23613 :     if (input_token == GSS_C_NO_BUFFER)
     746           0 :         return GSS_S_FAILURE;
     747             : 
     748       23613 :     if (actual_mech_type)
     749       21887 :         *actual_mech_type = GSS_KRB5_MECHANISM;
     750             : 
     751       23613 :     if (IS_DCE_STYLE(ctx)) {
     752             :         /* There is no OID wrapping. */
     753        3638 :         indata.length   = input_token->length;
     754        3638 :         indata.data     = input_token->value;
     755        3638 :         kret = krb5_rd_rep(context,
     756             :                            ctx->auth_context,
     757             :                            &indata,
     758             :                            &repl);
     759        3638 :         if (kret) {
     760           0 :             ret = _gsskrb5_decapsulate(minor_status,
     761             :                                        input_token,
     762             :                                        &indata,
     763             :                                        "\x03\x00",
     764             :                                        GSS_KRB5_MECHANISM);
     765           0 :             if (ret == GSS_S_COMPLETE) {
     766           0 :                 *minor_status = handle_error_packet(context, ctx, indata);
     767             :             } else {
     768           0 :                 *minor_status = kret;
     769             :             }
     770           0 :             return GSS_S_FAILURE;
     771             :         }
     772             :     } else {
     773       19975 :         ret = _gsskrb5_decapsulate (minor_status,
     774             :                                     input_token,
     775             :                                     &indata,
     776             :                                     "\x02\x00",
     777             :                                     GSS_KRB5_MECHANISM);
     778       19975 :         if (ret == GSS_S_DEFECTIVE_TOKEN) {
     779             :             /* check if there is an error token sent instead */
     780           0 :             ret = _gsskrb5_decapsulate (minor_status,
     781             :                                         input_token,
     782             :                                         &indata,
     783             :                                         "\x03\x00",
     784             :                                         GSS_KRB5_MECHANISM);
     785           0 :             if (ret == GSS_S_COMPLETE) {
     786           0 :                 *minor_status = handle_error_packet(context, ctx, indata);
     787           0 :                 return GSS_S_FAILURE;
     788             :             }
     789             :         }
     790       19975 :         kret = krb5_rd_rep (context,
     791             :                             ctx->auth_context,
     792             :                             &indata,
     793             :                             &repl);
     794       19975 :         if (kret) {
     795           0 :             *minor_status = kret;
     796           0 :             return GSS_S_FAILURE;
     797             :         }
     798             :     }
     799             : 
     800       23613 :     krb5_free_ap_rep_enc_part (context,
     801             :                                repl);
     802             : 
     803       23613 :     *minor_status = 0;
     804       23613 :     if (time_rec)
     805       23592 :         (void) _gsskrb5_lifetime_left(minor_status,
     806             :                                       context,
     807       23592 :                                       ctx->endtime,
     808             :                                       time_rec);
     809       23613 :     if (ret_flags)
     810       23613 :         *ret_flags = ctx->flags;
     811             : 
     812       23613 :     if (req_flags & GSS_C_DCE_STYLE) {
     813          96 :         int32_t local_seq, remote_seq;
     814          96 :         krb5_data outbuf;
     815             : 
     816             :         /*
     817             :          * So DCE_STYLE is strange. The client echos the seq number
     818             :          * that the server used in the server's mk_rep in its own
     819             :          * mk_rep(). After when done, it resets to it's own seq number
     820             :          * for the gss_wrap calls.
     821             :          */
     822             : 
     823        3638 :         krb5_auth_con_getremoteseqnumber(context, ctx->auth_context, &remote_seq);
     824        3638 :         krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &local_seq);
     825        3638 :         krb5_auth_con_setlocalseqnumber(context, ctx->auth_context, remote_seq);
     826             : 
     827        3638 :         kret = krb5_mk_rep(context, ctx->auth_context, &outbuf);
     828        3638 :         if (kret) {
     829           0 :             *minor_status = kret;
     830           0 :             return GSS_S_FAILURE;
     831             :         }
     832             : 
     833             :         /* reset local seq number */
     834        3638 :         krb5_auth_con_setlocalseqnumber(context, ctx->auth_context, local_seq);
     835             : 
     836        3638 :         output_token->length = outbuf.length;
     837        3638 :         output_token->value  = outbuf.data;
     838             :     }
     839             : 
     840       23613 :     return gsskrb5_initiator_ready(minor_status, ctx, context);
     841             : }
     842             : 
     843             : /*
     844             :  * gss_init_sec_context
     845             :  */
     846             : 
     847       47850 : OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context
     848             : (OM_uint32 * minor_status,
     849             :  gss_const_cred_id_t cred_handle,
     850             :  gss_ctx_id_t * context_handle,
     851             :  gss_const_name_t target_name,
     852             :  const gss_OID mech_type,
     853             :  OM_uint32 req_flags,
     854             :  OM_uint32 time_req,
     855             :  const gss_channel_bindings_t input_chan_bindings,
     856             :  const gss_buffer_t input_token,
     857             :  gss_OID * actual_mech_type,
     858             :  gss_buffer_t output_token,
     859             :  OM_uint32 * ret_flags,
     860             :  OM_uint32 * time_rec
     861             :     )
     862             : {
     863        1915 :     krb5_context context;
     864       47850 :     gsskrb5_cred cred = (gsskrb5_cred)cred_handle;
     865        1915 :     gsskrb5_ctx ctx;
     866        1915 :     OM_uint32 ret;
     867             : 
     868       47850 :     GSSAPI_KRB5_INIT (&context);
     869             : 
     870       47850 :     output_token->length = 0;
     871       47850 :     output_token->value  = NULL;
     872             : 
     873       47850 :     if (context_handle == NULL) {
     874           0 :         *minor_status = 0;
     875           0 :         return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE;
     876             :     }
     877             : 
     878       47850 :     if (ret_flags)
     879       47850 :         *ret_flags = 0;
     880       47850 :     if (time_rec)
     881       47808 :         *time_rec = 0;
     882             : 
     883       47850 :     if (target_name == GSS_C_NO_NAME) {
     884           0 :         if (actual_mech_type)
     885           0 :             *actual_mech_type = GSS_C_NO_OID;
     886           0 :         *minor_status = 0;
     887           0 :         return GSS_S_BAD_NAME;
     888             :     }
     889             : 
     890       95700 :     if (mech_type != GSS_C_NO_OID &&
     891       47850 :         !gss_oid_equal(mech_type, GSS_KRB5_MECHANISM))
     892           0 :         return GSS_S_BAD_MECH;
     893             : 
     894       47850 :     if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
     895        1035 :         OM_uint32 ret1;
     896             : 
     897       24237 :         if (*context_handle != GSS_C_NO_CONTEXT) {
     898           0 :             *minor_status = 0;
     899           0 :             return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE;
     900             :         }
     901             : 
     902       24237 :         ret1 = _gsskrb5_create_ctx(minor_status,
     903             :                                   context_handle,
     904             :                                   context,
     905             :                                   input_chan_bindings,
     906             :                                   INITIATOR_START);
     907       24237 :         if (ret1)
     908           0 :             return ret1;
     909             :     }
     910             : 
     911       47850 :     if (*context_handle == GSS_C_NO_CONTEXT) {
     912           0 :         *minor_status = 0;
     913           0 :         return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE;
     914             :     }
     915             : 
     916       45935 :     ctx = (gsskrb5_ctx) *context_handle;
     917             : 
     918        1915 :     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
     919             : 
     920       47850 :  again:
     921       47850 :     switch (ctx->state) {
     922       24237 :     case INITIATOR_START:
     923       24237 :         ret = init_auth(minor_status,
     924             :                         cred,
     925             :                         ctx,
     926             :                         context,
     927             :                         target_name,
     928             :                         mech_type,
     929             :                         req_flags,
     930             :                         time_req,
     931             :                         input_token,
     932             :                         actual_mech_type,
     933             :                         output_token,
     934             :                         ret_flags,
     935             :                         time_rec);
     936       24237 :         if (ret != GSS_S_COMPLETE)
     937          25 :             break;
     938        1035 :         HEIM_FALLTHROUGH;
     939             :     case INITIATOR_RESTART:
     940       24212 :         ret = init_auth_restart(minor_status,
     941             :                                 cred,
     942             :                                 ctx,
     943             :                                 context,
     944             :                                 req_flags,
     945             :                                 input_chan_bindings,
     946             :                                 input_token,
     947             :                                 actual_mech_type,
     948             :                                 output_token,
     949             :                                 ret_flags,
     950             :                                 time_rec);
     951       24212 :         break;
     952       23613 :     case INITIATOR_WAIT_FOR_MUTUAL:
     953       23613 :         ret = repl_mutual(minor_status,
     954             :                           ctx,
     955             :                           context,
     956             :                           mech_type,
     957             :                           req_flags,
     958             :                           time_req,
     959             :                           input_chan_bindings,
     960             :                           input_token,
     961             :                           actual_mech_type,
     962             :                           output_token,
     963             :                           ret_flags,
     964             :                           time_rec);
     965       23613 :         if (ctx->state == INITIATOR_RESTART)
     966           0 :             goto again;
     967       22733 :         break;
     968           0 :     case INITIATOR_READY:
     969             :         /*
     970             :          * If we get there, the caller have called
     971             :          * gss_init_sec_context() one time too many.
     972             :          */
     973           0 :         _gsskrb5_set_status(EINVAL, "init_sec_context "
     974             :                             "called one time too many");
     975           0 :         *minor_status = EINVAL;
     976           0 :         ret = GSS_S_BAD_STATUS;
     977           0 :         break;
     978           0 :     default:
     979           0 :         _gsskrb5_set_status(EINVAL, "init_sec_context "
     980             :                             "invalid state %d for client",
     981           0 :                             (int)ctx->state);
     982           0 :         *minor_status = EINVAL;
     983           0 :         ret = GSS_S_BAD_STATUS;
     984           0 :         break;
     985             :     }
     986        1915 :     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
     987             : 
     988             :     /* destroy context in case of error */
     989       47850 :     if (GSS_ERROR(ret)) {
     990           0 :         OM_uint32 min2;
     991          25 :         _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER);
     992             :     }
     993             : 
     994       45935 :     return ret;
     995             : 
     996             : }
     997             : 
     998             : static OM_uint32
     999       24212 : gsskrb5_set_authorization_data(OM_uint32 *minor_status,
    1000             :                                krb5_context context,
    1001             :                                krb5_auth_context auth_context,
    1002             :                                gss_const_name_t gn)
    1003             : {
    1004       24212 :     const CompositePrincipal *name = (const void *)gn;
    1005        1035 :     AuthorizationData *ad;
    1006       24212 :     krb5_error_code kret = 0;
    1007        1035 :     size_t i;
    1008             : 
    1009       24212 :     if (name->nameattrs == NULL || name->nameattrs->want_ad == NULL)
    1010       23177 :         return GSS_S_COMPLETE;
    1011             : 
    1012           0 :     ad = name->nameattrs->want_ad;
    1013           0 :     for (i = 0; kret == 0 && i < ad->len; i++) {
    1014           0 :         kret = krb5_auth_con_add_AuthorizationData(context, auth_context,
    1015           0 :                                                    ad->val[0].ad_type,
    1016           0 :                                                    &ad->val[0].ad_data);
    1017             :     }
    1018             : 
    1019           0 :     if (kret) {
    1020           0 :         *minor_status = kret;
    1021           0 :         return GSS_S_FAILURE;
    1022             :     }
    1023           0 :     return GSS_S_COMPLETE;
    1024             : }

Generated by: LCOV version 1.14