From: Marc Horowitz Date: Sun, 16 Aug 1998 05:55:55 +0000 (+0000) Subject: add add_cred.c to hold the now-implemented function X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c6d60b67fac00850aa7ef1108ce0453e556e6fb3;p=thirdparty%2Fkrb5.git add add_cred.c to hold the now-implemented function git-svn-id: svn://anonsvn.mit.edu/krb5/branches/marc-3des@10834 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in index a1b22716d8..00b575c34f 100644 --- a/src/lib/gssapi/krb5/Makefile.in +++ b/src/lib/gssapi/krb5/Makefile.in @@ -18,6 +18,7 @@ gssapi_err_krb5.c: gssapi_err_krb5.et SRCS = \ $(srcdir)/accept_sec_context.c \ $(srcdir)/acquire_cred.c \ + $(srcdir)/add_cred.c \ $(srcdir)/canon_name.c \ $(srcdir)/compare_name.c \ $(srcdir)/context_time.c \ @@ -64,6 +65,7 @@ SRCS = \ OBJS = \ accept_sec_context.$(OBJEXT) \ acquire_cred.$(OBJEXT) \ + add_cred.$(OBJEXT) \ canon_name.$(OBJEXT) \ compare_name.$(OBJEXT) \ context_time.$(OBJEXT) \ @@ -110,6 +112,7 @@ OBJS = \ STLIBOBJS = \ accept_sec_context.o \ acquire_cred.o \ + add_cred.o \ canon_name.o \ compare_name.o \ context_time.o \ diff --git a/src/lib/gssapi/krb5/add_cred.c b/src/lib/gssapi/krb5/add_cred.c new file mode 100644 index 0000000000..432eb19ae2 --- /dev/null +++ b/src/lib/gssapi/krb5/add_cred.c @@ -0,0 +1,283 @@ +#include "gssapiP_krb5.h" +#ifdef HAVE_STRING_H +#include +#else +#include +#endif + +/* + * $Id$ + */ + +/* V2 interface */ +OM_uint32 +krb5_gss_add_cred(minor_status, input_cred_handle, + desired_name, desired_mech, cred_usage, + initiator_time_req, acceptor_time_req, + output_cred_handle, actual_mechs, + initiator_time_rec, acceptor_time_rec) + OM_uint32 *minor_status; + gss_cred_id_t input_cred_handle; + gss_name_t desired_name; + gss_OID desired_mech; + gss_cred_usage_t cred_usage; + OM_uint32 initiator_time_req; + OM_uint32 acceptor_time_req; + gss_cred_id_t *output_cred_handle; + gss_OID_set *actual_mechs; + OM_uint32 *initiator_time_rec; + OM_uint32 *acceptor_time_rec; +{ + krb5_context context; + OM_uint32 major_status, lifetime; + krb5_gss_cred_id_t cred; + krb5_error_code code; + + /* this is pretty simple, since there's not really any difference + between the underlying mechanisms. The main hair is in copying + a mechanism if requested. */ + + /* check if the desired_mech is bogus */ + + if (!g_OID_equal(desired_mech, gss_mech_krb5_v2) && + !g_OID_equal(desired_mech, gss_mech_krb5) && + !g_OID_equal(desired_mech, gss_mech_krb5_old)) { + *minor_status = 0; + return(GSS_S_BAD_MECH); + } + + /* check if the desired_mech is bogus */ + + if ((cred_usage != GSS_C_INITIATE) && + (cred_usage != GSS_C_ACCEPT) && + (cred_usage != GSS_C_BOTH)) { + *minor_status = (OM_uint32) G_BAD_USAGE; + return(GSS_S_FAILURE); + } + + /* since the default credential includes all the mechanisms, + return an error for that case. */ + + /*SUPPRESS 29*/ + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return(GSS_S_DUPLICATE_ELEMENT); + } + + /* verify the credential */ + if (GSS_ERROR(major_status = + krb5_gss_validate_cred(minor_status, input_cred_handle))) + return(major_status); + + cred = (krb5_gss_cred_id_t) input_cred_handle; + + /* check if the cred_usage is equal or "less" than the passed-in cred + if copying */ + + if (!((cred->usage == cred_usage) || + ((cred->usage == GSS_C_BOTH) && + (output_cred_handle != NULL)))) { + *minor_status = (OM_uint32) G_BAD_USAGE; + return(GSS_S_FAILURE); + } + + /* check that desired_mech isn't already in the credential */ + + if ((g_OID_equal(desired_mech, gss_mech_krb5_old) && cred->prerfc_mech) || + (g_OID_equal(desired_mech, gss_mech_krb5) && cred->rfc_mech) || + (g_OID_equal(desired_mech, gss_mech_krb5_v2) && cred->rfcv2_mech)) { + *minor_status = 0; + return(GSS_S_DUPLICATE_ELEMENT); + } + + if (GSS_ERROR(kg_get_context(minor_status, &context))) + return(GSS_S_FAILURE); + + /* verify the desired_name */ + + /*SUPPRESS 29*/ + if ((desired_name != (gss_name_t) NULL) && + (! kg_validate_name(desired_name))) { + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME); + } + + /* make sure the desired_name is the same as the existing one */ + + if (desired_name && + !krb5_principal_compare(context, (krb5_principal) desired_name, + cred->princ)) { + *minor_status = 0; + return(GSS_S_BAD_NAME); + } + + /* copy the cred if necessary */ + + if (output_cred_handle) { + /* make a copy */ + krb5_gss_cred_id_t new_cred; + char *kttype, ktboth[1024]; + char *cctype, *ccname, ccboth[1024]; + + if ((new_cred = + (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec))) + == NULL) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + memset(new_cred, 0, sizeof(krb5_gss_cred_id_rec)); + + new_cred->usage = cred_usage; + new_cred->prerfc_mech = cred->prerfc_mech; + new_cred->rfc_mech = cred->rfc_mech; + new_cred->rfcv2_mech = cred->rfcv2_mech; + new_cred->tgt_expire = cred->tgt_expire; + + if (code = krb5_copy_principal(context, cred->princ, + &new_cred->princ)) { + free(new_cred); + + *minor_status = code; + return(GSS_S_FAILURE); + } + + if (cred->keytab) { + kttype = krb5_kt_get_type(context, cred->keytab); + if ((strlen(kttype)+2) > sizeof(ktboth)) { + krb5_free_principal(context, new_cred->princ); + free(new_cred); + + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + + strcpy(ktboth, kttype); + strcat(ktboth, ":"); + + if (code = krb5_kt_get_name(context, cred->keytab, + ktboth+strlen(ktboth), + sizeof(ktboth)-strlen(ktboth))) { + krb5_free_principal(context, new_cred->princ); + free(new_cred); + + *minor_status = code; + return(GSS_S_FAILURE); + } + + if (code = krb5_kt_resolve(context, ktboth, &new_cred->keytab)) { + krb5_free_principal(context, new_cred->princ); + free(new_cred); + + *minor_status = code; + return(GSS_S_FAILURE); + } + } else { + new_cred->keytab = NULL; + } + + if (cred->rcache) { + /* Open the replay cache for this principal. */ + if ((code = krb5_get_server_rcache(context, + krb5_princ_component(context, cred->princ, 0), + &new_cred->rcache))) { + if (new_cred->keytab) + krb5_kt_close(context, new_cred->keytab); + krb5_free_principal(context, new_cred->princ); + free(new_cred); + + *minor_status = code; + return(GSS_S_FAILURE); + } + } else { + new_cred->rcache = NULL; + } + + if (cred->ccache) { + cctype = krb5_cc_get_type(context, cred->ccache); + ccname = krb5_cc_get_name(context, cred->ccache); + + if ((strlen(cctype)+strlen(ccname)+2) > sizeof(ccboth)) { + if (new_cred->rcache) + krb5_rc_close(context, new_cred->rcache); + if (new_cred->keytab) + krb5_kt_close(context, new_cred->keytab); + krb5_free_principal(context, new_cred->princ); + free(new_cred); + + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + + strcpy(ccboth, cctype); + strcat(ccboth, ":"); + strcat(ccboth, ccname); + + if (code = krb5_cc_resolve(context, ccboth, &new_cred->ccache)) { + if (new_cred->rcache) + krb5_rc_close(context, new_cred->rcache); + if (new_cred->keytab) + krb5_kt_close(context, new_cred->keytab); + krb5_free_principal(context, new_cred->princ); + free(new_cred); + + *minor_status = code; + return(GSS_S_FAILURE); + } + } else { + new_cred->ccache = NULL; + } + + /* intern the credential handle */ + + if (! kg_save_cred_id((gss_cred_id_t) new_cred)) { + if (new_cred->ccache) + krb5_cc_close(context, new_cred->ccache); + if (new_cred->rcache) + krb5_rc_close(context, new_cred->rcache); + if (new_cred->keytab) + krb5_kt_close(context, new_cred->keytab); + krb5_free_principal(context, new_cred->princ); + free(new_cred); + + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + return(GSS_S_FAILURE); + } + + /* modify new_cred */ + + cred = new_cred; + } + + /* set the flag for the new mechanism */ + + if (g_OID_equal(desired_mech, gss_mech_krb5_old)) + cred->prerfc_mech = 1; + else if (g_OID_equal(desired_mech, gss_mech_krb5_old)) + cred->rfc_mech = 1; + else if (g_OID_equal(desired_mech, gss_mech_krb5_old)) + cred->rfcv2_mech = 1; + + /* set the outputs */ + + if (GSS_ERROR(major_status = krb5_gss_inquire_cred(minor_status, cred, + NULL, &lifetime, + NULL, actual_mechs))) { + OM_uint32 dummy; + + if (output_cred_handle) + (void) krb5_gss_release_cred(&dummy, (gss_cred_id_t *) &cred); + + return(major_status); + } + + if (initiator_time_rec) + *initiator_time_rec = lifetime; + if (acceptor_time_rec) + *acceptor_time_rec = lifetime; + + if (output_cred_handle) + *output_cred_handle = cred; + + *minor_status = 0; + return(GSS_S_COMPLETE); +}