root/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _gsskrb5_register_acceptor_identity
  2. _gsskrb5i_is_cfx
  3. gsskrb5_acceptor_ready
  4. send_error_token
  5. gsskrb5_acceptor_start
  6. acceptor_wait_for_dcestyle
  7. _gsskrb5_accept_sec_context

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

/* [<][>][^][v][top][bottom][index][help] */