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 98b443d9 Lines: 309 488 63.3 %
Date: 2024-05-31 13:13:24 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      152350 : 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        3890 :     krb5_address initiator_addr, acceptor_addr;
      56        3890 :     krb5_error_code kret;
      57             : 
      58      152350 :     if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS
      59         264 :         || input_chan_bindings->application_data.length !=
      60             :         2 * sizeof(ac->local_port))
      61      148460 :         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       76175 : _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        1945 :     krb5_error_code kret;
     116        1945 :     gsskrb5_ctx ctx;
     117             : 
     118       76175 :     *context_handle = NULL;
     119             : 
     120       76175 :     ctx = malloc(sizeof(*ctx));
     121       76175 :     if (ctx == NULL) {
     122           0 :         *minor_status = ENOMEM;
     123           0 :         return GSS_S_FAILURE;
     124             :     }
     125       76175 :     ctx->auth_context                = NULL;
     126       76175 :     ctx->deleg_auth_context  = NULL;
     127       76175 :     ctx->source                      = NULL;
     128       76175 :     ctx->target                      = NULL;
     129       76175 :     ctx->kcred                       = NULL;
     130       76175 :     ctx->ccache                      = NULL;
     131       76175 :     ctx->state                       = state;
     132       76175 :     ctx->flags                       = 0;
     133       76175 :     ctx->more_flags          = 0;
     134       76175 :     ctx->service_keyblock    = NULL;
     135       76175 :     ctx->ticket                      = NULL;
     136       76175 :     krb5_data_zero(&ctx->fwd_data);
     137       76175 :     ctx->endtime             = 0;
     138       76175 :     ctx->order                       = NULL;
     139       76175 :     ctx->crypto                      = NULL;
     140        1945 :     HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex);
     141             : 
     142       76175 :     kret = krb5_auth_con_init (context, &ctx->auth_context);
     143       76175 :     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       76175 :     kret = krb5_auth_con_init (context, &ctx->deleg_auth_context);
     151       76175 :     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       76175 :     kret = set_addresses(context, ctx->auth_context, input_chan_bindings);
     160       76175 :     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       76175 :     kret = set_addresses(context, ctx->deleg_auth_context, input_chan_bindings);
     172       76175 :     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       76175 :     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       76175 :     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       76175 :     *context_handle = (gss_ctx_id_t)ctx;
     204             : 
     205       76175 :     return GSS_S_COMPLETE;
     206             : }
     207             : 
     208             : 
     209             : static OM_uint32
     210       24255 : 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        1042 :     OM_uint32 ret;
     220        1042 :     krb5_error_code kret;
     221        1042 :     krb5_creds this_cred;
     222        1042 :     OM_uint32 lifetime_rec;
     223             : 
     224       24255 :     if (ctx->target) {
     225           0 :         krb5_free_principal(context, ctx->target);
     226           0 :         ctx->target = NULL;
     227             :     }
     228       24255 :     if (ctx->kcred) {
     229           0 :         krb5_free_creds(context, ctx->kcred);
     230           0 :         ctx->kcred = NULL;
     231             :     }
     232             : 
     233       24255 :     ret = _gsskrb5_canon_name(minor_status, context, target_name,
     234             :                               &ctx->target);
     235       24255 :     if (ret)
     236           0 :         return ret;
     237             : 
     238       24255 :     memset(&this_cred, 0, sizeof(this_cred));
     239       24255 :     this_cred.client = ctx->source;
     240       24255 :     this_cred.server = ctx->target;
     241             : 
     242       24255 :     if (time_req && time_req != GSS_C_INDEFINITE) {
     243          12 :         krb5_timestamp ts;
     244             : 
     245          53 :         krb5_timeofday (context, &ts);
     246          53 :         this_cred.times.endtime = ts + time_req;
     247             :     } else {
     248       23172 :         this_cred.times.endtime   = 0;
     249             :     }
     250             : 
     251       24255 :     this_cred.session.keytype = KEYTYPE_NULL;
     252             : 
     253       24255 :     kret = krb5_get_credentials(context,
     254             :                                 0,
     255             :                                 ccache,
     256             :                                 &this_cred,
     257             :                                 &ctx->kcred);
     258       24255 :     if (kret) {
     259          25 :         *minor_status = kret;
     260          25 :         return GSS_S_FAILURE;
     261             :     }
     262             : 
     263       24230 :     krb5_free_principal(context, ctx->target);
     264       24230 :     kret = krb5_copy_principal(context, ctx->kcred->server, &ctx->target);
     265       24230 :     if (kret) {
     266           0 :         *minor_status = kret;
     267           0 :         return GSS_S_FAILURE;
     268             :     }
     269             : 
     270       24230 :     ctx->endtime = ctx->kcred->times.endtime;
     271             : 
     272       24230 :     ret = _gsskrb5_lifetime_left(minor_status, context,
     273       23188 :                                  ctx->endtime, &lifetime_rec);
     274       24230 :     if (ret) return ret;
     275             : 
     276       24230 :     if (lifetime_rec == 0) {
     277           0 :         *minor_status = 0;
     278           0 :         return GSS_S_CONTEXT_EXPIRED;
     279             :     }
     280             : 
     281       24230 :     if (time_rec) *time_rec = lifetime_rec;
     282             : 
     283       23188 :     return GSS_S_COMPLETE;
     284             : }
     285             : 
     286             : static OM_uint32
     287       23593 : gsskrb5_initiator_ready(
     288             :         OM_uint32 * minor_status,
     289             :         gsskrb5_ctx ctx,
     290             :         krb5_context context)
     291             : {
     292         887 :     OM_uint32 ret;
     293         887 :     int32_t seq_number;
     294       23593 :     int is_cfx = 0;
     295       23593 :     OM_uint32 flags = ctx->flags;
     296             : 
     297       23593 :     krb5_free_creds(context, ctx->kcred);
     298       23593 :     ctx->kcred = NULL;
     299             : 
     300       23593 :     if (ctx->more_flags & CLOSE_CCACHE)
     301           0 :         krb5_cc_close(context, ctx->ccache);
     302       23593 :     ctx->ccache = NULL;
     303             : 
     304       23593 :     krb5_auth_con_getremoteseqnumber (context, ctx->auth_context, &seq_number);
     305             : 
     306       23593 :     _gsskrb5i_is_cfx(context, ctx, 0);
     307       23593 :     is_cfx = (ctx->more_flags & IS_CFX);
     308             : 
     309       23593 :     ret = _gssapi_msg_order_create(minor_status,
     310             :                                    &ctx->order,
     311             :                                    _gssapi_msg_order_f(flags),
     312             :                                    seq_number, 0, is_cfx);
     313       23593 :     if (ret) return ret;
     314             : 
     315       23593 :     ctx->state       = INITIATOR_READY;
     316       23593 :     ctx->more_flags  |= OPEN;
     317             : 
     318       23593 :     return GSS_S_COMPLETE;
     319             : }
     320             : 
     321             : /*
     322             :  * handle delegated creds in init-sec-context
     323             :  */
     324             : 
     325             : static void
     326       23127 : 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        1042 :     krb5_error_code kret;
     335        1042 :     krb5_principal client;
     336        1042 :     const char *host;
     337             : 
     338       23127 :     krb5_data_zero (fwd_data);
     339             : 
     340       23127 :     kret = krb5_cc_get_principal(context, ccache, &client);
     341       23127 :     if (kret)
     342           0 :         goto out;
     343             : 
     344             :     /* We can't generally enforce server.name_type == KRB5_NT_SRV_HST */
     345       23127 :     if (cred->server->name.name_string.len < 2)
     346          64 :         goto out;
     347       23063 :     host = krb5_principal_get_comp_string(context, cred->server, 1);
     348             : 
     349             : #define FWDABLE 1
     350       23063 :     kret = krb5_fwd_tgt_creds(context, ac, host, client, cred->server, ccache,
     351             :                               FWDABLE, fwd_data);
     352             : 
     353       23127 :  out:
     354       23127 :     if (kret)
     355          11 :         *flags &= ~flagmask;
     356             :     else
     357       23116 :         *flags |= flagmask;
     358             : 
     359       23127 :     if (client)
     360       23127 :         krb5_free_principal(context, client);
     361       23127 : }
     362             : 
     363             : /*
     364             :  * first stage of init-sec-context
     365             :  */
     366             : 
     367             : static OM_uint32
     368       24255 : 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       24255 :     OM_uint32 ret = GSS_S_FAILURE;
     385        1042 :     krb5_error_code kret;
     386        1042 :     krb5_data fwd_data;
     387        1042 :     OM_uint32 lifetime_rec;
     388             : 
     389       24255 :     krb5_data_zero(&fwd_data);
     390             : 
     391       24255 :     *minor_status = 0;
     392             : 
     393       24255 :     if (actual_mech_type)
     394       22475 :         *actual_mech_type = GSS_KRB5_MECHANISM;
     395             : 
     396       24255 :     if (cred == NULL) {
     397           0 :         kret = krb5_cc_default (context, &ctx->ccache);
     398           0 :         if (kret) {
     399           0 :             *minor_status = kret;
     400           0 :             ret = GSS_S_FAILURE;
     401           0 :             goto failure;
     402             :         }
     403           0 :         ctx->more_flags |= CLOSE_CCACHE;
     404             :     } else
     405       24255 :         ctx->ccache = cred->ccache;
     406             : 
     407       24255 :     kret = krb5_cc_get_principal (context, ctx->ccache, &ctx->source);
     408       24255 :     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       24255 :     if (cred && cred->enctypes)
     420       22324 :         krb5_set_default_in_tkt_etypes(context, cred->enctypes);
     421             : 
     422       24255 :     ret = gsskrb5_get_creds(minor_status, context, ctx->ccache,
     423             :                             ctx, name, time_req, time_rec);
     424       24255 :     if (ret)
     425          25 :         goto failure;
     426             : 
     427       24230 :     ret = gsskrb5_set_authorization_data(minor_status, context,
     428             :                                          ctx->auth_context, name);
     429       24230 :     if (ret)
     430           0 :         goto failure;
     431             : 
     432       24230 :     ctx->endtime = ctx->kcred->times.endtime;
     433             : 
     434       24230 :     ret = _gss_DES3_get_mic_compat(minor_status, ctx, context);
     435       24230 :     if (ret)
     436           0 :         goto failure;
     437             : 
     438       25272 :     ret = _gsskrb5_lifetime_left(minor_status,
     439             :                                  context,
     440       24230 :                                  ctx->endtime,
     441             :                                  &lifetime_rec);
     442       24230 :     if (ret)
     443           0 :         goto failure;
     444             : 
     445       24230 :     if (lifetime_rec == 0) {
     446           0 :         *minor_status = 0;
     447           0 :         ret = GSS_S_CONTEXT_EXPIRED;
     448           0 :         goto failure;
     449             :     }
     450             : 
     451       24230 :     krb5_auth_con_setkey(context,
     452             :                          ctx->auth_context,
     453       24230 :                          &ctx->kcred->session);
     454             : 
     455       25272 :     kret = krb5_auth_con_generatelocalsubkey(context,
     456             :                                              ctx->auth_context,
     457       24230 :                                              &ctx->kcred->session);
     458       24230 :     if(kret) {
     459           0 :         *minor_status = kret;
     460           0 :         ret = GSS_S_FAILURE;
     461           0 :         goto failure;
     462             :     }
     463             : 
     464       23188 :     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       24230 : 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       24230 :     OM_uint32 ret = GSS_S_FAILURE;
     491        1042 :     krb5_error_code kret;
     492        1042 :     krb5_flags ap_options;
     493        1042 :     krb5_data outbuf;
     494        1042 :     uint32_t flags;
     495        1042 :     krb5_data authenticator;
     496        1042 :     Checksum cksum;
     497        1042 :     krb5_enctype enctype;
     498        1042 :     krb5_data fwd_data, timedata;
     499       24230 :     int32_t offset = 0, oldoffset = 0;
     500        1042 :     uint32_t flagmask;
     501       24230 :     krb5_boolean channel_bound = FALSE;
     502             : 
     503       24230 :     krb5_data_zero(&outbuf);
     504       24230 :     krb5_data_zero(&fwd_data);
     505             : 
     506       24230 :     *minor_status = 0;
     507             : 
     508             :     /*
     509             :      * Check if our configuration requires us to follow the KDC's
     510             :      * guidance.  If so, we transmogrify the GSS_C_DELEG_FLAG into
     511             :      * the GSS_C_DELEG_POLICY_FLAG.
     512             :      */
     513       24230 :     if ((context->flags & KRB5_CTX_F_ENFORCE_OK_AS_DELEGATE)
     514           0 :         && (req_flags & GSS_C_DELEG_FLAG)) {
     515           0 :         req_flags &= ~GSS_C_DELEG_FLAG;
     516           0 :         req_flags |= GSS_C_DELEG_POLICY_FLAG;
     517             :     }
     518             : 
     519             :     /*
     520             :      * If the credential doesn't have ok-as-delegate, check if there
     521             :      * is a realm setting and use that.
     522             :      */
     523       24230 :     if (!ctx->kcred->flags.b.ok_as_delegate) {
     524           0 :         krb5_data data;
     525             : 
     526        1098 :         ret = krb5_cc_get_config(context, ctx->ccache, NULL,
     527             :                                  "realm-config", &data);
     528        1098 :         if (ret == 0) {
     529             :             /* XXX 1 is use ok-as-delegate */
     530           0 :             if (data.length < 1 || ((((unsigned char *)data.data)[0]) & 1) == 0)
     531           0 :                 req_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG);
     532           0 :             krb5_data_free(&data);
     533             :         }
     534             :     }
     535             : 
     536       24230 :     flagmask = 0;
     537             : 
     538             :     /* if we used GSS_C_DELEG_POLICY_FLAG, trust KDC */
     539       24230 :     if ((req_flags & GSS_C_DELEG_POLICY_FLAG)
     540       24195 :         && ctx->kcred->flags.b.ok_as_delegate)
     541       23127 :         flagmask |= GSS_C_DELEG_FLAG | GSS_C_DELEG_POLICY_FLAG;
     542             :     /* if there still is a GSS_C_DELEG_FLAG, use that */
     543       24230 :     if (req_flags & GSS_C_DELEG_FLAG)
     544           0 :         flagmask |= GSS_C_DELEG_FLAG;
     545             : 
     546             : 
     547       24230 :     flags = 0;
     548       24230 :     ap_options = 0;
     549       24230 :     if (flagmask & GSS_C_DELEG_FLAG) {
     550       23127 :         do_delegation (context,
     551             :                        ctx->deleg_auth_context,
     552             :                        ctx->ccache, ctx->kcred,
     553             :                        &fwd_data, flagmask, &flags);
     554             :     }
     555             : 
     556       24230 :     if (req_flags & GSS_C_MUTUAL_FLAG) {
     557       24230 :         flags |= GSS_C_MUTUAL_FLAG;
     558       24230 :         ap_options |= AP_OPTS_MUTUAL_REQUIRED;
     559             :     }
     560             : 
     561       24230 :     if (req_flags & GSS_C_REPLAY_FLAG)
     562       24230 :         flags |= GSS_C_REPLAY_FLAG;
     563       24230 :     if (req_flags & GSS_C_SEQUENCE_FLAG)
     564       24230 :         flags |= GSS_C_SEQUENCE_FLAG;
     565             : #if 0
     566             :     if (req_flags & GSS_C_ANON_FLAG)
     567             :         ;                               /* XXX */
     568             : #endif
     569       24230 :     if (req_flags & GSS_C_DCE_STYLE) {
     570             :         /* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */
     571        3644 :         flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG;
     572        3644 :         ap_options |= AP_OPTS_MUTUAL_REQUIRED;
     573             :     }
     574       24230 :     if (req_flags & GSS_C_IDENTIFY_FLAG)
     575           0 :         flags |= GSS_C_IDENTIFY_FLAG;
     576       24230 :     if (req_flags & GSS_C_EXTENDED_ERROR_FLAG)
     577           0 :         flags |= GSS_C_EXTENDED_ERROR_FLAG;
     578             : 
     579       24230 :     if (req_flags & GSS_C_CONF_FLAG) {
     580       15298 :         flags |= GSS_C_CONF_FLAG;
     581             :     }
     582       24230 :     if (req_flags & GSS_C_INTEG_FLAG) {
     583       23979 :         flags |= GSS_C_INTEG_FLAG;
     584             :     }
     585       24230 :     if (cred == NULL || !(cred->cred_flags & GSS_CF_NO_CI_FLAGS)) {
     586         151 :         flags |= GSS_C_CONF_FLAG;
     587         151 :         flags |= GSS_C_INTEG_FLAG;
     588             :     }
     589       24230 :     flags |= GSS_C_TRANS_FLAG;
     590             : 
     591       24230 :     if (req_flags & GSS_C_CHANNEL_BOUND_FLAG) {
     592       24198 :         flags |= GSS_C_CHANNEL_BOUND_FLAG;
     593       24198 :         channel_bound = TRUE;
     594             :     }
     595             : 
     596       24230 :     if (ret_flags)
     597       24230 :         *ret_flags = flags;
     598       24230 :     ctx->flags = flags;
     599       24230 :     ctx->more_flags |= LOCAL;
     600             : 
     601       24230 :     ret = _gsskrb5_create_8003_checksum (minor_status,
     602             :                                          input_chan_bindings,
     603             :                                          flags,
     604             :                                          &fwd_data,
     605             :                                          &cksum);
     606       24230 :     krb5_data_free (&fwd_data);
     607       24230 :     if (ret)
     608           0 :         goto failure;
     609             : 
     610       24230 :     enctype = ctx->auth_context->keyblock->keytype;
     611             : 
     612       24230 :     ret = krb5_cc_get_config(context, ctx->ccache, ctx->target,
     613             :                              "time-offset", &timedata);
     614       24230 :     if (ret == 0) {
     615           0 :         if (timedata.length == 4) {
     616           0 :             const u_char *p = timedata.data;
     617           0 :             offset = ((uint32_t)p[0] << 24)
     618           0 :                    | ((uint32_t)p[1] << 16)
     619           0 :                    | ((uint32_t)p[2] << 8)
     620           0 :                    | ((uint32_t)p[3] << 0);
     621             :         }
     622           0 :         krb5_data_free(&timedata);
     623             :     }
     624             : 
     625       23188 :     if (offset) {
     626           0 :         krb5_get_kdc_sec_offset (context, &oldoffset, NULL);
     627           0 :         krb5_set_kdc_sec_offset (context, offset, -1);
     628             :     }
     629             : 
     630       24230 :     kret = _krb5_build_authenticator(context,
     631             :                                      ctx->auth_context,
     632             :                                      enctype,
     633             :                                      ctx->kcred,
     634             :                                      &cksum,
     635             :                                      channel_bound,
     636             :                                      &authenticator,
     637             :                                      KRB5_KU_AP_REQ_AUTH);
     638             : 
     639       24230 :     if (kret) {
     640           0 :         if (offset)
     641           0 :             krb5_set_kdc_sec_offset (context, oldoffset, -1);
     642           0 :         *minor_status = kret;
     643           0 :         ret = GSS_S_FAILURE;
     644           0 :         goto failure;
     645             :     }
     646             : 
     647       24230 :     kret = krb5_build_ap_req (context,
     648             :                               enctype,
     649             :                               ctx->kcred,
     650             :                               ap_options,
     651             :                               authenticator,
     652             :                               &outbuf);
     653       24230 :     if (offset)
     654           0 :         krb5_set_kdc_sec_offset (context, oldoffset, -1);
     655       24230 :     if (kret) {
     656           0 :         *minor_status = kret;
     657           0 :         ret = GSS_S_FAILURE;
     658           0 :         goto failure;
     659             :     }
     660             : 
     661       24230 :     if (flags & GSS_C_DCE_STYLE) {
     662        3644 :         output_token->value = outbuf.data;
     663        3644 :         output_token->length = outbuf.length;
     664             :     } else {
     665       20586 :         ret = _gsskrb5_encapsulate (minor_status, &outbuf, output_token,
     666             :                                     (u_char *)(intptr_t)"\x01\x00",
     667             :                                     GSS_KRB5_MECHANISM);
     668       20586 :         krb5_data_free (&outbuf);
     669       20586 :         if (ret)
     670           0 :             goto failure;
     671             :     }
     672             : 
     673       24230 :     free_Checksum(&cksum);
     674             : 
     675       24230 :     if (flags & GSS_C_MUTUAL_FLAG) {
     676       24230 :         ctx->state = INITIATOR_WAIT_FOR_MUTUAL;
     677       24230 :         return GSS_S_CONTINUE_NEEDED;
     678             :     }
     679             : 
     680           0 :     return gsskrb5_initiator_ready(minor_status, ctx, context);
     681           0 : failure:
     682           0 :     if (ctx->ccache && (ctx->more_flags & CLOSE_CCACHE))
     683           0 :         krb5_cc_close(context, ctx->ccache);
     684           0 :     ctx->ccache = NULL;
     685             : 
     686           0 :     return ret;
     687             : }
     688             : 
     689             : static krb5_error_code
     690           0 : handle_error_packet(krb5_context context,
     691             :                     gsskrb5_ctx ctx,
     692             :                     krb5_data indata)
     693             : {
     694           0 :     krb5_error_code kret;
     695           0 :     KRB_ERROR error;
     696             : 
     697           0 :     kret = krb5_rd_error(context, &indata, &error);
     698           0 :     if (kret == 0) {
     699           0 :         kret = krb5_error_from_rd_error(context, &error, NULL);
     700             : 
     701             :         /* save the time skrew for this host */
     702           0 :         if (kret == KRB5KRB_AP_ERR_SKEW) {
     703           0 :             krb5_data timedata;
     704           0 :             unsigned char p[4];
     705           0 :             int32_t t = error.stime - time(NULL);
     706             : 
     707           0 :             p[0] = (t >> 24) & 0xFF;
     708           0 :             p[1] = (t >> 16) & 0xFF;
     709           0 :             p[2] = (t >> 8)  & 0xFF;
     710           0 :             p[3] = (t >> 0)  & 0xFF;
     711             : 
     712           0 :             timedata.data = p;
     713           0 :             timedata.length = sizeof(p);
     714             : 
     715           0 :             krb5_cc_set_config(context, ctx->ccache, ctx->target,
     716             :                                "time-offset", &timedata);
     717             : 
     718           0 :             if ((ctx->more_flags & RETRIED) == 0)
     719           0 :                  ctx->state = INITIATOR_RESTART;
     720           0 :             ctx->more_flags |= RETRIED;
     721             :         }
     722           0 :         free_KRB_ERROR (&error);
     723             :     }
     724           0 :     return kret;
     725             : }
     726             : 
     727             : 
     728             : static OM_uint32
     729       23593 : repl_mutual
     730             : (OM_uint32 * minor_status,
     731             :  gsskrb5_ctx ctx,
     732             :  krb5_context context,
     733             :  const gss_OID mech_type,
     734             :  OM_uint32 req_flags,
     735             :  OM_uint32 time_req,
     736             :  const gss_channel_bindings_t input_chan_bindings,
     737             :  const gss_buffer_t input_token,
     738             :  gss_OID * actual_mech_type,
     739             :  gss_buffer_t output_token,
     740             :  OM_uint32 * ret_flags,
     741             :  OM_uint32 * time_rec
     742             :     )
     743             : {
     744         887 :     OM_uint32 ret;
     745         887 :     krb5_error_code kret;
     746         887 :     krb5_data indata;
     747         887 :     krb5_ap_rep_enc_part *repl;
     748             : 
     749       23593 :     output_token->length = 0;
     750       23593 :     output_token->value = NULL;
     751             : 
     752       23593 :     if (input_token == GSS_C_NO_BUFFER)
     753           0 :         return GSS_S_FAILURE;
     754             : 
     755       23593 :     if (actual_mech_type)
     756       21824 :         *actual_mech_type = GSS_KRB5_MECHANISM;
     757             : 
     758       23593 :     if (IS_DCE_STYLE(ctx)) {
     759             :         /* There is no OID wrapping. */
     760        3613 :         indata.length   = input_token->length;
     761        3613 :         indata.data     = input_token->value;
     762        3613 :         kret = krb5_rd_rep(context,
     763             :                            ctx->auth_context,
     764             :                            &indata,
     765             :                            &repl);
     766        3613 :         if (kret) {
     767           0 :             ret = _gsskrb5_decapsulate(minor_status,
     768             :                                        input_token,
     769             :                                        &indata,
     770             :                                        "\x03\x00",
     771             :                                        GSS_KRB5_MECHANISM);
     772           0 :             if (ret == GSS_S_COMPLETE) {
     773           0 :                 *minor_status = handle_error_packet(context, ctx, indata);
     774             :             } else {
     775           0 :                 *minor_status = kret;
     776             :             }
     777           0 :             return GSS_S_FAILURE;
     778             :         }
     779             :     } else {
     780       19980 :         ret = _gsskrb5_decapsulate (minor_status,
     781             :                                     input_token,
     782             :                                     &indata,
     783             :                                     "\x02\x00",
     784             :                                     GSS_KRB5_MECHANISM);
     785       19980 :         if (ret == GSS_S_DEFECTIVE_TOKEN) {
     786             :             /* check if there is an error token sent instead */
     787           0 :             ret = _gsskrb5_decapsulate (minor_status,
     788             :                                         input_token,
     789             :                                         &indata,
     790             :                                         "\x03\x00",
     791             :                                         GSS_KRB5_MECHANISM);
     792           0 :             if (ret == GSS_S_COMPLETE) {
     793           0 :                 *minor_status = handle_error_packet(context, ctx, indata);
     794           0 :                 return GSS_S_FAILURE;
     795             :             }
     796             :         }
     797       19980 :         if (ret != GSS_S_COMPLETE) {
     798           0 :                 return ret;
     799             :         }
     800       19980 :         kret = krb5_rd_rep (context,
     801             :                             ctx->auth_context,
     802             :                             &indata,
     803             :                             &repl);
     804       19980 :         if (kret) {
     805           0 :             *minor_status = kret;
     806           0 :             return GSS_S_FAILURE;
     807             :         }
     808             :     }
     809             : 
     810       23593 :     krb5_free_ap_rep_enc_part (context,
     811             :                                repl);
     812             : 
     813       23593 :     *minor_status = 0;
     814       23593 :     if (time_rec)
     815       23593 :         (void) _gsskrb5_lifetime_left(minor_status,
     816             :                                       context,
     817       23593 :                                       ctx->endtime,
     818             :                                       time_rec);
     819       23593 :     if (ret_flags)
     820       23593 :         *ret_flags = ctx->flags;
     821             : 
     822       23593 :     if (req_flags & GSS_C_DCE_STYLE) {
     823          96 :         int32_t local_seq, remote_seq;
     824          96 :         krb5_data outbuf;
     825             : 
     826             :         /*
     827             :          * So DCE_STYLE is strange. The client echos the seq number
     828             :          * that the server used in the server's mk_rep in its own
     829             :          * mk_rep(). After when done, it resets to it's own seq number
     830             :          * for the gss_wrap calls.
     831             :          */
     832             : 
     833        3613 :         krb5_auth_con_getremoteseqnumber(context, ctx->auth_context, &remote_seq);
     834        3613 :         krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &local_seq);
     835        3613 :         krb5_auth_con_setlocalseqnumber(context, ctx->auth_context, remote_seq);
     836             : 
     837        3613 :         kret = krb5_mk_rep(context, ctx->auth_context, &outbuf);
     838        3613 :         if (kret) {
     839           0 :             *minor_status = kret;
     840           0 :             return GSS_S_FAILURE;
     841             :         }
     842             : 
     843             :         /* reset local seq number */
     844        3613 :         krb5_auth_con_setlocalseqnumber(context, ctx->auth_context, local_seq);
     845             : 
     846        3613 :         output_token->length = outbuf.length;
     847        3613 :         output_token->value  = outbuf.data;
     848             :     }
     849             : 
     850       23593 :     return gsskrb5_initiator_ready(minor_status, ctx, context);
     851             : }
     852             : 
     853             : /*
     854             :  * gss_init_sec_context
     855             :  */
     856             : 
     857       47848 : OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context
     858             : (OM_uint32 * minor_status,
     859             :  gss_const_cred_id_t cred_handle,
     860             :  gss_ctx_id_t * context_handle,
     861             :  gss_const_name_t target_name,
     862             :  const gss_OID mech_type,
     863             :  OM_uint32 req_flags,
     864             :  OM_uint32 time_req,
     865             :  const gss_channel_bindings_t input_chan_bindings,
     866             :  const gss_buffer_t input_token,
     867             :  gss_OID * actual_mech_type,
     868             :  gss_buffer_t output_token,
     869             :  OM_uint32 * ret_flags,
     870             :  OM_uint32 * time_rec
     871             :     )
     872             : {
     873        1929 :     krb5_context context;
     874       47848 :     gsskrb5_cred cred = (gsskrb5_cred)cred_handle;
     875        1929 :     gsskrb5_ctx ctx;
     876        1929 :     OM_uint32 ret;
     877             : 
     878       47848 :     GSSAPI_KRB5_INIT (&context);
     879             : 
     880       47848 :     output_token->length = 0;
     881       47848 :     output_token->value  = NULL;
     882             : 
     883       47848 :     if (context_handle == NULL) {
     884           0 :         *minor_status = 0;
     885           0 :         return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE;
     886             :     }
     887             : 
     888       47848 :     if (ret_flags)
     889       47848 :         *ret_flags = 0;
     890       47848 :     if (time_rec)
     891       47848 :         *time_rec = 0;
     892             : 
     893       47848 :     if (target_name == GSS_C_NO_NAME) {
     894           0 :         if (actual_mech_type)
     895           0 :             *actual_mech_type = GSS_C_NO_OID;
     896           0 :         *minor_status = 0;
     897           0 :         return GSS_S_BAD_NAME;
     898             :     }
     899             : 
     900       95696 :     if (mech_type != GSS_C_NO_OID &&
     901       47848 :         !gss_oid_equal(mech_type, GSS_KRB5_MECHANISM))
     902           0 :         return GSS_S_BAD_MECH;
     903             : 
     904       47848 :     if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
     905        1042 :         OM_uint32 ret1;
     906             : 
     907       24255 :         if (*context_handle != GSS_C_NO_CONTEXT) {
     908           0 :             *minor_status = 0;
     909           0 :             return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE;
     910             :         }
     911             : 
     912       24255 :         ret1 = _gsskrb5_create_ctx(minor_status,
     913             :                                   context_handle,
     914             :                                   context,
     915             :                                   input_chan_bindings,
     916             :                                   INITIATOR_START);
     917       24255 :         if (ret1)
     918           0 :             return ret1;
     919             :     }
     920             : 
     921       47848 :     if (*context_handle == GSS_C_NO_CONTEXT) {
     922           0 :         *minor_status = 0;
     923           0 :         return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE;
     924             :     }
     925             : 
     926       45919 :     ctx = (gsskrb5_ctx) *context_handle;
     927             : 
     928        1929 :     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
     929             : 
     930       47848 :  again:
     931       47848 :     switch (ctx->state) {
     932       24255 :     case INITIATOR_START:
     933       24255 :         ret = init_auth(minor_status,
     934             :                         cred,
     935             :                         ctx,
     936             :                         context,
     937             :                         target_name,
     938             :                         mech_type,
     939             :                         req_flags,
     940             :                         time_req,
     941             :                         input_token,
     942             :                         actual_mech_type,
     943             :                         output_token,
     944             :                         ret_flags,
     945             :                         time_rec);
     946       24255 :         if (ret != GSS_S_COMPLETE)
     947          25 :             break;
     948        1042 :         HEIM_FALLTHROUGH;
     949             :     case INITIATOR_RESTART:
     950       24230 :         ret = init_auth_restart(minor_status,
     951             :                                 cred,
     952             :                                 ctx,
     953             :                                 context,
     954             :                                 req_flags,
     955             :                                 input_chan_bindings,
     956             :                                 input_token,
     957             :                                 actual_mech_type,
     958             :                                 output_token,
     959             :                                 ret_flags,
     960             :                                 time_rec);
     961       24230 :         break;
     962       23593 :     case INITIATOR_WAIT_FOR_MUTUAL:
     963       23593 :         ret = repl_mutual(minor_status,
     964             :                           ctx,
     965             :                           context,
     966             :                           mech_type,
     967             :                           req_flags,
     968             :                           time_req,
     969             :                           input_chan_bindings,
     970             :                           input_token,
     971             :                           actual_mech_type,
     972             :                           output_token,
     973             :                           ret_flags,
     974             :                           time_rec);
     975       23593 :         if (ctx->state == INITIATOR_RESTART)
     976           0 :             goto again;
     977       22706 :         break;
     978           0 :     case INITIATOR_READY:
     979             :         /*
     980             :          * If we get there, the caller have called
     981             :          * gss_init_sec_context() one time too many.
     982             :          */
     983           0 :         _gsskrb5_set_status(EINVAL, "init_sec_context "
     984             :                             "called one time too many");
     985           0 :         *minor_status = EINVAL;
     986           0 :         ret = GSS_S_BAD_STATUS;
     987           0 :         break;
     988           0 :     default:
     989           0 :         _gsskrb5_set_status(EINVAL, "init_sec_context "
     990             :                             "invalid state %d for client",
     991           0 :                             (int)ctx->state);
     992           0 :         *minor_status = EINVAL;
     993           0 :         ret = GSS_S_BAD_STATUS;
     994           0 :         break;
     995             :     }
     996        1929 :     HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
     997             : 
     998             :     /* destroy context in case of error */
     999       47848 :     if (GSS_ERROR(ret)) {
    1000           0 :         OM_uint32 min2;
    1001          25 :         _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER);
    1002             :     }
    1003             : 
    1004       45919 :     return ret;
    1005             : 
    1006             : }
    1007             : 
    1008             : static OM_uint32
    1009       24230 : gsskrb5_set_authorization_data(OM_uint32 *minor_status,
    1010             :                                krb5_context context,
    1011             :                                krb5_auth_context auth_context,
    1012             :                                gss_const_name_t gn)
    1013             : {
    1014       24230 :     const CompositePrincipal *name = (const void *)gn;
    1015        1042 :     AuthorizationData *ad;
    1016       24230 :     krb5_error_code kret = 0;
    1017        1042 :     size_t i;
    1018             : 
    1019       24230 :     if (name->nameattrs == NULL || name->nameattrs->want_ad == NULL)
    1020       23188 :         return GSS_S_COMPLETE;
    1021             : 
    1022           0 :     ad = name->nameattrs->want_ad;
    1023           0 :     for (i = 0; kret == 0 && i < ad->len; i++) {
    1024           0 :         kret = krb5_auth_con_add_AuthorizationData(context, auth_context,
    1025           0 :                                                    ad->val[0].ad_type,
    1026           0 :                                                    &ad->val[0].ad_data);
    1027             :     }
    1028             : 
    1029           0 :     if (kret) {
    1030           0 :         *minor_status = kret;
    1031           0 :         return GSS_S_FAILURE;
    1032             :     }
    1033           0 :     return GSS_S_COMPLETE;
    1034             : }

Generated by: LCOV version 1.14