Make gss_acquire_cred_with_password() like Solaris
Solaris'/Illumos' gss_acquire_cred_with_password() does not have side-effects. MIT and Heimdal have differed, but it's now agreed that the Solaris/Illumos behavior is correct. To make a credential obained with gss_acquire_cred_with_password() available to other processes, use gss_store_cred().
This commit is contained in:
		| @@ -80,151 +80,282 @@ get_keytab(krb5_context context, krb5_keytab *keytab) | ||||
|     return (kret); | ||||
| } | ||||
|  | ||||
| static OM_uint32 acquire_initiator_cred | ||||
| 		  (OM_uint32 *minor_status, | ||||
| 		   krb5_context context, | ||||
| 		   gss_const_OID credential_type, | ||||
| 		   const void *credential_data, | ||||
| 		   OM_uint32 time_req, | ||||
| 		   gss_const_OID desired_mech, | ||||
| 		   gss_cred_usage_t cred_usage, | ||||
| 		   gsskrb5_cred handle | ||||
| 		  ) | ||||
| /* | ||||
|  * This function produces a cred with a MEMORY ccache containing a TGT | ||||
|  * acquired with a password. | ||||
|  */ | ||||
| static OM_uint32 | ||||
| acquire_cred_with_password(OM_uint32 *minor_status, | ||||
|                            krb5_context context, | ||||
|                            const char *password, | ||||
|                            OM_uint32 time_req, | ||||
|                            gss_const_OID desired_mech, | ||||
|                            gss_cred_usage_t cred_usage, | ||||
|                            gsskrb5_cred handle) | ||||
| { | ||||
|     OM_uint32 ret; | ||||
|     OM_uint32 ret = GSS_S_FAILURE; | ||||
|     krb5_creds cred; | ||||
|     krb5_principal def_princ; | ||||
|     krb5_get_init_creds_opt *opt; | ||||
|     krb5_ccache ccache; | ||||
|     krb5_keytab keytab; | ||||
|     krb5_ccache ccache = NULL; | ||||
|     krb5_error_code kret; | ||||
|     int try_get_init_creds = 0; | ||||
|     time_t now; | ||||
|     OM_uint32 left; | ||||
|  | ||||
|     keytab = NULL; | ||||
|     ccache = NULL; | ||||
|     def_princ = NULL; | ||||
|     ret = GSS_S_FAILURE; | ||||
|     if (cred_usage == GSS_C_ACCEPT) { | ||||
|         /* | ||||
|          * TODO: Here we should eventually support user2user (when we get | ||||
|          *       support for that via an extension to the mechanism | ||||
|          *       allowing for more than two security context tokens), | ||||
|          *       and/or new unique MEMORY keytabs (we have MEMORY keytab | ||||
|          *       support, but we don't have a keytab equivalent of | ||||
|          *       krb5_cc_new_unique()).  Either way, for now we can't | ||||
|          *       support this. | ||||
|          */ | ||||
|         *minor_status = ENOTSUP; /* XXX Better error? */ | ||||
|         return GSS_S_FAILURE; | ||||
|     } | ||||
|  | ||||
|     memset(&cred, 0, sizeof(cred)); | ||||
|  | ||||
|     /* | ||||
|      * If we have a preferred principal, lets try to find it in all | ||||
|      * caches, otherwise, fall back to default cache, ignore all | ||||
|      * errors while searching. | ||||
|      */ | ||||
|  | ||||
|     if (credential_type != GSS_C_NO_OID && | ||||
| 	!gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { | ||||
| 	kret = KRB5_NOCREDS_SUPPLIED; /* XXX */ | ||||
| 	goto end; | ||||
|     if (handle->principal == NULL) { | ||||
|         kret = krb5_get_default_principal(context, &handle->principal); | ||||
|         if (kret) | ||||
|             goto end; | ||||
|     } | ||||
|  | ||||
|     if (handle->principal) { | ||||
| 	kret = krb5_cc_cache_match(context, | ||||
| 				   handle->principal, | ||||
| 				   &ccache); | ||||
| 	if (kret == 0) { | ||||
| 	    ret = GSS_S_COMPLETE; | ||||
| 	    goto found; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     kret = krb5_cc_default(context, &ccache); | ||||
|     if (kret == 0) | ||||
|         kret = krb5_cc_get_principal(context, ccache, &def_princ); | ||||
|     if (kret != 0) { | ||||
| 	/* we'll try to use a keytab below */ | ||||
| 	krb5_cc_close(context, ccache); | ||||
| 	def_princ = NULL; | ||||
| 	kret = 0; | ||||
|         try_get_init_creds = 1; | ||||
|     } else if (handle->principal == NULL)  { | ||||
| 	kret = krb5_copy_principal(context, def_princ, &handle->principal); | ||||
| 	if (kret) | ||||
| 	    goto end; | ||||
|     } else if (handle->principal != NULL && | ||||
| 	       krb5_principal_compare(context, handle->principal, | ||||
| 				      def_princ) == FALSE) { | ||||
| 	krb5_cc_close(context, ccache); | ||||
| 	ccache = NULL; | ||||
|         try_get_init_creds = 1; | ||||
|     } | ||||
|     krb5_free_principal(context, def_princ); | ||||
|     def_princ = NULL; | ||||
|  | ||||
|     if (try_get_init_creds) { | ||||
| 	if (handle->principal == NULL) { | ||||
| 	    kret = krb5_get_default_principal(context, &handle->principal); | ||||
| 	    if (kret) | ||||
| 		goto end; | ||||
| 	} | ||||
| 	kret = krb5_get_init_creds_opt_alloc(context, &opt); | ||||
| 	if (kret) | ||||
| 	    goto end; | ||||
| 	if (credential_type != GSS_C_NO_OID && | ||||
| 	    gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { | ||||
| 	    gss_buffer_t pwbuf = (gss_buffer_t)credential_data; | ||||
|             char *pw; | ||||
|  | ||||
|             /* Add possibly-missing NUL terminator */ | ||||
|             pw = strndup(pwbuf->value, pwbuf->length); | ||||
|             if (pw == NULL) { | ||||
|                 kret = krb5_enomem(context); | ||||
|                 goto end; | ||||
|             } | ||||
|  | ||||
|             kret = krb5_get_init_creds_password(context, &cred, | ||||
|                                                 handle->principal, pw, | ||||
|                                                 NULL, NULL, 0, NULL, opt); | ||||
|             free(pw); | ||||
| 	} else { | ||||
| 	    kret = get_keytab(context, &keytab); | ||||
| 	    if (kret) { | ||||
| 		krb5_get_init_creds_opt_free(context, opt); | ||||
| 		goto end; | ||||
| 	    } | ||||
| 	    kret = krb5_get_init_creds_keytab(context, &cred, | ||||
| 					      handle->principal, keytab, | ||||
| 					      0, NULL, opt); | ||||
| 	} | ||||
| 	krb5_get_init_creds_opt_free(context, opt); | ||||
| 	if (kret) | ||||
| 	    goto end; | ||||
| 	kret = krb5_cc_new_unique(context, krb5_cc_type_memory, | ||||
| 				  NULL, &ccache); | ||||
| 	if (kret) | ||||
| 	    goto end; | ||||
| 	kret = krb5_cc_initialize(context, ccache, cred.client); | ||||
| 	if (kret) { | ||||
| 	    krb5_cc_destroy(context, ccache); | ||||
| 	    goto end; | ||||
| 	} | ||||
| 	kret = krb5_cc_store_cred(context, ccache, &cred); | ||||
| 	if (kret) { | ||||
| 	    krb5_cc_destroy(context, ccache); | ||||
| 	    goto end; | ||||
| 	} | ||||
| 	handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; | ||||
|     } | ||||
|  | ||||
| found: | ||||
|     krb5_timeofday(context, &now); | ||||
|     ret = __gsskrb5_ccache_lifetime(minor_status, | ||||
|                                     context, | ||||
|                                     ccache, | ||||
|                                     handle->principal, | ||||
|                                     &left); | ||||
|     if (ret != GSS_S_COMPLETE) { | ||||
|         krb5_cc_close(context, ccache); | ||||
|     kret = krb5_get_init_creds_opt_alloc(context, &opt); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|  | ||||
|     /* | ||||
|      * Get the current time before the AS exchange so we don't | ||||
|      * accidentally end up returning a value that puts advertised | ||||
|      * expiration past the real expiration. | ||||
|      * | ||||
|      * We need to do this because krb5_cc_get_lifetime() returns a | ||||
|      * relative time that we need to add to the current time.  We ought | ||||
|      * to have a version of krb5_cc_get_lifetime() that returns absolute | ||||
|      * time... | ||||
|      */ | ||||
|     krb5_timeofday(context, &now); | ||||
|  | ||||
|     kret = krb5_get_init_creds_password(context, &cred, handle->principal, | ||||
|                                         password, NULL, NULL, 0, NULL, opt); | ||||
|     krb5_get_init_creds_opt_free(context, opt); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|  | ||||
|     kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|  | ||||
|     kret = krb5_cc_initialize(context, ccache, cred.client); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|  | ||||
|     kret = krb5_cc_store_cred(context, ccache, &cred); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|  | ||||
|     handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; | ||||
|  | ||||
|     ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, | ||||
|                                     handle->principal, &left); | ||||
|     if (ret != GSS_S_COMPLETE) | ||||
|         goto end; | ||||
|     } | ||||
|     handle->endtime = now + left; | ||||
|     handle->ccache = ccache; | ||||
|     ccache = NULL; | ||||
|     ret = GSS_S_COMPLETE; | ||||
|     kret = 0; | ||||
|  | ||||
| end: | ||||
|     if (ccache != NULL) | ||||
|         krb5_cc_destroy(context, ccache); | ||||
|     if (cred.client != NULL) | ||||
| 	krb5_free_cred_contents(context, &cred); | ||||
|     if (ret != GSS_S_COMPLETE && kret != 0) | ||||
| 	*minor_status = kret; | ||||
|     return (ret); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Acquires an initiator credential from a ccache or using a keytab. | ||||
|  */ | ||||
| static OM_uint32 | ||||
| acquire_initiator_cred(OM_uint32 *minor_status, | ||||
|                        krb5_context context, | ||||
|                        OM_uint32 time_req, | ||||
|                        gss_const_OID desired_mech, | ||||
|                        gss_cred_usage_t cred_usage, | ||||
|                        gsskrb5_cred handle) | ||||
| { | ||||
|     OM_uint32 ret = GSS_S_FAILURE; | ||||
|     krb5_creds cred; | ||||
|     krb5_get_init_creds_opt *opt; | ||||
|     krb5_principal def_princ = NULL; | ||||
|     krb5_ccache def_ccache = NULL; | ||||
|     krb5_ccache ccache = NULL;  /* we may store into this ccache */ | ||||
|     krb5_keytab keytab = NULL; | ||||
|     krb5_error_code kret = 0; | ||||
|     OM_uint32 left; | ||||
|     time_t lifetime = 0; | ||||
|     time_t now; | ||||
|  | ||||
|     memset(&cred, 0, sizeof(cred)); | ||||
|  | ||||
|     /* | ||||
|      * Get current time early so we can set handle->endtime to a value that | ||||
|      * cannot accidentally be past the real endtime.  We need a variant of | ||||
|      * krb5_cc_get_lifetime() that returns absolute endtime. | ||||
|      */ | ||||
|     krb5_timeofday(context, &now); | ||||
|  | ||||
|     /* | ||||
|      * First look for a ccache that has the desired_name (which may be | ||||
|      * the default credential name). | ||||
|      * | ||||
|      * If we don't have an unexpired credential, acquire one with a | ||||
|      * keytab. | ||||
|      * | ||||
|      * If we acquire one with a keytab, save it in the ccache we found | ||||
|      * with the expired credential, if any. | ||||
|      * | ||||
|      * If we don't have any such ccache, then use a MEMORY ccache. | ||||
|      */ | ||||
|  | ||||
|     if (handle->principal != NULL) { | ||||
|         /* | ||||
|          * Not default credential case.  See if we can find a ccache in | ||||
|          * the cccol for the desired_name. | ||||
|          */ | ||||
| 	kret = krb5_cc_cache_match(context, | ||||
| 				   handle->principal, | ||||
| 				   &ccache); | ||||
| 	if (kret == 0) { | ||||
|             kret = krb5_cc_get_lifetime(context, ccache, &lifetime); | ||||
|             if (kret == 0) { | ||||
|                 if (lifetime > 0) | ||||
|                     goto found; | ||||
|                 else | ||||
|                     goto try_keytab; | ||||
|             } | ||||
| 	} | ||||
|         /* | ||||
|          * Fall through.  We shouldn't find this in the default ccache | ||||
|          * either, but we'll give it a try, then we'll try using a keytab. | ||||
|          */ | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Either desired_name was GSS_C_NO_NAME (default cred) or | ||||
|      * krb5_cc_cache_match() failed (or found expired). | ||||
|      */ | ||||
|     kret = krb5_cc_default(context, &def_ccache); | ||||
|     if (kret != 0) | ||||
|         goto try_keytab; | ||||
|     kret = krb5_cc_get_lifetime(context, def_ccache, &lifetime); | ||||
|     if (kret != 0) | ||||
|         lifetime = 0; | ||||
|     kret = krb5_cc_get_principal(context, def_ccache, &def_princ); | ||||
|     if (kret != 0) | ||||
|         goto try_keytab; | ||||
|     /* | ||||
|      * Have a default ccache; see if it matches desired_name. | ||||
|      */ | ||||
|     if (handle->principal == NULL || | ||||
|         krb5_principal_compare(context, handle->principal, | ||||
|                                def_princ) == TRUE) { | ||||
|         /* | ||||
|          * It matches. | ||||
|          * | ||||
|          * If we end up trying a keytab then we can write the result to | ||||
|          * the default ccache. | ||||
|          */ | ||||
|         if (handle->principal == NULL) { | ||||
|             kret = krb5_copy_principal(context, def_princ, &handle->principal); | ||||
|             if (kret) | ||||
|                 goto end; | ||||
|         } | ||||
|         if (ccache != NULL) | ||||
|             krb5_cc_close(context, ccache); | ||||
|         ccache = def_ccache; | ||||
|         def_ccache = NULL; | ||||
|         if (lifetime > 0) | ||||
|             goto found; | ||||
|         /* else we fall through and try using a keytab */ | ||||
|     } | ||||
|  | ||||
| try_keytab: | ||||
|     if (handle->principal == NULL) { | ||||
|         /* We need to know what client principal to use */ | ||||
|         kret = krb5_get_default_principal(context, &handle->principal); | ||||
|         if (kret) | ||||
|             goto end; | ||||
|     } | ||||
|     kret = get_keytab(context, &keytab); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|  | ||||
|     kret = krb5_get_init_creds_opt_alloc(context, &opt); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|     krb5_timeofday(context, &now); | ||||
|     kret = krb5_get_init_creds_keytab(context, &cred, handle->principal, | ||||
|                                       keytab, 0, NULL, opt); | ||||
|     krb5_get_init_creds_opt_free(context, opt); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|  | ||||
|     /* | ||||
|      * We got a credential with a keytab.  Save it if we can. | ||||
|      */ | ||||
|     if (ccache == NULL) { | ||||
|         /* | ||||
|          * There's no ccache we can overwrite with the credentials we acquired | ||||
|          * with a keytab.  We'll use a MEMORY ccache then. | ||||
|          * | ||||
|          * Note that an application that falls into this repeatedly will do an | ||||
|          * AS exchange every time it acquires a credential handle.  Hopefully | ||||
|          * this doesn't happen much.  A workaround is to kinit -k once so that | ||||
|          * we always re-initialize the matched/default ccache here.  I.e., once | ||||
|          * there's a FILE/DIR ccache, we'll keep it frash automatically if we | ||||
|          * have a keytab, but if there's no FILE/DIR ccache, then we'll | ||||
|          * get a fresh credential *every* time we're asked. | ||||
|          */ | ||||
|         kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache); | ||||
|         if (kret) | ||||
|             goto end; | ||||
|         handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; | ||||
|     } /* else we'll re-initialize whichever ccache we matched above */ | ||||
|  | ||||
|     kret = krb5_cc_initialize(context, ccache, cred.client); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|     kret = krb5_cc_store_cred(context, ccache, &cred); | ||||
|     if (kret) | ||||
|         goto end; | ||||
|  | ||||
| found: | ||||
|     assert(handle->principal != NULL); | ||||
|     ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache, | ||||
|                                     handle->principal, &left); | ||||
|     if (ret != GSS_S_COMPLETE) | ||||
|         goto end; | ||||
|     handle->endtime = now + left; | ||||
|     handle->ccache = ccache; | ||||
|     ccache = NULL; | ||||
|     ret = GSS_S_COMPLETE; | ||||
|     kret = 0; | ||||
|  | ||||
| end: | ||||
|     if (ccache != NULL) { | ||||
|         if ((handle->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) != 0) | ||||
|             krb5_cc_destroy(context, ccache); | ||||
|         else | ||||
|             krb5_cc_close(context, ccache); | ||||
|     } | ||||
|     if (def_ccache != NULL) | ||||
|         krb5_cc_close(context, def_ccache); | ||||
|     if (cred.client != NULL) | ||||
| 	krb5_free_cred_contents(context, &cred); | ||||
|     if (def_princ != NULL) | ||||
| @@ -236,27 +367,19 @@ end: | ||||
|     return (ret); | ||||
| } | ||||
|  | ||||
| static OM_uint32 acquire_acceptor_cred | ||||
| 		  (OM_uint32 * minor_status, | ||||
| 		   krb5_context context, | ||||
| 		   gss_const_OID credential_type, | ||||
| 		   const void *credential_data, | ||||
| 		   OM_uint32 time_req, | ||||
| 		   gss_const_OID desired_mech, | ||||
| 		   gss_cred_usage_t cred_usage, | ||||
| 		   gsskrb5_cred handle | ||||
| 		  ) | ||||
| static OM_uint32 | ||||
| acquire_acceptor_cred(OM_uint32 * minor_status, | ||||
|                       krb5_context context, | ||||
|                       OM_uint32 time_req, | ||||
|                       gss_const_OID desired_mech, | ||||
|                       gss_cred_usage_t cred_usage, | ||||
|                       gsskrb5_cred handle) | ||||
| { | ||||
|     OM_uint32 ret; | ||||
|     krb5_error_code kret; | ||||
|  | ||||
|     ret = GSS_S_FAILURE; | ||||
|  | ||||
|     if (credential_type != GSS_C_NO_OID) { | ||||
| 	kret = EINVAL; | ||||
| 	goto end; | ||||
|     } | ||||
|  | ||||
|     kret = get_keytab(context, &handle->keytab); | ||||
|     if (kret) | ||||
| 	goto end; | ||||
| @@ -364,19 +487,20 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred_ext | ||||
|  | ||||
|     cred_usage &= GSS_C_OPTION_MASK; | ||||
|  | ||||
|     if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { | ||||
|     if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && | ||||
|         cred_usage != GSS_C_BOTH) { | ||||
| 	*minor_status = GSS_KRB5_S_G_BAD_USAGE; | ||||
| 	return GSS_S_FAILURE; | ||||
|     } | ||||
|  | ||||
|     GSSAPI_KRB5_INIT(&context); | ||||
|  | ||||
|     *output_cred_handle = NULL; | ||||
|     *output_cred_handle = GSS_C_NO_CREDENTIAL; | ||||
|  | ||||
|     handle = calloc(1, sizeof(*handle)); | ||||
|     if (handle == NULL) { | ||||
| 	*minor_status = ENOMEM; | ||||
|         return (GSS_S_FAILURE); | ||||
|         return GSS_S_FAILURE; | ||||
|     } | ||||
|  | ||||
|     HEIMDAL_MUTEX_init(&handle->cred_id_mutex); | ||||
| @@ -390,29 +514,75 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred_ext | ||||
| 	    return ret; | ||||
| 	} | ||||
|     } | ||||
|     if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { | ||||
| 	ret = acquire_initiator_cred(minor_status, context, | ||||
| 				     credential_type, credential_data, | ||||
|                                      time_req, desired_mech, cred_usage, | ||||
|                                      handle); | ||||
|     	if (ret != GSS_S_COMPLETE) { | ||||
| 	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); | ||||
| 	    krb5_free_principal(context, handle->principal); | ||||
| 	    free(handle); | ||||
| 	    return (ret); | ||||
| 	} | ||||
|     } | ||||
|     if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { | ||||
| 	ret = acquire_acceptor_cred(minor_status, context, | ||||
| 				    credential_type, credential_data, | ||||
|                                     time_req, desired_mech, cred_usage, | ||||
|                                     handle); | ||||
| 	if (ret != GSS_S_COMPLETE) { | ||||
| 	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); | ||||
| 	    krb5_free_principal(context, handle->principal); | ||||
| 	    free(handle); | ||||
| 	    return (ret); | ||||
| 	} | ||||
|  | ||||
|     if (credential_type != GSS_C_NO_OID && | ||||
|         gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { | ||||
|         /* Acquire a cred with a password */ | ||||
|         gss_const_buffer_t pwbuf = credential_data; | ||||
|         char *pw; | ||||
|  | ||||
|         if (pwbuf == NULL) { | ||||
|             HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); | ||||
|             free(handle); | ||||
|             *minor_status = KRB5_NOCREDS_SUPPLIED; /* see below */ | ||||
|             return GSS_S_CALL_INACCESSIBLE_READ; | ||||
|         } | ||||
|  | ||||
|         /* NUL-terminate the password, if it wasn't already */ | ||||
|         pw = strndup(pwbuf->value, pwbuf->length); | ||||
|         if (pw == NULL) { | ||||
|             HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); | ||||
|             free(handle); | ||||
|             *minor_status = krb5_enomem(context); | ||||
|             return GSS_S_CALL_INACCESSIBLE_READ; | ||||
|         } | ||||
|         ret = acquire_cred_with_password(minor_status, context, pw, time_req, | ||||
|                                          desired_mech, cred_usage, handle); | ||||
|         free(pw); | ||||
|         if (ret != GSS_S_COMPLETE) { | ||||
|             HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); | ||||
|             krb5_free_principal(context, handle->principal); | ||||
|             free(handle); | ||||
|             return (ret); | ||||
|         } | ||||
|     } else if (credential_type != GSS_C_NO_OID) { | ||||
|         /* | ||||
|          * _gss_acquire_cred_ext() called with something other than a password. | ||||
|          * | ||||
|          * Not supported. | ||||
|          * | ||||
|          * _gss_acquire_cred_ext() is not a supported public interface, so | ||||
|          * we don't have to try too hard as to minor status codes here. | ||||
|          */ | ||||
|         HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); | ||||
|         free(handle); | ||||
|         *minor_status = ENOTSUP; | ||||
|         return GSS_S_FAILURE; | ||||
|     } else { | ||||
|         /* | ||||
|          * Acquire a credential from the background credential store (ccache, | ||||
|          * keytab). | ||||
|          */ | ||||
|         if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { | ||||
|             ret = acquire_initiator_cred(minor_status, context, time_req, | ||||
|                                          desired_mech, cred_usage, handle); | ||||
|             if (ret != GSS_S_COMPLETE) { | ||||
|                 HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); | ||||
|                 krb5_free_principal(context, handle->principal); | ||||
|                 free(handle); | ||||
|                 return (ret); | ||||
|             } | ||||
|         } | ||||
|         if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { | ||||
|             ret = acquire_acceptor_cred(minor_status, context, time_req, | ||||
|                                         desired_mech, cred_usage, handle); | ||||
|             if (ret != GSS_S_COMPLETE) { | ||||
|                 HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); | ||||
|                 krb5_free_principal(context, handle->principal); | ||||
|                 free(handle); | ||||
|                 return (ret); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); | ||||
|     if (ret == GSS_S_COMPLETE) | ||||
|   | ||||
| @@ -104,6 +104,12 @@ _gss_acquire_mech_cred(OM_uint32 *minor_status, | ||||
|     return major_status; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * This function is not a public interface and is deprecated anyways, do | ||||
|  * not use.  Use gss_acquire_cred_with_password() instead for now. | ||||
|  * | ||||
|  * @deprecated | ||||
|  */ | ||||
| OM_uint32 | ||||
| _gss_acquire_cred_ext(OM_uint32 *minor_status, | ||||
|     gss_const_name_t desired_name, | ||||
| @@ -168,8 +174,11 @@ _gss_acquire_cred_ext(OM_uint32 *minor_status, | ||||
| 					      credential_type, credential_data, | ||||
| 					      time_req, desired_mech, cred_usage, | ||||
| 					      &mc); | ||||
| 	if (GSS_ERROR(major_status)) | ||||
| 	if (GSS_ERROR(major_status)) { | ||||
|             if (mechs->count == 1) | ||||
|                 _gss_mg_error(m, major_status, *minor_status); | ||||
| 	    continue; | ||||
|         } | ||||
|  | ||||
| 	HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); | ||||
|     } | ||||
| @@ -180,7 +189,8 @@ _gss_acquire_cred_ext(OM_uint32 *minor_status, | ||||
|      */ | ||||
|     if (!HEIM_SLIST_FIRST(&cred->gc_mc)) { | ||||
| 	free(cred); | ||||
| 	*minor_status = 0; | ||||
|         if (mechs->count > 1) | ||||
|             *minor_status = 0; | ||||
| 	return GSS_S_NO_CRED; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -93,7 +93,8 @@ gss_acquire_cred_with_password(OM_uint32 *minor_status, | ||||
|  | ||||
| 	if (!HEIM_SLIST_FIRST(&new_cred->gc_mc)) { | ||||
| 	    free(new_cred); | ||||
| 	    *minor_status = 0; | ||||
|             if (desired_mechs->count > 1) | ||||
|                 *minor_status = 0; | ||||
| 	    return GSS_S_NO_CRED; | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Nicolas Williams
					Nicolas Williams