]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
add add_cred.c to hold the now-implemented function
authorMarc Horowitz <marc@mit.edu>
Sun, 16 Aug 1998 05:55:55 +0000 (05:55 +0000)
committerMarc Horowitz <marc@mit.edu>
Sun, 16 Aug 1998 05:55:55 +0000 (05:55 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/marc-3des@10834 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/gssapi/krb5/Makefile.in
src/lib/gssapi/krb5/add_cred.c [new file with mode: 0644]

index a1b22716d8a604ae1e99deda6a653f43bf4731e8..00b575c34f0b2c010b253b6ff77142730344ad47 100644 (file)
@@ -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 (file)
index 0000000..432eb19
--- /dev/null
@@ -0,0 +1,283 @@
+#include "gssapiP_krb5.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#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);
+}