]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Remove kg_release_defcred and caching of default credential. Rewrite
authorTom Yu <tlyu@mit.edu>
Thu, 17 Jul 2003 20:50:36 +0000 (20:50 +0000)
committerTom Yu <tlyu@mit.edu>
Thu, 17 Jul 2003 20:50:36 +0000 (20:50 +0000)
krb5_gss_init_sec_context() while we're at it to make defcred-related
changes easier, and as a side effect, fix some error condition memory
leaks.

ticket: 1365
target_version: 1.3.1
tags: pullup

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15694 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/gssapi/ChangeLog
src/lib/gssapi/gss_libinit.c
src/lib/gssapi/krb5/ChangeLog
src/lib/gssapi/krb5/gssapiP_krb5.h
src/lib/gssapi/krb5/gssapi_krb5.c
src/lib/gssapi/krb5/init_sec_context.c
src/lib/gssapi/krb5/inq_cred.c
src/lib/gssapi/krb5/rel_cred.c
src/lib/gssapi/krb5/set_ccache.c

index 26747104bc24308116bddec308b5b09f691ecdb1..27fc2d9a9e6f8b756f4ae46196f17e94228af95f 100644 (file)
@@ -1,3 +1,8 @@
+2003-07-17  Tom Yu  <tlyu@mit.edu>
+
+       * gss_libinit.c (gssint_initialize_library): Don't call
+       kg_release_defcred(); it doesn't exist any more.
+
 2003-03-08  Ken Raeburn  <raeburn@mit.edu>
 
        * Makefile.in ($(BUILDTOP)/include/gssapi/gssapi.h,
index 7906786e9579fdd88118a2a53e1a3013d2cd9e32..0568f29640626e9c49eebe65b4f71ae0a06efb1d 100644 (file)
@@ -33,12 +33,9 @@ OM_uint32 gssint_initialize_library (void)
 
 void gssint_cleanup_library (void)
 {
-       OM_uint32 min_stat;
 
        assert (initialized);
        
-       (void) kg_release_defcred (&min_stat);
-       
 #if !USE_BUNDLE_ERROR_STRINGS
        remove_error_table(&et_k5g_error_table);
        remove_error_table(&et_ggss_error_table);
index 88948c440461975b81b19a2a9a5caeeb7ce59501..44ba4200ebbe401c928f4d99ef0b2c69682616bd 100644 (file)
@@ -1,3 +1,40 @@
+2003-07-17  Tom Yu  <tlyu@mit.edu>
+
+       * gssapiP_krb5.h: Delete kg_release_defcred(); it's no longer
+       used.
+
+       * gssapi_krb5.c: Delete defcred; it's no longer cached.
+       (kg_get_defcred): Don't cache.
+       (kg_release_defcred): Delete; it's no longer used.
+
+       * init_sec_context.c (krb5_gss_init_sec_context): Break into more
+       manageable pieces.  Clean up a few error condition memory leaks
+       previously obscured by the sheer size of this function.
+       (setup_enc): New function; used to be part of
+       krb5_gss_init_sec_context() responsible for setting up enctypes,
+       keyblocks, related nastiness.
+       (get_requested_enctypes): New function; used to be part of
+       krb5_gss_init_sec_context() responsible for pruning the krb5
+       library's default enctype list to the limited set of enctypes
+       usable with GSSAPI.
+       (new_connection): New function; used to be part of
+       krb5_gss_init_sec_context() responsible for initial gss_ctx setup
+       and creating the AP-REQ.
+       (mutual_auth): New function; used to be part of
+       krb5_gss_init_sec_context() responsible for reading the AP-REP if
+       mutual auth was requested.
+
+       * inq_cred.c (krb5_gss_inquire_cred): Rearrange due to removal of
+       kg_release_defcred(), particularly to explicitly release the
+       defcred once it's obtained.
+
+       * rel_cred.c (krb5_gss_release_cred): Remove call to
+       kg_release_defcred(), and always succeed in releasing the null
+       credential.
+
+       * set_ccache.c (gss_krb5_ccache_name): Remove call to
+       kg_release_defcred().
+
 2003-07-17  Ken Raeburn  <raeburn@mit.edu>
 
        * Makefile.in (LIBNAME) [##WIN16##]: Don't define.
index f50653dbfd47a38188f13c222f05ce59ecc70b4a..1215b1a9a6374ee83793b45afb33f02cc4e870ce 100644 (file)
@@ -202,8 +202,6 @@ OM_uint32 kg_get_defcred
        (OM_uint32 *minor_status, 
                   gss_cred_id_t *cred);
 
-OM_uint32 kg_release_defcred (OM_uint32 *minor_status);
-
 krb5_error_code kg_checksum_channel_bindings
          (krb5_context context, gss_channel_bindings_t cb,
                                             krb5_checksum *cksum,
index db6eabd5d438bb6fcae0e65da9c51a9a49bdb763..2c7803bc5502e2cc0927f9a87e90c50fa9d2f27c 100644 (file)
@@ -128,10 +128,6 @@ void *kg_vdb = NULL;
 
 /** default credential support */
 
-/* default credentials */
-
-static gss_cred_id_t defcred = GSS_C_NO_CREDENTIAL;
-
 /*
  * init_sec_context() will explicitly re-acquire default credentials,
  * so handling the expiration/invalidation condition here isn't needed.
@@ -141,36 +137,18 @@ kg_get_defcred(minor_status, cred)
      OM_uint32 *minor_status;
      gss_cred_id_t *cred;
 {
-   if (defcred == GSS_C_NO_CREDENTIAL) {
-      OM_uint32 major;
-
-      if ((major = krb5_gss_acquire_cred(minor_status, 
-                                        (gss_name_t) NULL, GSS_C_INDEFINITE, 
-                                        GSS_C_NULL_OID_SET, GSS_C_INITIATE, 
-                                        &defcred, NULL, NULL)) &&
-         GSS_ERROR(major)) {
-        defcred = GSS_C_NO_CREDENTIAL;
-        return(major);
-      }
-   }
+   OM_uint32 major;
 
-   *cred = defcred;
+   if ((major = krb5_gss_acquire_cred(minor_status, 
+                                     (gss_name_t) NULL, GSS_C_INDEFINITE, 
+                                     GSS_C_NULL_OID_SET, GSS_C_INITIATE, 
+                                     cred, NULL, NULL)) && GSS_ERROR(major)) {
+      return(major);
+   }
    *minor_status = 0;
    return(GSS_S_COMPLETE);
 }
 
-OM_uint32
-kg_release_defcred(minor_status)
-     OM_uint32 *minor_status;
-{
-   if (defcred == GSS_C_NO_CREDENTIAL) {
-      *minor_status = 0;
-      return(GSS_S_COMPLETE);
-   }
-
-   return(krb5_gss_release_cred(minor_status, &defcred));
-}
-
 OM_uint32
 kg_get_context(minor_status, context)
    OM_uint32 *minor_status;
index 0d3ddc9689f340b14f0f502694d5e7c2d352fa08..98102ce8705aafa08ac88d87fcf81f4961f4b6e2 100644 (file)
@@ -324,29 +324,21 @@ make_ap_req_v1(context, ctx, cred, k_cred, chan_bindings, mech_type, token)
    return (code);
 }
 
-OM_uint32
-krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
-                         context_handle, target_name, mech_type,
-                         req_flags, time_req, input_chan_bindings,
-                         input_token, actual_mech_type, output_token,
-                         ret_flags, time_rec)
-    OM_uint32 *minor_status;
-    gss_cred_id_t claimant_cred_handle;
-    gss_ctx_id_t *context_handle;
-    gss_name_t target_name;
-    gss_OID mech_type;
-    OM_uint32 req_flags;
-    OM_uint32 time_req;
-    gss_channel_bindings_t input_chan_bindings;
-    gss_buffer_t input_token;
-    gss_OID *actual_mech_type;
-    gss_buffer_t output_token;
-    OM_uint32 *ret_flags;
-    OM_uint32 *time_rec;
+/*
+ * get_requested_enctypes
+ *
+ * Filter the krb5 library's default enctype list with the set of
+ * enctypes we support for GSSAPI.
+ */
+static krb5_error_code
+get_requested_enctypes(
+   krb5_context context,
+   krb5_enctype **ret_enctypes)
 {
-   krb5_context context;
-   krb5_gss_cred_id_t cred;
-   krb5_creds *k_cred = 0;
+   krb5_error_code code;
+   int i, j, k;
+   int is_duplicate_enctype;
+   int is_wanted_enctype;
    static const krb5_enctype wanted_enctypes[] = {
 #if 1
      ENCTYPE_DES3_CBC_SHA1,
@@ -356,488 +348,614 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
      ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4,
    };
 #define N_WANTED_ENCTYPES (sizeof(wanted_enctypes)/sizeof(wanted_enctypes[0]))
-   krb5_enctype requested_enctypes[N_WANTED_ENCTYPES + 1];
    krb5_enctype *default_enctypes = 0;
-   krb5_error_code code; 
-   krb5_gss_ctx_id_rec *ctx, *ctx_free;
-   krb5_timestamp now;
-   gss_buffer_desc token;
-   int i, j, k, err;
-   int default_mech = 0;
-   OM_uint32 major_status;
+   krb5_enctype *requested_enctypes;
 
-   if (GSS_ERROR(kg_get_context(minor_status, &context)))
-      return(GSS_S_FAILURE);
+   *ret_enctypes = malloc((N_WANTED_ENCTYPES + 1) * sizeof(krb5_enctype));
+   if (*ret_enctypes == NULL)
+      return ENOMEM;
 
-   /* set up return values so they can be "freed" successfully */
+   code = krb5_get_tgs_ktypes (context, 0, &default_enctypes);
+   if (code) {
+      free(*ret_enctypes);
+      *ret_enctypes = NULL;
+      return code;
+   }
+   requested_enctypes = *ret_enctypes;
+
+   /* "i" denotes *next* slot to fill.  Don't forget to save room
+      for a trailing zero.  */
+   i = 0;
+   for (j = 0;
+       (default_enctypes[j] != 0
+        /* This part should be redundant, but let's be paranoid.  */
+        && i < N_WANTED_ENCTYPES);
+       j++) {
+
+      krb5_enctype e = default_enctypes[j];
+
+      /* Is this enctype one of the ones we want for GSSAPI?  */
+      is_wanted_enctype = 0;
+      for (k = 0; k < N_WANTED_ENCTYPES; k++) {
+        if (wanted_enctypes[k] == e) {
+           is_wanted_enctype = 1;
+           break;
+        }
+      }
+      /* If unwanted, go to the next one. */
+      if (!is_wanted_enctype)
+        continue;
+
+      /* Is this enctype already in the list of enctypes to
+        request?  (Is it a duplicate?)  */
+      is_duplicate_enctype = 0;
+      for (k = 0; k < i; k++) {
+        if (requested_enctypes[k] == e) {
+           is_duplicate_enctype = 1;
+           break;
+        }
+      }
+      /* If it is not a duplicate, add it. */
+      if (!is_duplicate_enctype)
+        requested_enctypes[i++] = e;
+   }
+   krb5_free_ktypes(context, default_enctypes);
+   requested_enctypes[i++] = 0;
+   return GSS_S_COMPLETE;
+}
 
-   major_status = GSS_S_FAILURE; /* Default major code */
-   output_token->length = 0;
-   output_token->value = NULL;
-   if (actual_mech_type)
-      *actual_mech_type = NULL;
-   token.value = 0;
-   ctx_free = 0;
+/*
+ * setup_enc
+ *
+ * Fill in the encryption descriptors.  Called after AP-REQ is made.
+ */
+static OM_uint32
+setup_enc(
+   OM_uint32 *minor_status,
+   krb5_gss_ctx_id_rec *ctx,
+   krb5_context context)
+{
+   krb5_error_code code;
+   int i;
+
+   switch(ctx->subkey->enctype) {
+   case ENCTYPE_DES_CBC_MD5:
+   case ENCTYPE_DES_CBC_MD4:
+   case ENCTYPE_DES_CBC_CRC:
+      ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
+      ctx->signalg = SGN_ALG_DES_MAC_MD5;
+      ctx->cksum_size = 8;
+      ctx->sealalg = SEAL_ALG_DES;
+
+      /* The encryption key is the session key XOR
+        0xf0f0f0f0f0f0f0f0.  */
+      if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc)))
+        goto fail;
 
-   /* verify the credential, or use the default */
-   /*SUPPRESS 29*/
-   if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) {
-      OM_uint32 major;
+      for (i=0; i<ctx->enc->length; i++)
+        /*SUPPRESS 113*/
+        ctx->enc->contents[i] ^= 0xf0;
 
-      /*
-       * Release default cred prior to re-acquiring it, to notice when
-       * the ccache has changed.
-       */
-      major = kg_release_defcred(minor_status);
-      if (GSS_ERROR(major))
-        return major;
-      if ((major = kg_get_defcred(minor_status, &claimant_cred_handle)) &&
-         GSS_ERROR(major)) {
-        return(major);
+      if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq)))
+        goto fail;
+
+      break;
+
+   case ENCTYPE_DES3_CBC_SHA1:
+      ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
+      ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
+      ctx->cksum_size = 20;
+      ctx->sealalg = SEAL_ALG_DES3KD;
+
+      code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
+      if (code)
+        goto fail;
+      code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
+      if (code) {
+        krb5_free_keyblock (context, ctx->enc);
+        goto fail;
       }
-   } else {
-      OM_uint32 major;
-          
-      major = krb5_gss_validate_cred(minor_status, claimant_cred_handle);
-      if (GSS_ERROR(major))
-         return(major);
+      break;
+   case ENCTYPE_ARCFOUR_HMAC:
+      ctx->signalg = SGN_ALG_HMAC_MD5 ;
+      ctx->cksum_size = 8;
+      ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
+
+      code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
+      if (code)
+        goto fail;
+      code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
+      if (code) {
+        krb5_free_keyblock (context, ctx->enc);
+        goto fail;
+      }
+      break;       
+#if 0
+   case ENCTYPE_DES3_CBC_MD5:
+      enctype = ENCTYPE_DES3_CBC_RAW;
+      ctx->signalg = 3;
+      ctx->cksum_size = 16;
+      ctx->sealalg = 1;
+      break;
+#endif
+   default:
+      *minor_status = KRB5_BAD_ENCTYPE;
+      return GSS_S_FAILURE;
    }
+fail:
+   *minor_status = code;
+   return GSS_S_FAILURE;
+}
 
-   cred = (krb5_gss_cred_id_t) claimant_cred_handle;
+/*
+ * new_connection
+ *
+ * Do the grunt work of setting up a new context.
+ */
+static OM_uint32
+new_connection(
+   OM_uint32 *minor_status,
+   krb5_gss_cred_id_t cred,
+   gss_ctx_id_t *context_handle,
+   gss_name_t target_name,
+   gss_OID mech_type,
+   OM_uint32 req_flags,
+   OM_uint32 time_req,
+   gss_channel_bindings_t input_chan_bindings,
+   gss_buffer_t input_token,
+   gss_OID *actual_mech_type,
+   gss_buffer_t output_token,
+   OM_uint32 *ret_flags,
+   OM_uint32 *time_rec,
+   krb5_context context,
+   int default_mech)
+{
+   OM_uint32 major_status;
+   krb5_error_code code;
+   krb5_enctype *requested_enctypes;
+   krb5_creds *k_cred;
+   krb5_gss_ctx_id_rec *ctx, *ctx_free;
+   krb5_timestamp now;
+   gss_buffer_desc token;
 
-   /* verify the mech_type */
+   major_status = GSS_S_FAILURE;
+   token.length = 0;
+   token.value = NULL;
 
-   err = 0;
-   if (mech_type == GSS_C_NULL_OID) {
-       default_mech = 1;
-       if (cred->rfc_mech) {
-          mech_type = (gss_OID) gss_mech_krb5;
-       } else if (cred->prerfc_mech) {
-          mech_type = (gss_OID) gss_mech_krb5_old;
-       } else {
-          err = 1;
-       }
-   } else if (g_OID_equal(mech_type, gss_mech_krb5)) {
-       if (!cred->rfc_mech)
-          err = 1;
-   } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) {
-       if (!cred->prerfc_mech)
-          err = 1;
-   } else {
-       err = 1;
+   /* make sure the cred is usable for init */
+
+   if ((cred->usage != GSS_C_INITIATE) &&
+       (cred->usage != GSS_C_BOTH)) {
+      *minor_status = 0;
+      return(GSS_S_NO_CRED);
    }
-   
-   if (err) {
+
+   /* complain if the input token is non-null */
+
+   if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
       *minor_status = 0;
-      return(GSS_S_BAD_MECH);
+      return(GSS_S_DEFECTIVE_TOKEN);
    }
 
-   /* verify that the target_name is valid and usable */
+   /* create the ctx */
 
-   if (! kg_validate_name(target_name)) {
-      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
-      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+   if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
+       == NULL) {
+      *minor_status = ENOMEM;
+      return(GSS_S_FAILURE);
    }
 
-   /* is this a new connection or not? */
+   /* fill in the ctx */
+   memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
+   ctx_free = ctx;
+   if ((code = krb5_auth_con_init(context, &ctx->auth_context)))
+      goto fail;
+   krb5_auth_con_setflags(context, ctx->auth_context,
+                         KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+   ctx->initiate = 1;
+   ctx->gss_flags = KG_IMPLFLAGS(req_flags);
+   ctx->seed_init = 0;
+   ctx->big_endian = 0;  /* all initiators do little-endian, as per spec */
+   ctx->seqstate = 0;
+   ctx->nctypes = 0;
+   ctx->ctypes = 0;
+
+   if ((code = krb5_timeofday(context, &now)))
+      goto fail;
+
+   if (time_req == 0 || time_req == GSS_C_INDEFINITE) {
+      ctx->endtime = 0;
+   } else {
+      ctx->endtime = now + time_req;
+   }
 
-   /*SUPPRESS 29*/
-   if (*context_handle == GSS_C_NO_CONTEXT) {
-      /* make sure the cred is usable for init */
+   if ((code = krb5_copy_principal(context, cred->princ, &ctx->here)))
+      goto fail;
+      
+   if ((code = krb5_copy_principal(context, (krb5_principal) target_name,
+                                  &ctx->there)))
+      goto fail;
+
+   code = get_requested_enctypes(context, &requested_enctypes);
+   if (code)
+      goto fail;
+
+   code = get_credentials(context, cred, ctx->there, now,
+                         ctx->endtime, requested_enctypes, &k_cred);
+   free(requested_enctypes);
+   if (code)
+      goto fail;
+
+   if (default_mech) {
+      mech_type = (gss_OID) gss_mech_krb5;
+   }
 
-      if ((cred->usage != GSS_C_INITIATE) &&
-         (cred->usage != GSS_C_BOTH)) {
-        *minor_status = 0;
-        return(GSS_S_NO_CRED);
+   if (generic_gss_copy_oid(minor_status, mech_type, &ctx->mech_used)
+       != GSS_S_COMPLETE) {
+      code = *minor_status;
+      goto fail;
+   }
+   /*
+    * Now try to make it static if at all possible....
+    */
+   ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used);
+
+   {
+      /* gsskrb5 v1 */
+      if ((code = make_ap_req_v1(context, ctx,
+                                cred, k_cred, input_chan_bindings, 
+                                mech_type, &token))) {
+        if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
+            (code == KG_EMPTY_CCACHE))
+           major_status = GSS_S_NO_CRED;
+        if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
+           major_status = GSS_S_CREDENTIALS_EXPIRED;
+        goto fail;
       }
 
-      /* complain if the input token is non-null */
+      krb5_auth_con_getlocalseqnumber(context, ctx->auth_context,
+                                     &ctx->seq_send);
+      krb5_auth_con_getsendsubkey(context, ctx->auth_context,
+                                 &ctx->subkey);
+   }
 
-      if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
-        *minor_status = 0;
-        return(GSS_S_DEFECTIVE_TOKEN);
-      }
+   major_status = setup_enc(minor_status, ctx, context);
 
-      /* create the ctx */
+   if (k_cred) {
+      krb5_free_creds(context, k_cred);
+      k_cred = 0;
+   }
+      
+   /* at this point, the context is constructed and valid,
+      hence, releaseable */
 
-      if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
-         == NULL) {
-        *minor_status = ENOMEM;
-        return(GSS_S_FAILURE);
-      }
+   /* intern the context handle */
 
-      /* fill in the ctx */
-      memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
-      ctx_free = ctx;
-      if ((code = krb5_auth_con_init(context, &ctx->auth_context)))
-         goto fail;
-      krb5_auth_con_setflags(context, ctx->auth_context,
-                            KRB5_AUTH_CONTEXT_DO_SEQUENCE);
-      ctx->initiate = 1;
-      ctx->gss_flags = KG_IMPLFLAGS(req_flags);
-      ctx->seed_init = 0;
-      ctx->big_endian = 0;  /* all initiators do little-endian, as per spec */
-      ctx->seqstate = 0;
-      ctx->nctypes = 0;
-      ctx->ctypes = 0;
+   if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
+      code = G_VALIDATE_FAILED;
+      goto fail;
+   }
+   *context_handle = (gss_ctx_id_t) ctx;
+   ctx_free = 0;
 
+   /* compute time_rec */
+   if (time_rec) {
       if ((code = krb5_timeofday(context, &now)))
-         goto fail;
+        goto fail;
+      *time_rec = ctx->endtime - now;
+   }
 
-      if (time_req == 0 || time_req == GSS_C_INDEFINITE) {
-        ctx->endtime = 0;
-      } else {
-        ctx->endtime = now + time_req;
-      }
+   /* set the other returns */
+   *output_token = token;
 
-      if ((code = krb5_copy_principal(context, cred->princ, &ctx->here)))
-         goto fail;
-      
-      if ((code = krb5_copy_principal(context, (krb5_principal) target_name,
-                                     &ctx->there)))
-         goto fail;
+   if (ret_flags)
+      *ret_flags = ctx->gss_flags;
 
-      code = krb5_get_tgs_ktypes (context, 0, &default_enctypes);
-      if (code)
-         goto fail;
-      /* "i" denotes *next* slot to fill.  Don't forget to save room
-        for a trailing zero.  */
-      i = 0;
-      for (j = 0;
-          (default_enctypes[j] != 0
-           /* This part should be redundant, but let's be paranoid.  */
-           && i < N_WANTED_ENCTYPES);
-          j++) {
-
-         int is_duplicate_enctype;
-         int is_wanted_enctype;
-
-         krb5_enctype e = default_enctypes[j];
-
-         /* Is this enctype one of the ones we want for GSSAPI?  */
-         is_wanted_enctype = 0;
-         for (k = 0; k < N_WANTED_ENCTYPES; k++) {
-             if (wanted_enctypes[k] == e) {
-                 is_wanted_enctype = 1;
-                 break;
-             }
-         }
-         /* If unwanted, go to the next one. */
-         if (!is_wanted_enctype)
-             continue;
-
-         /* Is this enctype already in the list of enctypes to
-            request?  (Is it a duplicate?)  */
-         is_duplicate_enctype = 0;
-         for (k = 0; k < i; k++) {
-             if (requested_enctypes[k] == e) {
-                 is_duplicate_enctype = 1;
-                 break;
-             }
-         }
-         /* If it is not a duplicate, add it. */
-         if (!is_duplicate_enctype)
-             requested_enctypes[i++] = e;
-      }
-      krb5_free_ktypes(context, default_enctypes);
-      requested_enctypes[i++] = 0;
+   if (actual_mech_type)
+      *actual_mech_type = mech_type;
 
-      if ((code = get_credentials(context, cred, ctx->there, now,
-                                 ctx->endtime, requested_enctypes, &k_cred)))
-         goto fail;
+   /* return successfully */
 
-      if (default_mech) {
-        mech_type = (gss_OID) gss_mech_krb5;
-      }
+   *minor_status = 0;
+   if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
+      ctx->established = 0;
+      return(GSS_S_CONTINUE_NEEDED);
+   } else {
+      ctx->seq_recv = ctx->seq_send;
+      g_order_init(&(ctx->seqstate), ctx->seq_recv,
+                  (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, 
+                  (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0);
+      ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
+      ctx->established = 1;
+      return(GSS_S_COMPLETE);
+   }
 
-      if (generic_gss_copy_oid(minor_status, mech_type, &ctx->mech_used)
-         != GSS_S_COMPLETE) {
-         code = *minor_status;
-         goto fail;
-      }
-      /*
-       * Now try to make it static if at all possible....
-       */
-      ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used);
-
-      {
-         /* gsskrb5 v1 */
-         if ((code = make_ap_req_v1(context, ctx,
-                                    cred, k_cred, input_chan_bindings, 
-                                    mech_type, &token))) {
-             if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
-                 (code == KG_EMPTY_CCACHE))
-                 major_status = GSS_S_NO_CRED;
-             if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
-                 major_status = GSS_S_CREDENTIALS_EXPIRED;
-             goto fail;
-         }
-
-         krb5_auth_con_getlocalseqnumber(context, ctx->auth_context,
-                                         &ctx->seq_send);
-         krb5_auth_con_getsendsubkey(context, ctx->auth_context,
-                                     &ctx->subkey);
-
-         /* fill in the encryption descriptors */
-
-         switch(ctx->subkey->enctype) {
-         case ENCTYPE_DES_CBC_MD5:
-         case ENCTYPE_DES_CBC_MD4:
-         case ENCTYPE_DES_CBC_CRC:
-             ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
-             ctx->signalg = SGN_ALG_DES_MAC_MD5;
-             ctx->cksum_size = 8;
-             ctx->sealalg = SEAL_ALG_DES;
-
-             /* The encryption key is the session key XOR
-                0xf0f0f0f0f0f0f0f0.  */
-             if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc)))
-                 goto fail;
-
-             for (i=0; i<ctx->enc->length; i++)
-                 /*SUPPRESS 113*/
-                 ctx->enc->contents[i] ^= 0xf0;
-
-             if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq)))
-                 goto fail;
-
-             break;
-
-         case ENCTYPE_DES3_CBC_SHA1:
-             ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW;
-             ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD;
-             ctx->cksum_size = 20;
-             ctx->sealalg = SEAL_ALG_DES3KD;
-
-             code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
-             if (code)
-                 goto fail;
-             code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
-             if (code) {
-                 krb5_free_keyblock (context, ctx->enc);
-                 goto fail;
-             }
-             break;
-         case ENCTYPE_ARCFOUR_HMAC:
-           ctx->signalg = SGN_ALG_HMAC_MD5 ;
-           ctx->cksum_size = 8;
-           ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
-
-             code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc);
-             if (code)
-                 goto fail;
-             code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq);
-             if (code) {
-                 krb5_free_keyblock (context, ctx->enc);
-                 goto fail;
-             }
-             break;        
-#if 0
-         case ENCTYPE_DES3_CBC_MD5:
-             enctype = ENCTYPE_DES3_CBC_RAW;
-             ctx->signalg = 3;
-             ctx->cksum_size = 16;
-             ctx->sealalg = 1;
-             break;
-#endif
-         default:
-             *minor_status = KRB5_BAD_ENCTYPE;
-             return GSS_S_FAILURE;
-         }
+fail:
+   if (ctx_free) {
+       if (ctx_free->auth_context)
+          krb5_auth_con_free(context, ctx_free->auth_context);
+       if (ctx_free->here)
+          krb5_free_principal(context, ctx_free->here);
+       if (ctx_free->there)
+          krb5_free_principal(context, ctx_free->there);
+       if (ctx_free->subkey)
+          krb5_free_keyblock(context, ctx_free->subkey);
+       if (ctx_free->ctypes)
+          krb5_free_cksumtypes(context, ctx_free->ctypes);
+       xfree(ctx_free);
+   } else
+       (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
 
-      }
+   *minor_status = code;
+   return (major_status);
+}
 
-      if (k_cred) {
-          krb5_free_creds(context, k_cred);
-         k_cred = 0;
-      }
-      
-      /* at this point, the context is constructed and valid,
-        hence, releaseable */
+/*
+ * mutual_auth
+ *
+ * Handle the reply from the acceptor, if we're doing mutual auth.
+ */
+static OM_uint32
+mutual_auth(
+   OM_uint32 *minor_status,
+   krb5_gss_cred_id_t cred,
+   gss_ctx_id_t *context_handle,
+   gss_name_t target_name,
+   gss_OID mech_type,
+   OM_uint32 req_flags,
+   OM_uint32 time_req,
+   gss_channel_bindings_t input_chan_bindings,
+   gss_buffer_t input_token,
+   gss_OID *actual_mech_type,
+   gss_buffer_t output_token,
+   OM_uint32 *ret_flags,
+   OM_uint32 *time_rec,
+   krb5_context context)
+{
+   OM_uint32 major_status;
+   unsigned char *ptr;
+   char *sptr;
+   krb5_data ap_rep;
+   krb5_ap_rep_enc_part *ap_rep_data;
+   krb5_timestamp now;
+   krb5_gss_ctx_id_rec *ctx;
+   krb5_error *krb_error;
+   krb5_error_code code;
 
-      /* intern the context handle */
+   major_status = GSS_S_FAILURE;
 
-      if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
-         code = G_VALIDATE_FAILED;
-         goto fail;
-      }
-      *context_handle = (gss_ctx_id_t) ctx;
-      ctx_free = 0;
-
-      /* compute time_rec */
-      if (time_rec) {
-        if ((code = krb5_timeofday(context, &now)))
-            goto fail;
-        *time_rec = ctx->endtime - now;
-      }
+   /* validate the context handle */
+   /*SUPPRESS 29*/
+   if (! kg_validate_ctx_id(*context_handle)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      return(GSS_S_NO_CONTEXT);
+   }
 
-      /* set the other returns */
-      *output_token = token;
+   ctx = (gss_ctx_id_t) *context_handle;
 
-      if (ret_flags)
-        *ret_flags = ctx->gss_flags;
+   /* make sure the context is non-established, and that certain
+      arguments are unchanged */
 
-      if (actual_mech_type)
-        *actual_mech_type = mech_type;
+   if ((ctx->established) ||
+       ((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) {
+      code = KG_CONTEXT_ESTABLISHED;
+      goto fail;
+   }
 
-      /* return successfully */
+   if (! krb5_principal_compare(context, ctx->there, 
+                               (krb5_principal) target_name)) {
+      (void)krb5_gss_delete_sec_context(minor_status, 
+                                       context_handle, NULL);
+      code = 0;
+      major_status = GSS_S_BAD_NAME;
+      goto fail;
+   }
 
-      *minor_status = 0;
-      if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
-        ctx->established = 0;
-        return(GSS_S_CONTINUE_NEEDED);
-      } else {
-        ctx->seq_recv = ctx->seq_send;
-        g_order_init(&(ctx->seqstate), ctx->seq_recv,
-                     (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, 
-                     (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0);
-        ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
-        ctx->established = 1;
-        /* fall through to GSS_S_COMPLETE */
-      }
-   } else {
-      unsigned char *ptr;
-      char *sptr;
-      krb5_data ap_rep;
-      krb5_ap_rep_enc_part *ap_rep_data;
-      krb5_error *krb_error;
-
-      /* validate the context handle */
-      /*SUPPRESS 29*/
-      if (! kg_validate_ctx_id(*context_handle)) {
-        *minor_status = (OM_uint32) G_VALIDATE_FAILED;
-        return(GSS_S_NO_CONTEXT);
-      }
+   /* verify the token and leave the AP_REP message in ap_rep */
 
-      ctx = (gss_ctx_id_t) *context_handle;
+   if (input_token == GSS_C_NO_BUFFER) {
+      (void)krb5_gss_delete_sec_context(minor_status, 
+                                       context_handle, NULL);
+      code = 0;
+      major_status = GSS_S_DEFECTIVE_TOKEN;
+      goto fail;
+   }
 
-      /* make sure the context is non-established, and that certain
-        arguments are unchanged */
+   ptr = (unsigned char *) input_token->value;
 
-      if ((ctx->established) ||
-         (((gss_cred_id_t) cred) != claimant_cred_handle) ||
-         ((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) {
-         code = KG_CONTEXT_ESTABLISHED;
-         goto fail;
-      }
+   if (g_verify_token_header((gss_OID) ctx->mech_used,
+                            &(ap_rep.length),
+                            &ptr, KG_TOK_CTX_AP_REP,
+                            input_token->length)) {
+      if (g_verify_token_header((gss_OID) ctx->mech_used,
+                               &(ap_rep.length),
+                               &ptr, KG_TOK_CTX_ERROR,
+                               input_token->length) == 0) {
+
+        /* Handle a KRB_ERROR message from the server */
 
-      if (! krb5_principal_compare(context, ctx->there, 
-                                  (krb5_principal) target_name)) {
-        (void)krb5_gss_delete_sec_context(minor_status, 
-                                          context_handle, NULL);
-        code = 0;
-        major_status = GSS_S_BAD_NAME;
+        sptr = (char *) ptr;           /* PC compiler bug */
+        TREAD_STR(sptr, ap_rep.data, ap_rep.length);
+                     
+        code = krb5_rd_error(context, &ap_rep, &krb_error);
+        if (code)
+           goto fail;
+        if (krb_error->error)
+           code = krb_error->error + ERROR_TABLE_BASE_krb5;
+        else
+           code = 0;
+        krb5_free_error(context, krb_error);
         goto fail;
+      } else {
+        *minor_status = 0;
+        return(GSS_S_DEFECTIVE_TOKEN);
       }
+   }
 
-      /* verify the token and leave the AP_REP message in ap_rep */
+   sptr = (char *) ptr;                      /* PC compiler bug */
+   TREAD_STR(sptr, ap_rep.data, ap_rep.length);
 
-      if (input_token == GSS_C_NO_BUFFER) {
-        (void)krb5_gss_delete_sec_context(minor_status, 
-                                          context_handle, NULL);
-        code = 0;
-        major_status = GSS_S_DEFECTIVE_TOKEN;
+   /* decode the ap_rep */
+   if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep,
+                          &ap_rep_data))) {
+      /*
+       * XXX A hack for backwards compatiblity.
+       * To be removed in 1999 -- proven 
+       */
+      krb5_auth_con_setuseruserkey(context, ctx->auth_context,
+                                  ctx->subkey);
+      if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
+                      &ap_rep_data)))
         goto fail;
-      }
+   }
 
-      ptr = (unsigned char *) input_token->value;
+   /* store away the sequence number */
+   ctx->seq_recv = ap_rep_data->seq_number;
+   g_order_init(&(ctx->seqstate), ctx->seq_recv,
+               (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
+               (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) !=0);
 
-      if ((err = g_verify_token_header((gss_OID) ctx->mech_used,
-                                      &(ap_rep.length),
-                                      &ptr, KG_TOK_CTX_AP_REP,
-                                      input_token->length))) {
-         if (g_verify_token_header((gss_OID) ctx->mech_used,
-                                   &(ap_rep.length),
-                                   &ptr, KG_TOK_CTX_ERROR,
-                                   input_token->length) == 0) {
+   /* free the ap_rep_data */
+   krb5_free_ap_rep_enc_part(context, ap_rep_data);
 
-             /* Handle a KRB_ERROR message from the server */
+   /* set established */
+   ctx->established = 1;
 
-             sptr = (char *) ptr;           /* PC compiler bug */
-             TREAD_STR(sptr, ap_rep.data, ap_rep.length);
-                     
-             code = krb5_rd_error(context, &ap_rep, &krb_error);
-             if (code)
-                 goto fail;
-             if (krb_error->error)
-                 code = krb_error->error + ERROR_TABLE_BASE_krb5;
-             else
-                 code = 0;
-             krb5_free_error(context, krb_error);
-             goto fail;
-         } else {
-             *minor_status = 0;
-             return(GSS_S_DEFECTIVE_TOKEN);
-         }
-      }
+   /* set returns */
 
-      sptr = (char *) ptr;                      /* PC compiler bug */
-      TREAD_STR(sptr, ap_rep.data, ap_rep.length);
-
-      /* decode the ap_rep */
-      if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep,
-                             &ap_rep_data))) {
-         /*
-          * XXX A hack for backwards compatiblity.
-          * To be removed in 1999 -- proven 
-          */
-         krb5_auth_con_setuseruserkey(context, ctx->auth_context,
-                                      ctx->subkey);
-         if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
-                          &ap_rep_data)))
-             goto fail;
-      }
+   if (time_rec) {
+      if ((code = krb5_timeofday(context, &now)))
+        goto fail;
+      *time_rec = ctx->endtime - now;
+   }
 
-      /* store away the sequence number */
-      ctx->seq_recv = ap_rep_data->seq_number;
-      g_order_init(&(ctx->seqstate), ctx->seq_recv,
-                  (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
-                  (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) !=0);
+   if (ret_flags)
+      *ret_flags = ctx->gss_flags;
 
-      /* free the ap_rep_data */
-      krb5_free_ap_rep_enc_part(context, ap_rep_data);
+   if (actual_mech_type)
+      *actual_mech_type = mech_type;
 
-      /* set established */
-      ctx->established = 1;
+   /* success */
 
-      /* set returns */
+   *minor_status = 0;
+   return GSS_S_COMPLETE;
 
-      if (time_rec) {
-        if ((code = krb5_timeofday(context, &now)))
-                goto fail;
-        *time_rec = ctx->endtime - now;
-      }
+fail:
+   (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
 
-      if (ret_flags)
-        *ret_flags = ctx->gss_flags;
+   *minor_status = code;
+   return (major_status);
+}
 
-      if (actual_mech_type)
-        *actual_mech_type = mech_type;
+OM_uint32
+krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
+                         context_handle, target_name, mech_type,
+                         req_flags, time_req, input_chan_bindings,
+                         input_token, actual_mech_type, output_token,
+                         ret_flags, time_rec)
+    OM_uint32 *minor_status;
+    gss_cred_id_t claimant_cred_handle;
+    gss_ctx_id_t *context_handle;
+    gss_name_t target_name;
+    gss_OID mech_type;
+    OM_uint32 req_flags;
+    OM_uint32 time_req;
+    gss_channel_bindings_t input_chan_bindings;
+    gss_buffer_t input_token;
+    gss_OID *actual_mech_type;
+    gss_buffer_t output_token;
+    OM_uint32 *ret_flags;
+    OM_uint32 *time_rec;
+{
+   krb5_context context;
+   krb5_gss_cred_id_t cred;
+   int err;
+   int default_mech = 0;
+   OM_uint32 major_status;
+   OM_uint32 tmp_min_stat;
+
+   if (GSS_ERROR(kg_get_context(minor_status, &context)))
+      return(GSS_S_FAILURE);
+
+   /* set up return values so they can be "freed" successfully */
+
+   major_status = GSS_S_FAILURE; /* Default major code */
+   output_token->length = 0;
+   output_token->value = NULL;
+   if (actual_mech_type)
+      *actual_mech_type = NULL;
 
-      /* success */
+   /* verify that the target_name is valid and usable */
 
+   if (! kg_validate_name(target_name)) {
+      *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+      return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+   }
+
+   /* verify the credential, or use the default */
+   /*SUPPRESS 29*/
+   if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) {
+      major_status = kg_get_defcred(minor_status, &cred);
+      if (major_status && GSS_ERROR(major_status)) {
+        return(major_status);
+      }
+   } else {
+      major_status = krb5_gss_validate_cred(minor_status, claimant_cred_handle);
+      if (GSS_ERROR(major_status))
+         return(major_status);
+      cred = (krb5_gss_cred_id_t) claimant_cred_handle;
+   }
+
+   /* verify the mech_type */
+
+   err = 0;
+   if (mech_type == GSS_C_NULL_OID) {
+       default_mech = 1;
+       if (cred->rfc_mech) {
+          mech_type = (gss_OID) gss_mech_krb5;
+       } else if (cred->prerfc_mech) {
+          mech_type = (gss_OID) gss_mech_krb5_old;
+       } else {
+          err = 1;
+       }
+   } else if (g_OID_equal(mech_type, gss_mech_krb5)) {
+       if (!cred->rfc_mech)
+          err = 1;
+   } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) {
+       if (!cred->prerfc_mech)
+          err = 1;
+   } else {
+       err = 1;
+   }
+   
+   if (err) {
+      if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
+        krb5_gss_release_cred(minor_status, (gss_cred_id_t)cred);
       *minor_status = 0;
-      /* fall through to GSS_S_COMPLETE */
+      return(GSS_S_BAD_MECH);
    }
 
-   return(GSS_S_COMPLETE);
+   /* is this a new connection or not? */
 
-fail:
-   if (ctx_free) {
-       if (ctx_free->auth_context)
-          krb5_auth_con_free(context, ctx_free->auth_context);
-       if (ctx_free->here)
-          krb5_free_principal(context, ctx_free->here);
-       if (ctx_free->there)
-          krb5_free_principal(context, ctx_free->there);
-       if (ctx_free->subkey)
-          krb5_free_keyblock(context, ctx_free->subkey);
-       if (ctx_free->ctypes)
-          krb5_free_cksumtypes(context, ctx_free->ctypes);
-       xfree(ctx_free);
-   } else
-       (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
+   /*SUPPRESS 29*/
+   if (*context_handle == GSS_C_NO_CONTEXT) {
+      major_status = new_connection(minor_status, cred, context_handle,
+                                   target_name, mech_type, req_flags,
+                                   time_req, input_chan_bindings,
+                                   input_token, actual_mech_type,
+                                   output_token, ret_flags, time_rec,
+                                   context, default_mech);
+   } else {
+      major_status = mutual_auth(minor_status, cred, context_handle,
+                                target_name, mech_type, req_flags,
+                                time_req, input_chan_bindings,
+                                input_token, actual_mech_type,
+                                output_token, ret_flags, time_rec,
+                                context);
+   }
 
-   *minor_status = code;
-   return (major_status);
+   if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
+      krb5_gss_release_cred(&tmp_min_stat, (gss_cred_id_t)cred);
+
+   return(major_status);
 }
index a79034d9ec43877e9180cb2c9b5ac2c1513877d0..83782162bedf91fdeb7f9b7b86ee912bf678a4a8 100644 (file)
@@ -91,6 +91,8 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
    gss_OID_set mechs;
    OM_uint32 ret;
 
+   ret = GSS_S_FAILURE;
+
    if (GSS_ERROR(kg_get_context(minor_status, &context)))
       return(GSS_S_FAILURE);
 
@@ -102,7 +104,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
    if (cred_handle == GSS_C_NO_CREDENTIAL) {
       OM_uint32 major;
 
-      if ((major = kg_get_defcred(minor_status, &cred_handle)) &&
+      if ((major = kg_get_defcred(minor_status, (gss_cred_id_t)&cred)) &&
          GSS_ERROR(major)) {
         return(major);
       }
@@ -112,13 +114,13 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
       major = krb5_gss_validate_cred(minor_status, cred_handle);
       if (GSS_ERROR(major))
          return(major);
+      cred = (krb5_gss_cred_id_t) cred_handle;
    }
 
-   cred = (krb5_gss_cred_id_t) cred_handle;
-
    if ((code = krb5_timeofday(context, &now))) {
       *minor_status = code;
-      return(GSS_S_FAILURE);
+      ret = GSS_S_FAILURE;
+      goto fail;
    }
 
    if (cred->tgt_expire > 0) {
@@ -132,7 +134,8 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
       if (cred->princ &&
          (code = krb5_copy_principal(context, cred->princ, &ret_name))) {
         *minor_status = code;
-        return(GSS_S_FAILURE);
+        ret = GSS_S_FAILURE;
+        goto fail;
       }
    }
 
@@ -149,7 +152,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
                                                           &mechs)))) {
           krb5_free_principal(context, ret_name);
           /* *minor_status set above */
-          return(ret);
+          goto fail;
        }
    }
 
@@ -172,8 +175,18 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
    if (mechanisms)
       *mechanisms = mechs;
 
+   if (cred_handle == GSS_C_NO_CREDENTIAL)
+       krb5_gss_release_cred(minor_status, (gss_cred_id_t)cred);
+
    *minor_status = 0;
    return((lifetime == 0)?GSS_S_CREDENTIALS_EXPIRED:GSS_S_COMPLETE);
+fail:
+   if (cred_handle == GSS_C_NO_CREDENTIAL) {
+       OM_uint32 tmp_min_stat;
+
+       krb5_gss_release_cred(&tmp_min_stat, (gss_cred_id_t)cred);
+   }
+   return ret;
 }
 
 /* V2 interface */
index 0d81399af254ad4ecccc6e8098e986f1cf5ba514..43d5ca1c2efae7edd0166eb52c173caae543a323 100644 (file)
@@ -34,8 +34,10 @@ krb5_gss_release_cred(minor_status, cred_handle)
    if (GSS_ERROR(kg_get_context(minor_status, &context)))
       return(GSS_S_FAILURE);
 
-   if (*cred_handle == GSS_C_NO_CREDENTIAL)
-      return(kg_release_defcred(minor_status));
+   if (*cred_handle == GSS_C_NO_CREDENTIAL) {
+      *minor_status = 0;
+      return(GSS_S_COMPLETE);
+   }
 
    if (! kg_delete_cred_id(*cred_handle)) {
       *minor_status = (OM_uint32) G_VALIDATE_FAILED;
index 9a612201b5b18a5a6c07741a9ed38ad5560a0b78..236a83afff14452bbb4c27f2e90de1ced3eb4c9f 100644 (file)
@@ -38,7 +38,6 @@ gss_krb5_ccache_name(minor_status, name, out_name)
 {
        krb5_context context;
        krb5_error_code retval;
-       OM_uint32 foo_stat;
        static char *oldname = NULL;
        const char *tmpname = NULL;
 
@@ -66,6 +65,5 @@ gss_krb5_ccache_name(minor_status, name, out_name)
                *minor_status = retval;
                return GSS_S_FAILURE;
        }
-       kg_release_defcred(&foo_stat);
        return GSS_S_COMPLETE;
 }