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;
#include <krb5/authdata_plugin.h>
struct _krb5_authdata_context {
+ krb5_magic magic;
int n_modules;
struct _krb5_authdata_context_module {
krb5_authdatatype ad_type;
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,
(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,
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,
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,
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;
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 */
* 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,
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;
* 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;
}
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;
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;
/* 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;
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);
}
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;
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)
&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);
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)
&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);
krb5_octet *bp;
size_t remain;
krb5int_access kaccess;
+ krb5_principal princ;
kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
if (kret)
bp = *buffer;
remain = *lenremain;
kret = EINVAL;
+ princ = NULL;
/* Read our magic number */
if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
ibuf = 0;
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 &&
}
}
}
+ /* 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);
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
#include "k5-int.h"
#include "authdata.h"
#include "auth_con.h"
+#include "int-proto.h"
/* Loosely based on preauth2.c */
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)
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)
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
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,
if ((module->flags & usage) == 0)
continue;
- if (module->ftable->import_attributes == NULL)
+ if (module->ftable->import_authdata == NULL)
continue;
if (kdc_issued_authdata != NULL) {
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,
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
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;
}
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);
+}
+
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,
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;
}
}
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);
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,
* Thoughts?
*/
if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
- assert(pacctx->pac->verified == FALSE);
- code = 0;
+ assert(pacctx->pac->verified == FALSE);
+ code = 0;
}
#endif
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,
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 = {
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
};
-
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);
}
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
}
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;
}
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 };
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
};