From: Luke Howard Date: Thu, 1 Oct 2009 16:51:09 +0000 (+0000) Subject: Import/export authdata context with gss_{import,export}_sec_context; ensure serialize... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f8eaf5e7b21b8e22a1969f14da45bed6c5230d6;p=thirdparty%2Fkrb5.git Import/export authdata context with gss_{import,export}_sec_context; ensure serialized authdata context includes attribute authentication state git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/authdata@22817 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/appl/gss-sample/gss-server.c b/src/appl/gss-sample/gss-server.c index 488f14ccc5..131ca5c56a 100644 --- a/src/appl/gss-sample/gss-server.c +++ b/src/appl/gss-sample/gss-server.c @@ -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; diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 7c25cdf170..cf26d1df12 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1347,6 +1347,7 @@ void KRB5_CALLCONV krb5_free_ad_kdcissued #include 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, diff --git a/src/include/krb5/authdata_plugin.h b/src/include/krb5/authdata_plugin.h index 502b1c846e..294e4f9561 100644 --- a/src/include/krb5/authdata_plugin.h +++ b/src/include/krb5/authdata_plugin.h @@ -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 */ diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c index ea7ad0810f..b33619583e 100644 --- a/src/lib/gssapi/krb5/import_name.c +++ b/src/lib/gssapi/krb5/import_name.c @@ -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; diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c index 93784ad985..62e7d6ed73 100644 --- a/src/lib/gssapi/krb5/init_sec_context.c +++ b/src/lib/gssapi/krb5/init_sec_context.c @@ -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; } diff --git a/src/lib/gssapi/krb5/naming_exts.c b/src/lib/gssapi/krb5/naming_exts.c index 86170efceb..14b9b006d2 100644 --- a/src/lib/gssapi/krb5/naming_exts.c +++ b/src/lib/gssapi/krb5/naming_exts.c @@ -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); diff --git a/src/lib/gssapi/krb5/s4u_gss_glue.c b/src/lib/gssapi/krb5/s4u_gss_glue.c index 1f6e9eb7d9..cae45039cd 100644 --- a/src/lib/gssapi/krb5/s4u_gss_glue.c +++ b/src/lib/gssapi/krb5/s4u_gss_glue.c @@ -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; diff --git a/src/lib/gssapi/krb5/ser_sctx.c b/src/lib/gssapi/krb5/ser_sctx.c index cad1871218..9b55a65077 100644 --- a/src/lib/gssapi/krb5/ser_sctx.c +++ b/src/lib/gssapi/krb5/ser_sctx.c @@ -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); diff --git a/src/lib/krb5/error_tables/kv5m_err.et b/src/lib/krb5/error_tables/kv5m_err.et index d68398cf97..6259adab7c 100644 --- a/src/lib/krb5/error_tables/kv5m_err.et +++ b/src/lib/krb5/error_tables/kv5m_err.et @@ -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 diff --git a/src/lib/krb5/krb/authdata.c b/src/lib/krb5/krb/authdata.c index 8d42413127..fea141b6da 100644 --- a/src/lib/krb5/krb/authdata.c +++ b/src/lib/krb5/krb/authdata.c @@ -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); +} + diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h index cc0c9f2de0..03b541fb5b 100644 --- a/src/lib/krb5/krb/int-proto.h +++ b/src/lib/krb5/krb/int-proto.h @@ -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, diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index 06f1140fc3..df5ac28724 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -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; } diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c index 79a347ea96..5c2a37bfd8 100644 --- a/src/lib/krb5/krb/pac.c +++ b/src/lib/krb5/krb/pac.c @@ -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 }; - diff --git a/src/lib/krb5/krb/ser_actx.c b/src/lib/krb5/krb/ser_actx.c index 347b300f55..487455b9d6 100644 --- a/src/lib/krb5/krb/ser_actx.c +++ b/src/lib/krb5/krb/ser_actx.c @@ -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); } diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index cf4dc21ec7..2735c9f985 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -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 diff --git a/src/plugins/authdata/greet_client/greet.c b/src/plugins/authdata/greet_client/greet.c index 833965e047..74a0a74bf3 100644 --- a/src/plugins/authdata/greet_client/greet.c +++ b/src/plugins/authdata/greet_client/greet.c @@ -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 };