/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* plugins/authdata/greet_client/greet.c - Sample authorization data plugin */ /* * Copyright 2009 by the Massachusetts Institute of Technology. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #include "k5-int.h" #include #include struct greet_context { krb5_data greeting; krb5_boolean verified; }; static krb5_data greet_attr = { KV5M_DATA, sizeof("urn:greet:greeting") - 1, "urn:greet:greeting" }; static krb5_error_code greet_init(krb5_context kcontext, void **plugin_context) { *plugin_context = 0; return 0; } static void greet_flags(krb5_context kcontext, void *plugin_context, krb5_authdatatype ad_type, krb5_flags *flags) { *flags = AD_USAGE_AP_REQ | AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL; } static void greet_fini(krb5_context kcontext, void *plugin_context) { return; } static krb5_error_code greet_request_init(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void **request_context) { struct greet_context *greet; greet = malloc(sizeof(*greet)); if (greet == NULL) return ENOMEM; greet->greeting.data = NULL; greet->greeting.length = 0; greet->verified = FALSE; *request_context = greet; return 0; } static krb5_error_code 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; krb5_data data; krb5_free_data_contents(kcontext, &greet->greeting); greet->verified = FALSE; assert(authdata[0] != NULL); data.length = authdata[0]->length; data.data = (char *)authdata[0]->contents; code = krb5int_copy_data_contents_add0(kcontext, &data, &greet->greeting); if (code == 0) greet->verified = kdc_issued_flag; return code; } static void greet_request_fini(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context) { struct greet_context *greet = (struct greet_context *)request_context; if (greet != NULL) { krb5_free_data_contents(kcontext, &greet->greeting); free(greet); } } static krb5_error_code greet_get_attribute_types(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context, krb5_data **out_attrs) { krb5_error_code code; struct greet_context *greet = (struct greet_context *)request_context; if (greet->greeting.length == 0) return ENOENT; *out_attrs = calloc(2, sizeof(krb5_data)); if (*out_attrs == NULL) return ENOMEM; code = krb5int_copy_data_contents_add0(kcontext, &greet_attr, &(*out_attrs)[0]); if (code != 0) { free(*out_attrs); *out_attrs = NULL; return code; } return 0; } static krb5_error_code greet_get_attribute(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context, const krb5_data *attribute, krb5_boolean *authenticated, krb5_boolean *complete, krb5_data *value, krb5_data *display_value, int *more) { struct greet_context *greet = (struct greet_context *)request_context; krb5_error_code code; if (!data_eq(*attribute, greet_attr) || greet->greeting.length == 0) return ENOENT; *authenticated = greet->verified; *complete = TRUE; *more = 0; code = krb5int_copy_data_contents_add0(kcontext, &greet->greeting, value); if (code == 0) { code = krb5int_copy_data_contents_add0(kcontext, &greet->greeting, display_value); if (code != 0) krb5_free_data_contents(kcontext, value); } return code; } static krb5_error_code greet_set_attribute(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context, krb5_boolean complete, const krb5_data *attribute, const krb5_data *value) { struct greet_context *greet = (struct greet_context *)request_context; krb5_data data; krb5_error_code code; if (!data_eq(*attribute, greet_attr)) return ENOENT; if (greet->greeting.data != NULL) return EEXIST; code = krb5int_copy_data_contents_add0(kcontext, value, &data); if (code != 0) return code; krb5_free_data_contents(kcontext, &greet->greeting); greet->greeting = data; greet->verified = FALSE; return 0; } static krb5_error_code greet_delete_attribute(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context, const krb5_data *attribute) { struct greet_context *greet = (struct greet_context *)request_context; krb5_free_data_contents(kcontext, &greet->greeting); greet->verified = FALSE; return 0; } static krb5_error_code 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; *sizep += sizeof(krb5_int32) + greet->greeting.length + sizeof(krb5_int32); return 0; } 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; 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_internalize(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context, krb5_octet **buffer, size_t *lenremain) { 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; /* 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; } } /* 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 }; krb5plugin_authdata_client_ftable_v0 authdata_client_0 = { "greet", greet_ad_types, greet_init, greet_fini, greet_flags, greet_request_init, greet_request_fini, greet_get_attribute_types, greet_get_attribute, greet_set_attribute, greet_delete_attribute, greet_export_authdata, greet_import_authdata, NULL, NULL, NULL, greet_size, greet_externalize, greet_internalize, NULL };