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);
|
return (kret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static OM_uint32 acquire_initiator_cred
|
/*
|
||||||
(OM_uint32 *minor_status,
|
* This function produces a cred with a MEMORY ccache containing a TGT
|
||||||
krb5_context context,
|
* acquired with a password.
|
||||||
gss_const_OID credential_type,
|
*/
|
||||||
const void *credential_data,
|
static OM_uint32
|
||||||
OM_uint32 time_req,
|
acquire_cred_with_password(OM_uint32 *minor_status,
|
||||||
gss_const_OID desired_mech,
|
krb5_context context,
|
||||||
gss_cred_usage_t cred_usage,
|
const char *password,
|
||||||
gsskrb5_cred handle
|
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_creds cred;
|
||||||
krb5_principal def_princ;
|
|
||||||
krb5_get_init_creds_opt *opt;
|
krb5_get_init_creds_opt *opt;
|
||||||
krb5_ccache ccache;
|
krb5_ccache ccache = NULL;
|
||||||
krb5_keytab keytab;
|
|
||||||
krb5_error_code kret;
|
krb5_error_code kret;
|
||||||
int try_get_init_creds = 0;
|
|
||||||
time_t now;
|
time_t now;
|
||||||
OM_uint32 left;
|
OM_uint32 left;
|
||||||
|
|
||||||
keytab = NULL;
|
if (cred_usage == GSS_C_ACCEPT) {
|
||||||
ccache = NULL;
|
/*
|
||||||
def_princ = NULL;
|
* TODO: Here we should eventually support user2user (when we get
|
||||||
ret = GSS_S_FAILURE;
|
* 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));
|
memset(&cred, 0, sizeof(cred));
|
||||||
|
|
||||||
/*
|
if (handle->principal == NULL) {
|
||||||
* If we have a preferred principal, lets try to find it in all
|
kret = krb5_get_default_principal(context, &handle->principal);
|
||||||
* caches, otherwise, fall back to default cache, ignore all
|
if (kret)
|
||||||
* errors while searching.
|
goto end;
|
||||||
*/
|
|
||||||
|
|
||||||
if (credential_type != GSS_C_NO_OID &&
|
|
||||||
!gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) {
|
|
||||||
kret = KRB5_NOCREDS_SUPPLIED; /* XXX */
|
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
|
kret = krb5_get_init_creds_opt_alloc(context, &opt);
|
||||||
if (handle->principal) {
|
if (kret)
|
||||||
kret = krb5_cc_cache_match(context,
|
goto end;
|
||||||
handle->principal,
|
|
||||||
&ccache);
|
/*
|
||||||
if (kret == 0) {
|
* Get the current time before the AS exchange so we don't
|
||||||
ret = GSS_S_COMPLETE;
|
* accidentally end up returning a value that puts advertised
|
||||||
goto found;
|
* 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
|
||||||
kret = krb5_cc_default(context, &ccache);
|
* to have a version of krb5_cc_get_lifetime() that returns absolute
|
||||||
if (kret == 0)
|
* time...
|
||||||
kret = krb5_cc_get_principal(context, ccache, &def_princ);
|
*/
|
||||||
if (kret != 0) {
|
krb5_timeofday(context, &now);
|
||||||
/* we'll try to use a keytab below */
|
|
||||||
krb5_cc_close(context, ccache);
|
kret = krb5_get_init_creds_password(context, &cred, handle->principal,
|
||||||
def_princ = NULL;
|
password, NULL, NULL, 0, NULL, opt);
|
||||||
kret = 0;
|
krb5_get_init_creds_opt_free(context, opt);
|
||||||
try_get_init_creds = 1;
|
if (kret)
|
||||||
} else if (handle->principal == NULL) {
|
goto end;
|
||||||
kret = krb5_copy_principal(context, def_princ, &handle->principal);
|
|
||||||
if (kret)
|
kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache);
|
||||||
goto end;
|
if (kret)
|
||||||
} else if (handle->principal != NULL &&
|
goto end;
|
||||||
krb5_principal_compare(context, handle->principal,
|
|
||||||
def_princ) == FALSE) {
|
kret = krb5_cc_initialize(context, ccache, cred.client);
|
||||||
krb5_cc_close(context, ccache);
|
if (kret)
|
||||||
ccache = NULL;
|
goto end;
|
||||||
try_get_init_creds = 1;
|
|
||||||
}
|
kret = krb5_cc_store_cred(context, ccache, &cred);
|
||||||
krb5_free_principal(context, def_princ);
|
if (kret)
|
||||||
def_princ = NULL;
|
goto end;
|
||||||
|
|
||||||
if (try_get_init_creds) {
|
handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
|
||||||
if (handle->principal == NULL) {
|
|
||||||
kret = krb5_get_default_principal(context, &handle->principal);
|
ret = __gsskrb5_ccache_lifetime(minor_status, context, ccache,
|
||||||
if (kret)
|
handle->principal, &left);
|
||||||
goto end;
|
if (ret != GSS_S_COMPLETE)
|
||||||
}
|
|
||||||
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);
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
|
||||||
handle->endtime = now + left;
|
handle->endtime = now + left;
|
||||||
handle->ccache = ccache;
|
handle->ccache = ccache;
|
||||||
|
ccache = NULL;
|
||||||
ret = GSS_S_COMPLETE;
|
ret = GSS_S_COMPLETE;
|
||||||
kret = 0;
|
kret = 0;
|
||||||
|
|
||||||
end:
|
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)
|
if (cred.client != NULL)
|
||||||
krb5_free_cred_contents(context, &cred);
|
krb5_free_cred_contents(context, &cred);
|
||||||
if (def_princ != NULL)
|
if (def_princ != NULL)
|
||||||
@@ -236,27 +367,19 @@ end:
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static OM_uint32 acquire_acceptor_cred
|
static OM_uint32
|
||||||
(OM_uint32 * minor_status,
|
acquire_acceptor_cred(OM_uint32 * minor_status,
|
||||||
krb5_context context,
|
krb5_context context,
|
||||||
gss_const_OID credential_type,
|
OM_uint32 time_req,
|
||||||
const void *credential_data,
|
gss_const_OID desired_mech,
|
||||||
OM_uint32 time_req,
|
gss_cred_usage_t cred_usage,
|
||||||
gss_const_OID desired_mech,
|
gsskrb5_cred handle)
|
||||||
gss_cred_usage_t cred_usage,
|
|
||||||
gsskrb5_cred handle
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
OM_uint32 ret;
|
OM_uint32 ret;
|
||||||
krb5_error_code kret;
|
krb5_error_code kret;
|
||||||
|
|
||||||
ret = GSS_S_FAILURE;
|
ret = GSS_S_FAILURE;
|
||||||
|
|
||||||
if (credential_type != GSS_C_NO_OID) {
|
|
||||||
kret = EINVAL;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
kret = get_keytab(context, &handle->keytab);
|
kret = get_keytab(context, &handle->keytab);
|
||||||
if (kret)
|
if (kret)
|
||||||
goto end;
|
goto end;
|
||||||
@@ -364,19 +487,20 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred_ext
|
|||||||
|
|
||||||
cred_usage &= GSS_C_OPTION_MASK;
|
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;
|
*minor_status = GSS_KRB5_S_G_BAD_USAGE;
|
||||||
return GSS_S_FAILURE;
|
return GSS_S_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSSAPI_KRB5_INIT(&context);
|
GSSAPI_KRB5_INIT(&context);
|
||||||
|
|
||||||
*output_cred_handle = NULL;
|
*output_cred_handle = GSS_C_NO_CREDENTIAL;
|
||||||
|
|
||||||
handle = calloc(1, sizeof(*handle));
|
handle = calloc(1, sizeof(*handle));
|
||||||
if (handle == NULL) {
|
if (handle == NULL) {
|
||||||
*minor_status = ENOMEM;
|
*minor_status = ENOMEM;
|
||||||
return (GSS_S_FAILURE);
|
return GSS_S_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
|
HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
|
||||||
@@ -390,29 +514,75 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred_ext
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) {
|
|
||||||
ret = acquire_initiator_cred(minor_status, context,
|
if (credential_type != GSS_C_NO_OID &&
|
||||||
credential_type, credential_data,
|
gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) {
|
||||||
time_req, desired_mech, cred_usage,
|
/* Acquire a cred with a password */
|
||||||
handle);
|
gss_const_buffer_t pwbuf = credential_data;
|
||||||
if (ret != GSS_S_COMPLETE) {
|
char *pw;
|
||||||
HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
|
|
||||||
krb5_free_principal(context, handle->principal);
|
if (pwbuf == NULL) {
|
||||||
free(handle);
|
HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
|
||||||
return (ret);
|
free(handle);
|
||||||
}
|
*minor_status = KRB5_NOCREDS_SUPPLIED; /* see below */
|
||||||
}
|
return GSS_S_CALL_INACCESSIBLE_READ;
|
||||||
if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) {
|
}
|
||||||
ret = acquire_acceptor_cred(minor_status, context,
|
|
||||||
credential_type, credential_data,
|
/* NUL-terminate the password, if it wasn't already */
|
||||||
time_req, desired_mech, cred_usage,
|
pw = strndup(pwbuf->value, pwbuf->length);
|
||||||
handle);
|
if (pw == NULL) {
|
||||||
if (ret != GSS_S_COMPLETE) {
|
HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
|
||||||
HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
|
free(handle);
|
||||||
krb5_free_principal(context, handle->principal);
|
*minor_status = krb5_enomem(context);
|
||||||
free(handle);
|
return GSS_S_CALL_INACCESSIBLE_READ;
|
||||||
return (ret);
|
}
|
||||||
}
|
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);
|
ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
|
||||||
if (ret == GSS_S_COMPLETE)
|
if (ret == GSS_S_COMPLETE)
|
||||||
|
@@ -104,6 +104,12 @@ _gss_acquire_mech_cred(OM_uint32 *minor_status,
|
|||||||
return major_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
|
OM_uint32
|
||||||
_gss_acquire_cred_ext(OM_uint32 *minor_status,
|
_gss_acquire_cred_ext(OM_uint32 *minor_status,
|
||||||
gss_const_name_t desired_name,
|
gss_const_name_t desired_name,
|
||||||
@@ -168,8 +174,11 @@ _gss_acquire_cred_ext(OM_uint32 *minor_status,
|
|||||||
credential_type, credential_data,
|
credential_type, credential_data,
|
||||||
time_req, desired_mech, cred_usage,
|
time_req, desired_mech, cred_usage,
|
||||||
&mc);
|
&mc);
|
||||||
if (GSS_ERROR(major_status))
|
if (GSS_ERROR(major_status)) {
|
||||||
|
if (mechs->count == 1)
|
||||||
|
_gss_mg_error(m, major_status, *minor_status);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link);
|
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)) {
|
if (!HEIM_SLIST_FIRST(&cred->gc_mc)) {
|
||||||
free(cred);
|
free(cred);
|
||||||
*minor_status = 0;
|
if (mechs->count > 1)
|
||||||
|
*minor_status = 0;
|
||||||
return GSS_S_NO_CRED;
|
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)) {
|
if (!HEIM_SLIST_FIRST(&new_cred->gc_mc)) {
|
||||||
free(new_cred);
|
free(new_cred);
|
||||||
*minor_status = 0;
|
if (desired_mechs->count > 1)
|
||||||
|
*minor_status = 0;
|
||||||
return GSS_S_NO_CRED;
|
return GSS_S_NO_CRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user