diff options
Diffstat (limited to 'lib/gssapi/krb5/acquire_cred.c')
| -rw-r--r-- | lib/gssapi/krb5/acquire_cred.c | 308 | 
1 files changed, 180 insertions, 128 deletions
| diff --git a/lib/gssapi/krb5/acquire_cred.c b/lib/gssapi/krb5/acquire_cred.c index 6e13a4287b62..0f1f5f81cffc 100644 --- a/lib/gssapi/krb5/acquire_cred.c +++ b/lib/gssapi/krb5/acquire_cred.c @@ -1,39 +1,37 @@  /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden).  - * All rights reserved.  + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved.   * - * Redistribution and use in source and binary forms, with or without  - * modification, are permitted provided that the following conditions  - * are met:  + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met:   * - * 1. Redistributions of source code must retain the above copyright  - *    notice, this list of conditions and the following disclaimer.  + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer.   * - * 2. Redistributions in binary form must reproduce the above copyright  - *    notice, this list of conditions and the following disclaimer in the  - *    documentation and/or other materials provided with the distribution.  + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution.   * - * 3. Neither the name of the Institute nor the names of its contributors  - *    may be used to endorse or promote products derived from this software  - *    without specific prior written permission.  + * 3. Neither the name of the Institute nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission.   * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  - * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  - * SUCH DAMAGE.  + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE.   */ -#include "krb5/gsskrb5_locl.h" - -RCSID("$Id: acquire_cred.c 22124 2007-12-04 00:03:52Z lha $"); +#include "gsskrb5_locl.h"  OM_uint32  __gsskrb5_ccache_lifetime(OM_uint32 *minor_status, @@ -42,13 +40,13 @@ __gsskrb5_ccache_lifetime(OM_uint32 *minor_status,  			  krb5_principal principal,  			  OM_uint32 *lifetime)  { -    krb5_creds in_cred, *out_cred; +    krb5_creds in_cred, out_cred;      krb5_const_realm realm;      krb5_error_code kret;      memset(&in_cred, 0, sizeof(in_cred));      in_cred.client = principal; -	 +      realm = krb5_principal_get_realm(context,  principal);      if (realm == NULL) {  	_gsskrb5_clear_status (); @@ -56,23 +54,23 @@ __gsskrb5_ccache_lifetime(OM_uint32 *minor_status,  	return GSS_S_FAILURE;      } -    kret = krb5_make_principal(context, &in_cred.server,  +    kret = krb5_make_principal(context, &in_cred.server,  			       realm, KRB5_TGS_NAME, realm, NULL);      if (kret) {  	*minor_status = kret;  	return GSS_S_FAILURE;      } -    kret = krb5_get_credentials(context, 0,  -				id, &in_cred, &out_cred); +    kret = krb5_cc_retrieve_cred(context, id, 0, &in_cred, &out_cred);      krb5_free_principal(context, in_cred.server);      if (kret) { -	*minor_status = kret; -	return GSS_S_FAILURE; +	*minor_status = 0; +	*lifetime = 0; +	return GSS_S_COMPLETE;      } -    *lifetime = out_cred->times.endtime; -    krb5_free_creds(context, out_cred); +    *lifetime = out_cred.times.endtime; +    krb5_free_cred_contents(context, &out_cred);      return GSS_S_COMPLETE;  } @@ -83,17 +81,18 @@ __gsskrb5_ccache_lifetime(OM_uint32 *minor_status,  static krb5_error_code  get_keytab(krb5_context context, krb5_keytab *keytab)  { -    char kt_name[256];      krb5_error_code kret;      HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);      if (_gsskrb5_keytab != NULL) { -	kret = krb5_kt_get_name(context, -				_gsskrb5_keytab, -				kt_name, sizeof(kt_name)); -	if (kret == 0) -	    kret = krb5_kt_resolve(context, kt_name, keytab); +	char *name = NULL; + +	kret = krb5_kt_get_full_name(context, _gsskrb5_keytab, &name); +	if (kret == 0) { +	    kret = krb5_kt_resolve(context, name, keytab); +	    krb5_xfree(name); +	}      } else  	kret = krb5_kt_default(context, keytab); @@ -105,13 +104,13 @@ get_keytab(krb5_context context, krb5_keytab *keytab)  static OM_uint32 acquire_initiator_cred  		  (OM_uint32 * minor_status,  		   krb5_context context, +		   gss_const_OID credential_type, +		   const void *credential_data,  		   const gss_name_t desired_name,  		   OM_uint32 time_req, -		   const gss_OID_set desired_mechs, +		   gss_const_OID desired_mech,  		   gss_cred_usage_t cred_usage, -		   gsskrb5_cred handle, -		   gss_OID_set * actual_mechs, -		   OM_uint32 * time_rec +		   gsskrb5_cred handle  		  )  {      OM_uint32 ret; @@ -128,70 +127,100 @@ static OM_uint32 acquire_initiator_cred      ret = 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 -     * errors. */ -    if (handle->principal) +    /* +     * 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) {  	kret = krb5_cc_cache_match (context,  				    handle->principal, -				    NULL,  				    &ccache); -     +	if (kret == 0) { +	    ret = GSS_S_COMPLETE; +	    goto found; +	} +    } +      if (ccache == NULL) {  	kret = krb5_cc_default(context, &ccache);  	if (kret)  	    goto end;      } -    kret = krb5_cc_get_principal(context, ccache, -	&def_princ); +    kret = krb5_cc_get_principal(context, ccache, &def_princ);      if (kret != 0) {  	/* we'll try to use a keytab below */ -	krb5_cc_destroy(context, ccache); -	ccache = NULL; +	krb5_cc_close(context, ccache); +	def_princ = NULL;  	kret = 0;      } else if (handle->principal == NULL)  { -	kret = krb5_copy_principal(context, def_princ, -	    &handle->principal); +	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) { -	/* Before failing, lets check the keytab */ +	       krb5_principal_compare(context, handle->principal, +				      def_princ) == FALSE) {  	krb5_free_principal(context, def_princ);  	def_princ = NULL; +	krb5_cc_close(context, ccache); +	ccache = NULL;      }      if (def_princ == NULL) {  	/* We have no existing credentials cache,  	 * so attempt to get a TGT using a keytab.  	 */  	if (handle->principal == NULL) { -	    kret = krb5_get_default_principal(context, -		&handle->principal); +	    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; -	kret = krb5_get_init_creds_keytab(context, &cred, -	    handle->principal, keytab, 0, NULL, opt); +	if (credential_type != GSS_C_NO_OID && +	    gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { +	    gss_buffer_t password = (gss_buffer_t)credential_data; + +	    /* XXX are we requiring password to be NUL terminated? */ + +	    kret = krb5_get_init_creds_password(context, &cred, +						handle->principal, +						password->value, +						NULL, NULL, 0, NULL, opt); +	} 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_gen_new(context, &krb5_mcc_ops, -		&ccache); +	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) +	if (kret) { +	    krb5_cc_destroy(context, ccache);  	    goto end; +	}  	kret = krb5_cc_store_cred(context, ccache, &cred); -	if (kret) +	if (kret) { +	    krb5_cc_destroy(context, ccache);  	    goto end; +	}  	handle->lifetime = cred.times.endtime;  	handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;      } else { @@ -201,11 +230,13 @@ static OM_uint32 acquire_initiator_cred  					ccache,  					handle->principal,  					&handle->lifetime); -	if (ret != GSS_S_COMPLETE) +	if (ret != GSS_S_COMPLETE) { +	    krb5_cc_close(context, ccache);  	    goto end; +	}  	kret = 0;      } - + found:      handle->ccache = ccache;      ret = GSS_S_COMPLETE; @@ -216,49 +247,49 @@ end:  	krb5_free_principal(context, def_princ);      if (keytab != NULL)  	krb5_kt_close(context, keytab); -    if (ret != GSS_S_COMPLETE) { -	if (ccache != NULL) -	    krb5_cc_close(context, ccache); -	if (kret != 0) { -	    *minor_status = kret; -	} -    } +    if (ret != GSS_S_COMPLETE && kret != 0) +	*minor_status = kret;      return (ret);  }  static OM_uint32 acquire_acceptor_cred  		  (OM_uint32 * minor_status,  		   krb5_context context, +		   gss_const_OID credential_type, +		   const void *credential_data,  		   const gss_name_t desired_name,  		   OM_uint32 time_req, -		   const gss_OID_set desired_mechs, +		   gss_const_OID desired_mech,  		   gss_cred_usage_t cred_usage, -		   gsskrb5_cred handle, -		   gss_OID_set * actual_mechs, -		   OM_uint32 * time_rec +		   gsskrb5_cred handle  		  )  {      OM_uint32 ret;      krb5_error_code kret; -    kret = 0;      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; -     +      /* check that the requested principal exists in the keytab */      if (handle->principal) {  	krb5_keytab_entry entry; -	kret = krb5_kt_get_entry(context, handle->keytab,  +	kret = krb5_kt_get_entry(context, handle->keytab,  				 handle->principal, 0, 0, &entry);  	if (kret)  	    goto end;  	krb5_kt_free_entry(context, &entry);  	ret = GSS_S_COMPLETE;      } else { -	/*  +	/*  	 * Check if there is at least one entry in the keytab before  	 * declaring it as an useful keytab.  	 */ @@ -273,7 +304,7 @@ static OM_uint32 acquire_acceptor_cred  	    ret = GSS_S_COMPLETE; /* ok found one entry */  	}  	krb5_kt_end_seq_get (context, handle->keytab, &c); -    }  +    }  end:      if (ret != GSS_S_COMPLETE) {  	if (handle->keytab != NULL) @@ -285,7 +316,7 @@ end:      return (ret);  } -OM_uint32 _gsskrb5_acquire_cred +OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred  (OM_uint32 * minor_status,   const gss_name_t desired_name,   OM_uint32 time_req, @@ -296,28 +327,13 @@ OM_uint32 _gsskrb5_acquire_cred   OM_uint32 * time_rec      )  { -    krb5_context context; -    gsskrb5_cred handle;      OM_uint32 ret; -    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; -    if (time_rec) -	*time_rec = 0; -    if (actual_mechs) -	*actual_mechs = GSS_C_NO_OID_SET; -      if (desired_mechs) {  	int present = 0;  	ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM, -				      desired_mechs, &present);  +				      desired_mechs, &present);  	if (ret)  	    return ret;  	if (!present) { @@ -326,6 +342,54 @@ OM_uint32 _gsskrb5_acquire_cred  	}      } +    ret = _gsskrb5_acquire_cred_ext(minor_status, +				    desired_name, +				    GSS_C_NO_OID, +				    NULL, +				    time_req, +				    GSS_KRB5_MECHANISM, +				    cred_usage, +				    output_cred_handle); +    if (ret) +	return ret; + + +    ret = _gsskrb5_inquire_cred(minor_status, *output_cred_handle, +				NULL, time_rec, NULL, actual_mechs); +    if (ret) { +	OM_uint32 tmp; +	_gsskrb5_release_cred(&tmp, output_cred_handle); +    } + +    return ret; +} + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred_ext +(OM_uint32 * minor_status, + const gss_name_t desired_name, + gss_const_OID credential_type, + const void *credential_data, + OM_uint32 time_req, + gss_const_OID desired_mech, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle +    ) +{ +    krb5_context context; +    gsskrb5_cred handle; +    OM_uint32 ret; + +    cred_usage &= GSS_C_OPTION_MASK; + +    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; +      handle = calloc(1, sizeof(*handle));      if (handle == NULL) {  	*minor_status = ENOMEM; @@ -335,20 +399,19 @@ OM_uint32 _gsskrb5_acquire_cred      HEIMDAL_MUTEX_init(&handle->cred_id_mutex);      if (desired_name != GSS_C_NO_NAME) { -	krb5_principal name = (krb5_principal)desired_name; -	ret = krb5_copy_principal(context, name, &handle->principal); +	ret = _gsskrb5_canon_name(minor_status, context, 1, NULL, +				  desired_name, &handle->principal);  	if (ret) {  	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); -	    *minor_status = ret;  	    free(handle); -	    return GSS_S_FAILURE; +	    return ret;  	}      }      if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) {  	ret = acquire_initiator_cred(minor_status, context, +				     credential_type, credential_data,  				     desired_name, time_req, -				     desired_mechs, cred_usage, handle, -				     actual_mechs, time_rec); +				     desired_mech, cred_usage, handle);      	if (ret != GSS_S_COMPLETE) {  	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);  	    krb5_free_principal(context, handle->principal); @@ -358,8 +421,9 @@ OM_uint32 _gsskrb5_acquire_cred      }      if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) {  	ret = acquire_acceptor_cred(minor_status, context, +				    credential_type, credential_data,  				    desired_name, time_req, -				    desired_mechs, cred_usage, handle, actual_mechs, time_rec); +				    desired_mech, cred_usage, handle);  	if (ret != GSS_S_COMPLETE) {  	    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);  	    krb5_free_principal(context, handle->principal); @@ -371,9 +435,6 @@ OM_uint32 _gsskrb5_acquire_cred      if (ret == GSS_S_COMPLETE)      	ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,  				     &handle->mechanisms); -    if (ret == GSS_S_COMPLETE) -    	ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)handle,  -				    NULL, time_rec, NULL, actual_mechs);      if (ret != GSS_S_COMPLETE) {  	if (handle->mechanisms != NULL)  	    gss_release_oid_set(NULL, &handle->mechanisms); @@ -381,18 +442,9 @@ OM_uint32 _gsskrb5_acquire_cred  	krb5_free_principal(context, handle->principal);  	free(handle);  	return (ret); -    }  -    *minor_status = 0; -    if (time_rec) { -	ret = _gsskrb5_lifetime_left(minor_status, -				     context, -				     handle->lifetime, -				     time_rec); - -	if (ret) -	    return ret;      }      handle->usage = cred_usage; +    *minor_status = 0;      *output_cred_handle = (gss_cred_id_t)handle;      return (GSS_S_COMPLETE);  } | 
