]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Import/export authdata context with gss_{import,export}_sec_context; ensure serialize...
authorLuke Howard <lukeh@padl.com>
Thu, 1 Oct 2009 16:51:09 +0000 (16:51 +0000)
committerLuke Howard <lukeh@padl.com>
Thu, 1 Oct 2009 16:51:09 +0000 (16:51 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/authdata@22817 dc483132-0cff-0310-8789-dd5450dbe970

16 files changed:
src/appl/gss-sample/gss-server.c
src/include/k5-int.h
src/include/krb5/authdata_plugin.h
src/lib/gssapi/krb5/import_name.c
src/lib/gssapi/krb5/init_sec_context.c
src/lib/gssapi/krb5/naming_exts.c
src/lib/gssapi/krb5/s4u_gss_glue.c
src/lib/gssapi/krb5/ser_sctx.c
src/lib/krb5/error_tables/kv5m_err.et
src/lib/krb5/krb/authdata.c
src/lib/krb5/krb/int-proto.h
src/lib/krb5/krb/mk_req_ext.c
src/lib/krb5/krb/pac.c
src/lib/krb5/krb/ser_actx.c
src/lib/krb5/libkrb5.exports
src/plugins/authdata/greet_client/greet.c

index 488f14ccc53caf832a5b30a67b9725b4c250abf2..131ca5c56a3b6760ac3a7c2189bfcdecd5977075 100644 (file)
@@ -723,6 +723,8 @@ main(argc, argv)
 
     service_name = *argv;
 
+    krb5_gss_register_acceptor_identity("/Users/lukeh/CVSRoot/mit/authdata/src/appl/gss-sample/rand.keytab");
+
     if (server_acquire_creds(service_name, &server_creds) < 0)
        return -1;
 
index 7c25cdf1703a275ce1c80c6d1443a665d76110fb..cf26d1df125abc6773a3865626f82e762617a461 100644 (file)
@@ -1347,6 +1347,7 @@ void KRB5_CALLCONV krb5_free_ad_kdcissued
 #include <krb5/authdata_plugin.h>
 
 struct _krb5_authdata_context {
+    krb5_magic magic;
     int n_modules;
     struct _krb5_authdata_context_module {
        krb5_authdatatype ad_type;
@@ -1375,6 +1376,12 @@ void KRB5_CALLCONV
 krb5_authdata_context_free
 (krb5_context kcontext, krb5_authdata_context context);
 
+krb5_error_code KRB5_CALLCONV krb5_authdata_export_authdata
+(krb5_context kcontext,
+ krb5_authdata_context context,
+ krb5_flags usage,
+ krb5_authdata ***pauthdata);
+
 krb5_error_code KRB5_CALLCONV
 krb5_authdata_get_attribute_types
 (krb5_context kcontext,
@@ -1408,13 +1415,13 @@ krb5_error_code KRB5_CALLCONV krb5_authdata_import_attributes
 (krb5_context kcontext,
  krb5_authdata_context context,
  krb5_flags usage,
krb5_authdata **pauthdata);
const krb5_data *attributes);
 
 krb5_error_code KRB5_CALLCONV krb5_authdata_export_attributes
 (krb5_context kcontext,
  krb5_authdata_context context,
  krb5_flags usage,
- krb5_authdata ***pauthdata);
+ krb5_data **pattributes);
 
 krb5_error_code KRB5_CALLCONV krb5_authdata_export_internal
 (krb5_context kcontext,
index 502b1c846ebce5b6c80a4de266388c5b98860fb1..294e4f9561d618ed63dd35e808e75ac431129bb2 100644 (file)
@@ -197,13 +197,21 @@ typedef void
                                     void *request_context);
 
 typedef krb5_error_code
-(*authdata_client_import_attributes_proc)(krb5_context kcontext,
-                                         struct _krb5_authdata_context *context,
-                                         void *plugin_context,
-                                         void *request_context,
-                                         krb5_authdata **authdata,
-                                         krb5_boolean kdc_issued_flag,
-                                         krb5_const_principal issuer);
+(*authdata_client_import_authdata_proc)(krb5_context kcontext,
+                                       struct _krb5_authdata_context *context,
+                                       void *plugin_context,
+                                       void *request_context,
+                                       krb5_authdata **authdata,
+                                       krb5_boolean kdc_issued_flag,
+                                       krb5_const_principal issuer);
+
+typedef krb5_error_code
+(*authdata_client_export_authdata_proc)(krb5_context kcontext,
+                                       struct _krb5_authdata_context *context,
+                                       void *plugin_context,
+                                       void *request_context,
+                                       krb5_flags usage,
+                                       krb5_authdata ***authdata);
 
 typedef krb5_error_code
 (*authdata_client_get_attribute_types_proc)(krb5_context kcontext,
@@ -240,14 +248,6 @@ typedef krb5_error_code
                                         void *request_context,
                                         const krb5_data *attribute);
 
-typedef krb5_error_code
-(*authdata_client_export_attributes_proc)(krb5_context kcontext,
-                                         struct _krb5_authdata_context *context,
-                                         void *plugin_context,
-                                         void *request_context,
-                                         krb5_flags usage,
-                                         krb5_authdata ***authdata);
-
 typedef krb5_error_code
 (*authdata_client_export_internal_proc)(krb5_context kcontext,
                                        struct _krb5_authdata_context *context,
@@ -280,6 +280,29 @@ typedef krb5_error_code
                               const krb5_keyblock *key,
                               const krb5_ap_req *req);
 
+typedef krb5_error_code
+(*authdata_client_size_proc)(krb5_context kcontext,
+                            struct _krb5_authdata_context *context,
+                            void *plugin_context,
+                            void *request_context,
+                            size_t *sizep);
+
+typedef krb5_error_code
+(*authdata_client_externalize_proc)(krb5_context kcontext,
+                                   struct _krb5_authdata_context *context,
+                                   void *plugin_context,
+                                   void *request_context,
+                                   krb5_octet **buffer,
+                                   size_t *lenremain);
+
+typedef krb5_error_code
+(*authdata_client_internalize_proc)(krb5_context kcontext,
+                                   struct _krb5_authdata_context *context,
+                                   void *plugin_context,
+                                   void *request_context,
+                                   krb5_octet **buffer,
+                                   size_t *lenremain);
+
 typedef struct krb5plugin_authdata_client_ftable_v0 {
     char *name;
     krb5_authdatatype *ad_type_list;
@@ -292,12 +315,15 @@ typedef struct krb5plugin_authdata_client_ftable_v0 {
     authdata_client_get_attribute_proc get_attribute;
     authdata_client_set_attribute_proc set_attribute;
     authdata_client_delete_attribute_proc delete_attribute;
-    authdata_client_import_attributes_proc import_attributes;
-    authdata_client_export_attributes_proc export_attributes;
+    authdata_client_export_authdata_proc export_authdata;
+    authdata_client_import_authdata_proc import_authdata;
     authdata_client_export_internal_proc export_internal;
     authdata_client_free_internal_proc free_internal;
     authdata_client_copy_context_proc copy_context;
     authdata_client_verify_proc verify;
+    authdata_client_size_proc size;
+    authdata_client_externalize_proc externalize;
+    authdata_client_internalize_proc internalize;
 } krb5plugin_authdata_client_ftable_v0;
 
 #endif /* KRB5_AUTHDATA_PLUGIN_H_INCLUDED */
index ea7ad0810f60d55960bfcb6f1df236a356db9a53..b33619583e7c5c4919e957b3689ac4588a3c1751 100644 (file)
@@ -45,6 +45,9 @@
  * GSS_S_FAILURE        if memory allocation fails
  */
 
+/*
+ * Import serialized authdata context
+ */
 static krb5_error_code
 import_name_composite(krb5_context context,
                       unsigned char *enc_data, size_t enc_length,
@@ -53,33 +56,23 @@ import_name_composite(krb5_context context,
     krb5_authdata_context ad_context;
     krb5_error_code code;
     krb5_data data;
-    krb5_authdata **authdata;
 
-    data.data = (char *)enc_data;
-    data.length = enc_length;
-
-    code = decode_krb5_authdata(&data, &authdata);
+    code = krb5_authdata_context_init(context, &ad_context);
     if (code != 0)
         return code;
 
-    code = krb5_authdata_context_init(context, &ad_context);
-    if (code != 0) {
-        krb5_free_authdata(context, authdata);
-        return code;
-    }
+    data.data = (char *)enc_data;
+    data.length = enc_length;
 
     code = krb5_authdata_import_attributes(context,
                                            ad_context,
                                            AD_USAGE_MASK,
-                                           authdata);
+                                           &data);
     if (code != 0) {
-        krb5_free_authdata(context, authdata);
         krb5_authdata_context_free(context, ad_context);
         return code;
     }
 
-    krb5_free_authdata(context, authdata);
-
     *pad_context = ad_context;
 
     return 0;
index 93784ad98584c2c577d7e157a1eca6919f609a23..62e7d6ed73d8c5f03a7e2aee0173323960b10fa1 100644 (file)
@@ -187,10 +187,10 @@ static krb5_error_code get_credentials(context, cred, server, now,
      * cred->name->lock.
      */
     if (cred->name->ad_context != NULL) {
-        code = krb5_authdata_export_attributes(context,
-                                               cred->name->ad_context,
-                                               AD_USAGE_TGS_REQ,
-                                               &in_creds.authdata);
+        code = krb5_authdata_export_authdata(context,
+                                             cred->name->ad_context,
+                                             AD_USAGE_TGS_REQ,
+                                             &in_creds.authdata);
         if (code != 0)
             goto cleanup;
     }
index 86170efcebf32cf6e9376ab8412ca992dd9aefe0..14b9b006d243c739266979ef796a502d7e82bb06 100644 (file)
@@ -619,8 +619,7 @@ krb5_gss_export_name_composite(OM_uint32 *minor_status,
     krb5_context context;
     krb5_error_code code;
     krb5_gss_name_t kname;
-    krb5_authdata **authdata = NULL;
-    krb5_data *enc_authdata = NULL;
+    krb5_data *attrs = NULL;
     char *princstr = NULL;
     unsigned char *cp;
     size_t princlen;
@@ -658,22 +657,16 @@ krb5_gss_export_name_composite(OM_uint32 *minor_status,
         code = krb5_authdata_export_attributes(context,
                                                kname->ad_context,
                                                AD_USAGE_MASK,
-                                               &authdata);
+                                               &attrs);
         if (code != 0)
             goto cleanup;
-
-        if (authdata != NULL) {
-            code = encode_krb5_authdata(authdata, &enc_authdata);
-            if (code != 0)
-                goto cleanup;
-        }
     }
 
     /* 04 02 OID Name AuthData */
 
     exp_composite_name->length = 10 + gss_mech_krb5->length + princlen;
-    if (enc_authdata != NULL)
-        exp_composite_name->length += 4 + enc_authdata->length;
+    if (attrs != NULL)
+        exp_composite_name->length += 4 + attrs->length;
     exp_composite_name->value = malloc(exp_composite_name->length);
     if (exp_composite_name->value == NULL) {
         code = ENOMEM;
@@ -684,7 +677,7 @@ krb5_gss_export_name_composite(OM_uint32 *minor_status,
 
     /* Note: we assume the OID will be less than 128 bytes... */
     *cp++ = 0x04;
-    if (enc_authdata != NULL)
+    if (attrs != NULL)
         *cp++ = 0x02;
     else
         *cp++ = 0x01;
@@ -701,17 +694,16 @@ krb5_gss_export_name_composite(OM_uint32 *minor_status,
     memcpy(cp, princstr, princlen);
     cp += princlen;
 
-    if (enc_authdata != NULL) {
-        store_32_be(enc_authdata->length, cp);
+    if (attrs != NULL) {
+        store_32_be(attrs->length, cp);
         cp += 4;
-        memcpy(cp, enc_authdata->data, enc_authdata->length);
-        cp += enc_authdata->length;
+        memcpy(cp, attrs->data, attrs->length);
+        cp += attrs->length;
     }
 
 cleanup:
     krb5_free_unparsed_name(context, princstr);
-    krb5_free_data(context, enc_authdata);
-    krb5_free_authdata(context, authdata);
+    krb5_free_data(context, attrs);
     k5_mutex_unlock(&kname->lock);
     krb5_free_context(context);
 
index 1f6e9eb7d90063bc3bf66a2f1d065fdbfa4f379d..cae45039cdc03dae527ff5b4ef95b3d3dad94b22 100644 (file)
@@ -137,10 +137,10 @@ kg_impersonate_name(OM_uint32 *minor_status,
     }
 
     if (user->ad_context != NULL) {
-        code = krb5_authdata_export_attributes(context,
-                                               user->ad_context,
-                                               AD_USAGE_TGS_REQ,
-                                               &in_creds.authdata);
+        code = krb5_authdata_export_authdata(context,
+                                             user->ad_context,
+                                             AD_USAGE_TGS_REQ,
+                                             &in_creds.authdata);
         if (code != 0) {
             k5_mutex_unlock(&user->lock);
             *minor_status = code;
index cad1871218cdd4a8cb2d7f9dc0192d326ec6b6bd..9b55a650773a42ba250c44be748d10f8279546d3 100644 (file)
@@ -292,13 +292,13 @@ kg_ctx_size(kcontext, arg, sizep)
         if (!kret && ctx->here)
             kret = krb5_size_opaque(kcontext,
                                     KV5M_PRINCIPAL,
-                                    (krb5_pointer) ctx->here,
+                                    (krb5_pointer) ctx->here->princ,
                                     &required);
 
         if (!kret && ctx->there)
             kret = krb5_size_opaque(kcontext,
                                     KV5M_PRINCIPAL,
-                                    (krb5_pointer) ctx->there,
+                                    (krb5_pointer) ctx->there->princ,
                                     &required);
 
         if (!kret && ctx->subkey)
@@ -352,7 +352,18 @@ kg_ctx_size(kcontext, arg, sizep)
                                         &required);
             }
         }
-        if (!kret)
+        if (!kret) {
+            krb5_gss_name_t initiator_name;
+
+            initiator_name = ctx->initiate ? ctx->here : ctx->there;
+
+            if (initiator_name) {
+                kret = krb5_size_opaque(kcontext,
+                                        KV5M_AUTHDATA_CONTEXT,
+                                        initiator_name->ad_context,
+                                        &required);
+            }
+        }
             *sizep += required;
     }
     return(kret);
@@ -437,13 +448,13 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
             if (!kret && ctx->here)
                 kret = krb5_externalize_opaque(kcontext,
                                                KV5M_PRINCIPAL,
-                                               (krb5_pointer) ctx->here,
+                                               (krb5_pointer) ctx->here->princ,
                                                &bp, &remain);
 
             if (!kret && ctx->there)
                 kret = krb5_externalize_opaque(kcontext,
                                                KV5M_PRINCIPAL,
-                                               (krb5_pointer) ctx->there,
+                                               (krb5_pointer) ctx->there->princ,
                                                &bp, &remain);
 
             if (!kret && ctx->subkey)
@@ -517,6 +528,20 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
                                                        &remain);
                 }
             }
+            /* authdata context */
+            if (!kret) {
+                krb5_gss_name_t initiator_name;
+
+                initiator_name = ctx->initiate ? ctx->here : ctx->there;
+
+                if (initiator_name) {
+                    kret = krb5_externalize_opaque(kcontext,
+                                                   KV5M_AUTHDATA_CONTEXT,
+                                                   initiator_name->ad_context,
+                                                   &bp,
+                                                   &remain);
+                }
+            }
             /* trailer */
             if (!kret)
                 kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
@@ -545,6 +570,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
     krb5_octet          *bp;
     size_t              remain;
     krb5int_access kaccess;
+    krb5_principal        princ;
 
     kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
     if (kret)
@@ -553,6 +579,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
     bp = *buffer;
     remain = *lenremain;
     kret = EINVAL;
+    princ = NULL;
     /* Read our magic number */
     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
         ibuf = 0;
@@ -618,19 +645,28 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
                     kret = 0;
             }
             /* Now get substructure data */
-            if ((kret = krb5_internalize_opaque(kcontext,
-                                                KV5M_PRINCIPAL,
-                                                (krb5_pointer *) &ctx->here,
-                                                &bp, &remain))) {
-                if (kret == EINVAL)
-                    kret = 0;
-            }
-            if (!kret &&
-                (kret = krb5_internalize_opaque(kcontext,
-                                                KV5M_PRINCIPAL,
-                                                (krb5_pointer *) &ctx->there,
-                                                &bp, &remain))) {
-                if (kret == EINVAL)
+            kret = krb5_internalize_opaque(kcontext,
+                                           KV5M_PRINCIPAL,
+                                            (krb5_pointer *) &princ,
+                                            &bp, &remain);
+            if (kret == 0) {
+                kret = kg_init_name(kcontext, princ, NULL,
+                                    KG_INIT_NAME_NO_COPY, &ctx->here);
+                if (kret)
+                    krb5_free_principal(kcontext, princ);
+            } else if (kret == EINVAL)
+                kret = 0;
+            if (!kret) {
+                kret = krb5_internalize_opaque(kcontext,
+                                               KV5M_PRINCIPAL,
+                                               (krb5_pointer *) &princ,
+                                               &bp, &remain);
+                if (kret == 0) {
+                    kret = kg_init_name(kcontext, princ, NULL,
+                                        KG_INIT_NAME_NO_COPY, &ctx->there);
+                    if (kret)
+                        krb5_free_principal(kcontext, princ);
+                } else if (kret == EINVAL)
                     kret = 0;
             }
             if (!kret &&
@@ -718,6 +754,21 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
                     }
                 }
             }
+            /* authdata context */
+            if (!kret) {
+                krb5_gss_name_t initiator_name;
+
+                initiator_name = ctx->initiate ? ctx->here : ctx->there;
+                if (initiator_name == NULL) {
+                    kret = EINVAL;
+                } else {
+                    kret = krb5_internalize_opaque(kcontext,
+                                                   KV5M_AUTHDATA_CONTEXT,
+                                                   (krb5_pointer *)&initiator_name->ad_context,
+                                                   &bp,
+                                                   &remain);
+                }
+            }
             /* Get trailer */
             if (!kret)
                 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
index d68398cf97336998fff95985bdbcfdbb603242dc..6259adab7ce2989ef9b864390d85044466cc15c0 100644 (file)
@@ -89,4 +89,5 @@ error_code KV5M_GSS_QUEUE,    "Bad magic number for GSSAPI QUEUE"
 error_code KV5M_FAST_ARMORED_REQ, "Bad magic number for fast armored request"
 error_code KV5M_FAST_REQ, "Bad magic number for FAST request"
 error_code KV5M_FAST_RESPONSE, "Bad magic number for FAST response"
+error_code KV5M_AUTHDATA_CONTEXT,  "Bad magic number for krb5_authdata_context"
 end
index 8d424131276585faf4fea60b72c9bdd4e05b5d30..fea141b6da61807de8004b8d248883fedc731e74 100644 (file)
@@ -27,6 +27,7 @@
 #include "k5-int.h"
 #include "authdata.h"
 #include "auth_con.h"
+#include "int-proto.h"
 
 /* Loosely based on preauth2.c */
 
@@ -140,6 +141,225 @@ k5_ad_init_modules(krb5_context kcontext,
     return code;
 }
 
+/*
+ * Determine size of to-be-externalized authdata context, for
+ * modules that match given flags mask. Note that this size
+ * does not include the magic identifier/trailer.
+ */
+static krb5_error_code
+k5_ad_size(krb5_context kcontext,
+           krb5_authdata_context context,
+           krb5_flags flags,
+           size_t *sizep)
+{
+    int i;
+    krb5_error_code code = 0;
+
+    *sizep += sizeof(krb5_int32); /* count */
+
+    for (i = 0; i < context->n_modules; i++) {
+        struct _krb5_authdata_context_module *module = &context->modules[i];
+        size_t size;
+
+        if ((module->flags & flags) == 0)
+            continue;
+
+        /* externalize request context for the first instance only */
+        if (module->client_req_init == NULL)
+            continue;
+
+        if (module->ftable->size == NULL)
+            continue;
+
+        assert(module->ftable->externalize != NULL);
+
+        size = sizeof(krb5_int32) /* namelen */ + strlen(module->name);
+
+        code = (*module->ftable->size)(kcontext,
+                                       context,
+                                       module->plugin_context,
+                                       *(module->request_context_pp),
+                                       &size);
+        if (code != 0)
+            break;
+
+        *sizep += size;
+    }
+
+    return code;
+}
+
+/*
+ * Externalize authdata context, for modules that match given flags
+ * mask. Note that the magic identifier/trailer is not included.
+ */
+static krb5_error_code
+k5_ad_externalize(krb5_context kcontext,
+                  krb5_authdata_context context,
+                  krb5_flags flags,
+                  krb5_octet **buffer,
+                  size_t *lenremain)
+{
+    int i;
+    krb5_error_code code;
+    krb5_int32 ad_count = 0;
+    krb5_octet *bp;
+    size_t remain;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    /* placeholder for count */
+    code = krb5_ser_pack_int32(0, &bp, &remain);
+    if (code != 0)
+        return code;
+
+    for (i = 0; i < context->n_modules; i++) {
+        struct _krb5_authdata_context_module *module = &context->modules[i];
+        size_t namelen;
+
+        if ((module->flags & flags) == 0)
+            continue;
+
+        /* externalize request context for the first instance only */
+        if (module->client_req_init == NULL)
+            continue;
+
+        if (module->ftable->externalize == NULL)
+            continue;
+
+        /*
+         * We use the module name rather than the authdata type, because
+         * there may be multiple modules for a particular authdata type.
+         */
+        namelen = strlen(module->name);
+
+        code = krb5_ser_pack_int32((krb5_int32)namelen, &bp, &remain);
+        if (code != 0)
+            break;
+
+        code = krb5_ser_pack_bytes((krb5_octet *)module->name,
+                                   namelen, &bp, &remain);
+        if (code != 0)
+            break;
+
+        code = (*module->ftable->externalize)(kcontext,
+                                              context,
+                                              module->plugin_context,
+                                              *(module->request_context_pp),
+                                              &bp,
+                                              &remain);
+        if (code != 0)
+            break;
+
+        ad_count++;
+    }
+
+    if (code == 0) {
+        /* store actual count */
+        krb5_ser_pack_int32(ad_count, buffer, lenremain);
+
+        *buffer = bp;
+        *lenremain = remain;
+    }
+
+    return code;
+}
+
+/*
+ * Find authdata module for authdata type that matches flag mask
+ */
+static struct _krb5_authdata_context_module *
+k5_ad_find_module(krb5_context kcontext,
+                  krb5_authdata_context context,
+                  krb5_flags flags,
+                  const krb5_data *name)
+{
+    int i;
+    struct _krb5_authdata_context_module *ret = NULL;
+
+    for (i = 0; i < context->n_modules; i++) {
+        struct _krb5_authdata_context_module *module = &context->modules[i];
+
+        if ((module->flags & flags) &&
+            module->client_req_init != NULL &&
+            strlen(module->name) == name->length &&
+            memcmp(module->name, name->data, name->length) == 0) {
+            ret = module;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/*
+ * In-place internalize authdata context, for modules that match given
+ * flags mask. The magic identifier/trailer is not expected by this.
+ */
+static krb5_error_code
+k5_ad_internalize(krb5_context kcontext,
+                  krb5_authdata_context context,
+                  krb5_flags flags,
+                  krb5_octet **buffer,
+                  size_t *lenremain)
+{
+    krb5_error_code code = 0;
+    krb5_int32 i, count;
+    krb5_octet *bp;
+    size_t remain;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    code = krb5_ser_unpack_int32(&count, &bp, &remain);
+    if (code != 0)
+        return code;
+
+    for (i = 0; i < count; i++) {
+        struct _krb5_authdata_context_module *module;
+        krb5_int32 namelen;
+        krb5_data name;
+
+        code = krb5_ser_unpack_int32(&namelen, &bp, &remain);
+        if (code != 0)
+            break;
+
+        if (remain < (size_t)namelen) {
+            code = ENOMEM;
+            break;
+        }
+
+        name.length = namelen;
+        name.data = (char *)bp;
+
+        module = k5_ad_find_module(kcontext, context, flags, &name);
+        if (module == NULL || module->ftable->internalize == NULL) {
+            code = EINVAL;
+            break;
+        }
+
+        bp += namelen;
+        remain -= namelen;
+
+        code = (*module->ftable->internalize)(kcontext,
+                                              context,
+                                              module->plugin_context,
+                                              *(module->request_context_pp),
+                                              &bp,
+                                              &remain);
+        if (code != 0)
+            break;
+    }
+
+    if (code == 0) {
+        *buffer = bp;
+        *lenremain = remain;
+    }
+
+    return code;
+}
+
 krb5_error_code KRB5_CALLCONV
 krb5_authdata_context_init(krb5_context kcontext,
                            krb5_authdata_context *pcontext)
@@ -184,6 +404,7 @@ krb5_authdata_context_init(krb5_context kcontext,
         krb5int_close_plugin_dirs(&context->plugins);
         return ENOMEM;
     }
+    context->magic = KV5M_AUTHDATA_CONTEXT;
     context->modules = calloc(n_modules, sizeof(context->modules[0]));
     if (context->modules == NULL) {
         if (tables != NULL)
@@ -260,46 +481,15 @@ krb5_error_code KRB5_CALLCONV
 krb5_authdata_import_attributes(krb5_context kcontext,
                                 krb5_authdata_context context,
                                 krb5_flags usage,
-                                krb5_authdata **authdata_to_import)
+                                const krb5_data *attrs)
 {
-    int i;
-    krb5_error_code code = 0;
+    krb5_octet *bp;
+    size_t remain;
 
-    for (i = 0; i < context->n_modules; i++) {
-        struct _krb5_authdata_context_module *module = &context->modules[i];
-        krb5_authdata **authdata;
-
-        if ((module->flags & usage) == 0)
-            continue;
+    bp = (krb5_octet *)attrs->data;
+    remain = attrs->length;
 
-        if (module->ftable->import_attributes == NULL)
-            continue;
-
-        code = krb5int_find_authdata(kcontext,
-                                     authdata_to_import,
-                                     NULL,
-                                     module->ad_type,
-                                     &authdata);
-        if (code != 0 || authdata == NULL)
-            continue;
-
-        assert(authdata[0] != NULL);
-
-        code = (*module->ftable->import_attributes)(kcontext,
-                                                    context,
-                                                    module->plugin_context,
-                                                    *(module->request_context_pp),
-                                                    authdata,
-                                                    FALSE,
-                                                    NULL);
-        if (code != 0 && (module->flags & AD_INFORMATIONAL))
-            code = 0;
-        krb5_free_authdata(kcontext, authdata);
-        if (code != 0)
-            break;
-    }
-
-    return code;
+    return k5_ad_internalize(kcontext, context, usage, &bp, &remain);
 }
 
 static krb5_error_code
@@ -343,6 +533,65 @@ k5_get_kdc_issued_authdata(krb5_context kcontext,
     return code;
 }
 
+krb5_error_code KRB5_CALLCONV
+krb5_authdata_export_authdata(krb5_context kcontext,
+                              krb5_authdata_context context,
+                              krb5_flags flags,
+                              krb5_authdata ***pauthdata)
+{
+    int i;
+    krb5_error_code code = 0;
+    krb5_authdata **authdata = NULL;
+    unsigned int len = 0;
+
+    *pauthdata = NULL;
+
+    for (i = 0; i < context->n_modules; i++) {
+        struct _krb5_authdata_context_module *module = &context->modules[i];
+        krb5_authdata **authdata2 = NULL;
+        int j;
+
+        if ((module->flags & flags) == 0)
+            continue;
+
+        if (module->ftable->export_authdata == NULL)
+            continue;
+
+        code = (*module->ftable->export_authdata)(kcontext,
+                                                  context,
+                                                  module->plugin_context,
+                                                  *(module->request_context_pp),
+                                                  flags,
+                                                  &authdata2);
+        if (code == ENOENT)
+            code = 0;
+        else if (code != 0)
+            break;
+
+        if (authdata2 == NULL)
+            continue;
+
+        for (j = 0; authdata2[j] != NULL; j++)
+            ;
+
+        authdata = realloc(authdata, (len + j + 1) * sizeof(krb5_authdata *));
+        if (authdata == NULL)
+            return ENOMEM;
+
+        memcpy(&authdata[len], authdata2, j * sizeof(krb5_authdata *));
+        free(authdata2);
+
+        len += j;
+    }
+
+    if (authdata != NULL)
+        authdata[len] = NULL;
+
+    *pauthdata = authdata;
+
+    return code;
+}
+
 krb5_error_code
 krb5int_authdata_verify(krb5_context kcontext,
                         krb5_authdata_context context,
@@ -371,7 +620,7 @@ krb5int_authdata_verify(krb5_context kcontext,
         if ((module->flags & usage) == 0)
             continue;
 
-        if (module->ftable->import_attributes == NULL)
+        if (module->ftable->import_authdata == NULL)
             continue;
 
         if (kdc_issued_authdata != NULL) {
@@ -401,13 +650,13 @@ krb5int_authdata_verify(krb5_context kcontext,
 
         assert(authdata[0] != NULL);
 
-        code = (*module->ftable->import_attributes)(kcontext,
-                                                    context,
-                                                    module->plugin_context,
-                                                    *(module->request_context_pp),
-                                                    authdata,
-                                                    kdc_issued_flag,
-                                                    kdc_issuer);
+        code = (*module->ftable->import_authdata)(kcontext,
+                                                  context,
+                                                  module->plugin_context,
+                                                  *(module->request_context_pp),
+                                                  authdata,
+                                                  kdc_issued_flag,
+                                                  kdc_issuer);
         if (code == 0 && module->ftable->verify != NULL) {
             code = (*module->ftable->verify)(kcontext,
                                              context,
@@ -630,59 +879,44 @@ krb5_error_code KRB5_CALLCONV
 krb5_authdata_export_attributes(krb5_context kcontext,
                                 krb5_authdata_context context,
                                 krb5_flags flags,
-                                krb5_authdata ***pauthdata)
+                                krb5_data **attrsp)
 {
-    int i;
-    krb5_error_code code = 0;
-    krb5_authdata **authdata = NULL;
-    unsigned int len = 0;
-
-    *pauthdata = NULL;
-
-    for (i = 0; i < context->n_modules; i++) {
-        struct _krb5_authdata_context_module *module = &context->modules[i];
-        krb5_authdata **authdata2 = NULL;
-        int j;
-
-        if ((module->flags & flags) == 0)
-            continue;
-
-        if (module->ftable->export_attributes == NULL)
-            continue;
-
-        code = (*module->ftable->export_attributes)(kcontext,
-                                                    context,
-                                                    module->plugin_context,
-                                                    *(module->request_context_pp),
-                                                    flags,
-                                                    &authdata2);
-        if (code == ENOENT)
-            code = 0;
-        else if (code != 0)
-            break;
+    krb5_error_code code;
+    size_t required = 0;
+    krb5_octet *bp;
+    size_t remain;
+    krb5_data *attrs;
 
-        if (authdata2 == NULL)
-            continue;
+    code = k5_ad_size(kcontext, context, AD_USAGE_MASK, &required);
+    if (code != 0)
+        return code;
 
-        for (j = 0; authdata2[j] != NULL; j++)
-            ;
+    attrs = malloc(sizeof(*attrs));
+    if (attrs == NULL)
+        return ENOMEM;
 
-        authdata = realloc(authdata, (len + j + 1) * sizeof(krb5_authdata *));
-        if (authdata == NULL)
-            return ENOMEM;
+    attrs->magic = KV5M_DATA;
+    attrs->length = 0;
+    attrs->data = malloc(required);
+    if (attrs->data == NULL) {
+        free(attrs);
+        return ENOMEM;
+    }
 
-        memcpy(&authdata[len], authdata2, j * sizeof(krb5_authdata *));
-        free(authdata2);
+    bp = (krb5_octet *)attrs->data;
+    remain = required;
 
-        len += j;
+    code = k5_ad_externalize(kcontext, context, AD_USAGE_MASK, &bp, &remain);
+    if (code != 0) {
+        krb5_free_data(kcontext, attrs);
+        return code;
     }
 
-    if (authdata != NULL)
-        authdata[len] = NULL;
+    attrs->length = (bp - (krb5_octet *)attrs->data);
 
-    *pauthdata = authdata;
+    *attrsp = attrs;
 
-    return code;
+    return 0;
 }
 
 krb5_error_code KRB5_CALLCONV
@@ -772,21 +1006,73 @@ k5_copy_ad_module_data(krb5_context kcontext,
     if (dst_module == NULL)
         return ENOENT;
 
-    if (dst_module->client_req_init == NULL) {
-        /* only copy the context for the head module */
+    /* copy request context for the first instance only */
+    if (dst_module->client_req_init == NULL)
         return 0;
-    }
 
     assert(strcmp(dst_module->name, src_module->name) == 0);
-    assert(src_module->request_context_pp == &src_module->request_context);
-    assert(dst_module->request_context_pp == &dst_module->request_context);
 
-    code = (*src_module->ftable->copy_context)(kcontext,
-                                               context,
-                                               src_module->plugin_context,
-                                               src_module->request_context,
-                                               dst_module->plugin_context,
-                                               dst_module->request_context);
+    /* If copy_context is unimplemented, externalize/internalize */
+    if (src_module->ftable->copy_context == NULL) {
+        size_t size = 0, remain;
+        krb5_octet *contents, *bp;
+
+        assert(src_module->ftable->size != NULL);
+        assert(src_module->ftable->externalize != NULL);
+        assert(dst_module->ftable->internalize != NULL);
+
+        code = (*src_module->ftable->size)(kcontext,
+                                           context,
+                                           src_module->plugin_context,
+                                           src_module->request_context,
+                                           &size);
+        if (code != 0)
+            return code;
+
+        contents = malloc(size);
+        if (contents == NULL)
+            return ENOMEM;
+
+        bp = contents;
+        remain = size;
+
+        code = (*src_module->ftable->externalize)(kcontext,
+                                                  context,
+                                                  src_module->plugin_context,
+                                                  *(src_module->request_context_pp),
+                                                  &bp,
+                                                  &remain);
+        if (code != 0) {
+            free(contents);
+            return code;
+        }
+
+        remain = (bp - contents);
+        bp = contents;
+
+        code = (*dst_module->ftable->internalize)(kcontext,
+                                                  context,
+                                                  dst_module->plugin_context,
+                                                  *(dst_module->request_context_pp),
+                                                  &bp,
+                                                  &remain);
+        if (code != 0) {
+            free(contents);
+            return code;
+        }
+
+        free(contents);
+    } else {
+        assert(src_module->request_context_pp == &src_module->request_context);
+        assert(dst_module->request_context_pp == &dst_module->request_context);
+
+        code = (*src_module->ftable->copy_context)(kcontext,
+                                                   context,
+                                                   src_module->plugin_context,
+                                                   src_module->request_context,
+                                                   dst_module->plugin_context,
+                                                   dst_module->request_context);
+    }
 
     return code;
 }
@@ -823,3 +1109,133 @@ krb5_authdata_context_copy(krb5_context kcontext,
     return 0;
 }
 
+/*
+ * Calculate size of to-be-externalized authdata context.
+ */
+static krb5_error_code
+krb5_authdata_context_size(krb5_context kcontext,
+                           krb5_pointer ptr,
+                           size_t *sizep)
+{
+    krb5_error_code code;
+    krb5_authdata_context context = (krb5_authdata_context)ptr;
+
+    code = k5_ad_size(kcontext, context, AD_USAGE_MASK, sizep);
+    if (code != 0)
+        return code;
+
+    *sizep += 2 * sizeof(krb5_int32); /* identifier/trailer */
+
+    return 0;
+}
+
+/*
+ * Externalize an authdata context.
+ */
+static krb5_error_code
+krb5_authdata_context_externalize(krb5_context kcontext,
+                                  krb5_pointer ptr,
+                                  krb5_octet **buffer,
+                                  size_t *lenremain)
+{
+    krb5_error_code code;
+    krb5_authdata_context context = (krb5_authdata_context)ptr;
+    krb5_octet *bp;
+    size_t remain;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    /* Our identifier */
+    if (remain < sizeof(krb5_int32))
+        return ENOMEM;
+
+    krb5_ser_pack_int32(KV5M_AUTHDATA_CONTEXT, &bp, &remain);
+
+    /* The actual context data */
+    code = k5_ad_externalize(kcontext, context, AD_USAGE_MASK,
+                             &bp, &remain);
+    if (code != 0)
+        return code;
+
+    /* Our trailer */
+    if (remain < sizeof(krb5_int32))
+        return ENOMEM;
+
+    krb5_ser_pack_int32(KV5M_AUTHDATA_CONTEXT, &bp, &remain);
+
+    *buffer = bp;
+    *lenremain = remain;
+
+    return 0;
+}
+
+/*
+ * Internalize an authdata context.
+ */
+static krb5_error_code
+krb5_authdata_context_internalize(krb5_context kcontext,
+                                  krb5_pointer *ptr,
+                                  krb5_octet **buffer,
+                                  size_t *lenremain)
+{
+    krb5_error_code code;
+    krb5_authdata_context context;
+    krb5_int32 ibuf;
+    krb5_octet *bp;
+    size_t remain;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+    if (code != 0)
+        return code;
+
+    if (ibuf != KV5M_AUTHDATA_CONTEXT)
+        return EINVAL;
+
+    code = krb5_authdata_context_init(kcontext, &context);
+    if (code != 0)
+        return code;
+
+    code = k5_ad_internalize(kcontext, context, AD_USAGE_MASK,
+                             &bp, &remain);
+    if (code != 0) {
+        krb5_authdata_context_free(kcontext, context);
+        return code;
+    }
+
+    code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+    if (code != 0)
+        return code;
+
+    if (ibuf != KV5M_AUTHDATA_CONTEXT) {
+        krb5_authdata_context_free(kcontext, context);
+        return EINVAL;
+    }
+
+    *buffer = bp;
+    *lenremain = remain;
+    *ptr = context;
+
+    return 0;
+}
+
+static const krb5_ser_entry krb5_authdata_context_ser_entry = {
+    KV5M_AUTHDATA_CONTEXT,
+    krb5_authdata_context_size,
+    krb5_authdata_context_externalize,
+    krb5_authdata_context_internalize
+};
+
+/*
+ * Register the authdata context serializer.
+ */
+krb5_error_code
+krb5_ser_authdata_context_init(krb5_context kcontext)
+{
+    return krb5_register_serializer(kcontext,
+                                    &krb5_authdata_context_ser_entry);
+}
+
index cc0c9f2de03f04ac292be5d5d5a34c62a4378f4f..03b541fb5bb74372d97211fe1a2570408434cac0 100644 (file)
@@ -47,6 +47,7 @@ krb5_error_code krb5_ser_authenticator_init (krb5_context);
 krb5_error_code krb5_ser_checksum_init (krb5_context);
 krb5_error_code krb5_ser_keyblock_init (krb5_context);
 krb5_error_code krb5_ser_principal_init (krb5_context);
+krb5_error_code krb5_ser_authdata_context_init (krb5_context);
 
 krb5_error_code
 krb5_preauth_supply_preauth_data(krb5_context context,
index 06f1140fc312130a8245a0d4133f8c2c054ce63e..df5ac287246c533189f384a4641dda3aab345b1b 100644 (file)
@@ -321,10 +321,10 @@ krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent,
     authent->authorization_data = NULL;
 
     if (ad_context != NULL) {
-       retval = krb5_authdata_export_attributes(context,
-                                                ad_context,
-                                                AD_USAGE_AP_REQ,
-                                                &ext_authdata);
+       retval = krb5_authdata_export_authdata(context,
+                                              ad_context,
+                                              AD_USAGE_AP_REQ,
+                                              &ext_authdata);
        if (retval)
            return retval;
     }
index 79a347ea96facd81d3f6dcaec98811b4497c83ee..5c2a37bfd8876ad33985f4f61da4e9db3be083ad 100644 (file)
@@ -995,19 +995,19 @@ mspac_request_init(krb5_context kcontext,
 }
 
 static krb5_error_code
-mspac_import_attributes(krb5_context kcontext,
-                       krb5_authdata_context context,
-                        void *plugin_context,
-                       void *request_context,
-                       krb5_authdata **authdata,
-                       krb5_boolean kdc_issued,
-                       krb5_const_principal kdc_issuer)
+mspac_import_authdata(krb5_context kcontext,
+                     krb5_authdata_context context,
+                     void *plugin_context,
+                     void *request_context,
+                     krb5_authdata **authdata,
+                     krb5_boolean kdc_issued,
+                     krb5_const_principal kdc_issuer)
 {
     krb5_error_code code;
     struct mspac_context *pacctx = (struct mspac_context *)request_context;
 
     if (kdc_issued)
-       return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+       return EINVAL;
 
     if (pacctx->pac != NULL) {
        krb5_pac_free(kcontext, pacctx->pac);
@@ -1024,6 +1024,51 @@ mspac_import_attributes(krb5_context kcontext,
     return code;
 }
 
+static krb5_error_code
+mspac_export_authdata(krb5_context kcontext,
+                     krb5_authdata_context context,
+                     void *plugin_context,
+                     void *request_context,
+                     krb5_flags usage,
+                     krb5_authdata ***out_authdata)
+{
+    struct mspac_context *pacctx = (struct mspac_context *)request_context;
+    krb5_error_code code;
+    krb5_authdata **authdata;
+    krb5_data data;
+
+    if (pacctx->pac == NULL)
+       return 0;
+
+    authdata = calloc(2, sizeof(krb5_authdata *));
+    if (authdata == NULL)
+       return ENOMEM;
+
+    authdata[0] = calloc(1, sizeof(krb5_authdata));
+    if (authdata[0] == NULL) {
+       free(authdata);
+       return ENOMEM;
+    }
+    authdata[1] = NULL;
+
+    code = krb5int_copy_data_contents(kcontext, &pacctx->pac->data, &data);
+    if (code != 0) {
+       krb5_free_authdata(kcontext, authdata);
+       return code;
+    }
+
+    authdata[0]->magic = KV5M_AUTHDATA;
+    authdata[0]->ad_type = KRB5_AUTHDATA_WIN2K_PAC;
+    authdata[0]->length = data.length;
+    authdata[0]->contents = (krb5_octet *)data.data;
+
+    authdata[1] = NULL;
+
+    *out_authdata = authdata;
+
+    return 0;
+}
+
 static krb5_error_code
 mspac_verify(krb5_context kcontext,
             krb5_authdata_context context,
@@ -1052,8 +1097,8 @@ mspac_verify(krb5_context kcontext,
      * Thoughts?
      */
     if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
-        assert(pacctx->pac->verified == FALSE);
-        code = 0;
+       assert(pacctx->pac->verified == FALSE);
+       code = 0;
     }
 #endif
 
@@ -1289,51 +1334,6 @@ mspac_set_attribute(krb5_context kcontext,
     return code;
 }
 
-static krb5_error_code
-mspac_export_attributes(krb5_context kcontext,
-                       krb5_authdata_context context,
-                       void *plugin_context,
-                       void *request_context,
-                       krb5_flags usage,
-                       krb5_authdata ***out_authdata)
-{
-    struct mspac_context *pacctx = (struct mspac_context *)request_context;
-    krb5_error_code code;
-    krb5_authdata **authdata;
-    krb5_data data;
-
-    if (pacctx->pac == NULL)
-       return 0;
-
-    authdata = calloc(2, sizeof(krb5_authdata *));
-    if (authdata == NULL)
-       return ENOMEM;
-
-    authdata[0] = calloc(1, sizeof(krb5_authdata));
-    if (authdata[0] == NULL) {
-       free(authdata);
-       return ENOMEM;
-    }
-    authdata[1] = NULL;
-
-    code = krb5int_copy_data_contents(kcontext, &pacctx->pac->data, &data);
-    if (code != 0) {
-       krb5_free_authdata(kcontext, authdata);
-       return code;
-    }
-
-    authdata[0]->magic = KV5M_AUTHDATA;
-    authdata[0]->ad_type = KRB5_AUTHDATA_WIN2K_PAC;
-    authdata[0]->length = data.length;
-    authdata[0]->contents = (krb5_octet *)data.data;
-
-    authdata[1] = NULL;
-
-    *out_authdata = authdata;
-
-    return 0;
-}
-
 static krb5_error_code
 mspac_export_internal(krb5_context kcontext,
                      krb5_authdata_context context,
@@ -1398,6 +1398,123 @@ mspac_free_internal(krb5_context kcontext,
     return;
 }
 
+static krb5_error_code
+mspac_size(krb5_context kcontext,
+          krb5_authdata_context context,
+          void *plugin_context,
+          void *request_context,
+          size_t *sizep)
+{
+    struct mspac_context *pacctx = (struct mspac_context *)request_context;
+
+    *sizep += sizeof(krb5_int32);
+
+    if (pacctx->pac != NULL)
+       *sizep += pacctx->pac->data.length;
+
+    *sizep += sizeof(krb5_int32);
+
+    return 0;
+}
+
+static krb5_error_code
+mspac_externalize(krb5_context kcontext,
+                 krb5_authdata_context context,
+                 void *plugin_context,
+                 void *request_context,
+                 krb5_octet **buffer,
+                 size_t *lenremain)
+{
+    krb5_error_code code = 0;
+    struct mspac_context *pacctx = (struct mspac_context *)request_context;
+    size_t required = 0;
+    krb5_octet *bp;
+    size_t remain;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    if (pacctx->pac != NULL) {
+       mspac_size(kcontext, context, plugin_context,
+                  request_context, &required);
+
+       if (required <= remain) {
+           krb5_ser_pack_int32((krb5_int32)pacctx->pac->data.length,
+                               &bp, &remain);
+           krb5_ser_pack_bytes((krb5_octet *)pacctx->pac->data.data,
+                               (size_t)pacctx->pac->data.length,
+                               &bp, &remain);
+           krb5_ser_pack_int32((krb5_int32)pacctx->pac->verified,
+                               &bp, &remain);
+       } else {
+           code = ENOMEM;
+       }
+    } else {
+       krb5_ser_pack_int32(0, &bp, &remain); /* length */
+       krb5_ser_pack_int32(0, &bp, &remain); /* verified */
+    }
+
+    *buffer = bp;
+    *lenremain = remain;
+
+    return code;
+}
+
+static krb5_error_code
+mspac_internalize(krb5_context kcontext,
+                 krb5_authdata_context context,
+                 void *plugin_context,
+                 void *request_context,
+                 krb5_octet **buffer,
+                 size_t *lenremain)
+{
+    struct mspac_context *pacctx = (struct mspac_context *)request_context;
+    krb5_error_code code;
+    krb5_int32 ibuf;
+    krb5_octet *bp;
+    size_t remain;
+    krb5_pac pac = NULL;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    /* length */
+    code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+    if (code != 0)
+       return code;
+
+    if (ibuf != 0) {
+       code = krb5_pac_parse(kcontext, bp, ibuf, &pac);
+       if (code != 0)
+           return code;
+
+       bp += ibuf;
+       remain -= ibuf;
+    }
+
+    /* verified */
+    code = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+    if (code != 0) {
+       krb5_pac_free(kcontext, pac);
+       return code;
+    }
+
+    if (pac != NULL) {
+       pac->verified = (ibuf != 0);
+    }
+
+    if (pacctx->pac != NULL) {
+       krb5_pac_free(kcontext, pacctx->pac);
+    }
+
+    pacctx->pac = pac;
+
+    *buffer = bp;
+    *lenremain = remain;
+
+    return 0;
+}
+
 static krb5_authdatatype mspac_ad_types[] = { KRB5_AUTHDATA_WIN2K_PAC, 0 };
 
 krb5plugin_authdata_client_ftable_v0 krb5int_mspac_authdata_client_ftable = {
@@ -1412,12 +1529,14 @@ krb5plugin_authdata_client_ftable_v0 krb5int_mspac_authdata_client_ftable = {
     mspac_get_attribute,
     mspac_set_attribute,
     NULL, /* delete_attribute_proc */
-    mspac_import_attributes,
-    mspac_export_attributes,
+    mspac_export_authdata,
+    mspac_import_authdata,
     mspac_export_internal,
     mspac_free_internal,
     mspac_copy_context,
-    mspac_verify
+    mspac_verify,
+    mspac_size,
+    mspac_externalize,
+    mspac_internalize
 };
 
-
index 347b300f55f5aa7044facd001e81a89b3d46eb7e..487455b9d6dd242a3d7bacaaeed4b4f121ebbdee 100644 (file)
@@ -560,5 +560,7 @@ krb5_ser_auth_context_init(krb5_context kcontext)
        kret = krb5_ser_keyblock_init(kcontext);
     if (!kret)
        kret = krb5_ser_principal_init(kcontext);
+    if (!kret)
+       kret = krb5_ser_authdata_context_init(kcontext);
     return(kret);
 }
index cf4dc21ec7e12350e71d4c8cb430166fbe25092f..2735c9f9856fa3b99618f045f62aedab2d06bf71 100644 (file)
@@ -148,6 +148,7 @@ krb5_authdata_get_attribute_types
 krb5_authdata_get_attribute
 krb5_authdata_set_attribute
 krb5_authdata_export_attributes
+krb5_authdata_export_authdata
 krb5_authdata_export_internal
 krb5_authdata_free_internal
 krb5_authdata_import_attributes
index 833965e047976933a08328b470cf3084fd462aa5..74a0a74bf3867c359e206a68467c460083eb7ff4 100644 (file)
@@ -84,13 +84,38 @@ greet_request_init(krb5_context kcontext,
 }
 
 static krb5_error_code
-greet_import_attributes(krb5_context kcontext,
-                        krb5_authdata_context context,
-                        void *plugin_context,
-                        void *request_context,
-                        krb5_authdata **authdata,
-                        krb5_boolean kdc_issued_flag,
-                        krb5_const_principal issuer)
+greet_export_authdata(krb5_context kcontext,
+                      krb5_authdata_context context,
+                      void *plugin_context,
+                      void *request_context,
+                      krb5_flags usage,
+                      krb5_authdata ***out_authdata)
+{
+    struct greet_context *greet = (struct greet_context *)request_context;
+    krb5_authdata *data[2];
+    krb5_authdata datum;
+    krb5_error_code code;
+
+    datum.ad_type = -42;
+    datum.length = greet->greeting.length;
+    datum.contents = (krb5_octet *)greet->greeting.data;
+
+    data[0] = &datum;
+    data[1] = NULL;
+
+    code = krb5_copy_authdata(kcontext, data, out_authdata);
+
+    return code;
+}
+
+static krb5_error_code
+greet_import_authdata(krb5_context kcontext,
+                      krb5_authdata_context context,
+                      void *plugin_context,
+                      void *request_context,
+                      krb5_authdata **authdata,
+                      krb5_boolean kdc_issued_flag,
+                      krb5_const_principal issuer)
 {
     krb5_error_code code;
     struct greet_context *greet = (struct greet_context *)request_context;
@@ -231,46 +256,101 @@ greet_delete_attribute(krb5_context kcontext,
 }
 
 static krb5_error_code
-greet_export_attributes(krb5_context kcontext,
-                        krb5_authdata_context context,
-                        void *plugin_context,
-                        void *request_context,
-                        krb5_flags usage,
-                        krb5_authdata ***out_authdata)
+greet_size(krb5_context kcontext,
+           krb5_authdata_context context,
+           void *plugin_context,
+           void *request_context,
+           size_t *sizep)
 {
     struct greet_context *greet = (struct greet_context *)request_context;
-    krb5_authdata *data[2];
-    krb5_authdata datum;
-    krb5_error_code code;
 
-    datum.ad_type = -42;
-    datum.length = greet->greeting.length;
-    datum.contents = (krb5_octet *)greet->greeting.data;
+    *sizep += sizeof(krb5_int32) +
+              greet->greeting.length +
+              sizeof(krb5_int32);
 
-    data[0] = &datum;
-    data[1] = NULL;
+    return 0;
+}
 
-    code = krb5_copy_authdata(kcontext, data, out_authdata);
+static krb5_error_code
+greet_externalize(krb5_context kcontext,
+                  krb5_authdata_context context,
+                  void *plugin_context,
+                  void *request_context,
+                  krb5_octet **buffer,
+                  size_t *lenremain)
+{
+    size_t required = 0;
+    struct greet_context *greet = (struct greet_context *)request_context;
 
-    return code;
+    greet_size(kcontext, context, plugin_context,
+               request_context, &required);
+
+    if (*lenremain < required)
+        return ENOMEM;
+
+    /* Greeting Length | Greeting Contents | Verified */
+    krb5_ser_pack_int32(greet->greeting.length, buffer, lenremain);
+    krb5_ser_pack_bytes((krb5_octet *)greet->greeting.data,
+                        (size_t)greet->greeting.length,
+                        buffer, lenremain);
+    krb5_ser_pack_int32((krb5_int32)greet->verified, buffer, lenremain);
+
+    return 0;
 }
 
 static krb5_error_code
-greet_copy_context(krb5_context kcontext,
-                   krb5_authdata_context context,
-                   void *plugin_context,
-                   void *request_context,
-                   void *dst_plugin_context,
-                   void *dst_request_context)
+greet_internalize(krb5_context kcontext,
+                  krb5_authdata_context context,
+                  void *plugin_context,
+                  void *request_context,
+                  krb5_octet **buffer,
+                  size_t *lenremain)
 {
-    struct greet_context *src = (struct greet_context *)request_context;
-    struct greet_context *dst = (struct greet_context *)dst_request_context;
+    struct greet_context *greet = (struct greet_context *)request_context;
+    krb5_error_code code;
+    krb5_int32 length;
+    krb5_octet *contents = NULL;
+    krb5_int32 verified;
+    krb5_octet *bp;
+    size_t remain;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    /* Greeting Length */
+    code = krb5_ser_unpack_int32(&length, &bp, &remain);
+    if (code != 0)
+        return code;
 
-    dst->verified = src->verified;
+    /* Greeting Contents */
+    if (length != 0) {
+        contents = malloc(length);
+        if (contents == NULL)
+            return ENOMEM;
+
+        code = krb5_ser_unpack_bytes(contents, (size_t)length, &bp, &remain);
+        if (code != 0) {
+            free(contents);
+            return code;
+        }
+    }
 
-    return krb5int_copy_data_contents_add0(kcontext,
-                                           &src->greeting,
-                                           &dst->greeting);
+    /* Verified */
+    code = krb5_ser_unpack_int32(&verified, &bp, &remain);
+    if (code != 0) {
+        free(contents);
+        return code;
+    }
+
+    krb5_free_data_contents(kcontext, &greet->greeting);
+    greet->greeting.length = length;
+    greet->greeting.data = (char *)contents;
+    greet->verified = (verified != 0);
+
+    *buffer = bp;
+    *lenremain = remain;
+
+    return 0;
 }
 
 static krb5_authdatatype greet_ad_types[] = { -42, 0 };
@@ -287,10 +367,13 @@ krb5plugin_authdata_client_ftable_v0 authdata_client_0 = {
     greet_get_attribute,
     greet_set_attribute,
     greet_delete_attribute,
-    greet_import_attributes,
-    greet_export_attributes,
+    greet_export_authdata,
+    greet_import_authdata,
+    NULL,
     NULL,
     NULL,
-    greet_copy_context,
     NULL,
+    greet_size,
+    greet_externalize,
+    greet_internalize
 };