X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mod_auth_gssapi.git;a=blobdiff_plain;f=src%2Fenviron.c;h=9ef010bb6e88ed984acdfb298eba44b8465eb3fb;hp=0ff7cf0e369156b403943079194cf3219eb975d3;hb=7f11db955b8440668fc806b4203f584bb44f58c1;hpb=472d605d916f7ad63cd8bbffa100997eca700da4 diff --git a/src/environ.c b/src/environ.c index 0ff7cf0..9ef010b 100644 --- a/src/environ.c +++ b/src/environ.c @@ -1,7 +1,243 @@ /* Copyright (C) 2015 mod_auth_gssapi authors - See COPYING for (C) terms */ #include "mod_auth_gssapi.h" -#include "environ.h" + +struct name_attr { + gss_buffer_desc name; + int authenticated; + int complete; + gss_buffer_desc value; + gss_buffer_desc display_value; + const char *env_name; + int number; + int more; +}; + +static bool mag_get_name_attr(request_rec *req, + gss_name_t name, struct name_attr *attr) +{ + uint32_t maj, min; + + maj = gss_get_name_attribute(&min, name, &attr->name, + &attr->authenticated, + &attr->complete, + &attr->value, + &attr->display_value, + &attr->more); + if (GSS_ERROR(maj)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, + "gss_get_name_attribute() failed on %.*s%s", + (int)attr->name.length, (char *)attr->name.value, + mag_error(req, "", maj, min)); + return false; + } + + return true; +} + +static void mc_add_name_attribute(struct mag_conn *mc, + const char *name, const char *value) +{ + size_t size; + + if (mc->na_count % 16 == 0) { + size = sizeof(struct mag_attr) * (mc->na_count + 16); + mc->name_attributes = realloc(mc->name_attributes, size); + if (!mc->name_attributes) apr_pool_abort_get(mc->pool)(ENOMEM); + } + + mc->name_attributes[mc->na_count].name = apr_pstrdup(mc->pool, name); + mc->name_attributes[mc->na_count].value = apr_pstrdup(mc->pool, value); + mc->na_count++; +} + +static void mag_set_env_name_attr(request_rec *req, struct mag_conn *mc, + struct name_attr *attr) +{ + char *value = ""; + int len = 0; + + /* Prefer a display_value, otherwise fallback to value */ + if (attr->display_value.length != 0) { + len = attr->display_value.length; + value = (char *)attr->display_value.value; + } else if (attr->value.length != 0) { + len = apr_base64_encode_len(attr->value.length); + value = apr_pcalloc(req->pool, len); + len = apr_base64_encode(value, + (char *)attr->value.value, + attr->value.length); + } + + if (attr->number == 1) { + mc_add_name_attribute(mc, + attr->env_name, + apr_psprintf(req->pool, "%.*s", len, value)); + } + if (attr->more != 0 || attr->number > 1) { + mc_add_name_attribute(mc, + apr_psprintf(req->pool, "%s_%d", + attr->env_name, attr->number), + apr_psprintf(req->pool, "%.*s", len, value)); + } + if (attr->more == 0 && attr->number > 1) { + mc_add_name_attribute(mc, + apr_psprintf(req->pool, "%s_N", attr->env_name), + apr_psprintf(req->pool, "%d", attr->number - 1)); + } +} + +static void mag_add_json_name_attr(request_rec *req, bool first, + struct name_attr *attr, char **json) +{ + const char *value = ""; + int len = 0; + char *b64value = NULL; + int b64len = 0; + const char *vstart = ""; + const char *vend = ""; + const char *vformat; + + if (attr->value.length != 0) { + b64len = apr_base64_encode_len(attr->value.length); + b64value = apr_pcalloc(req->pool, b64len); + b64len = apr_base64_encode(b64value, + (char *)attr->value.value, + attr->value.length); + } + if (attr->display_value.length != 0) { + len = attr->display_value.length; + value = (const char *)attr->display_value.value; + } + if (attr->number == 1) { + *json = apr_psprintf(req->pool, + "%s%s\"%.*s\":{\"authenticated\":%s," + "\"complete\":%s," + "\"values\":[", + *json, (first ? "" : ","), + (int)attr->name.length, (char *)attr->name.value, + attr->authenticated ? "true" : "false", + attr->complete ? "true" : "false"); + } else { + vstart = ","; + } + + if (b64value) { + if (len) { + vformat = "%s%s{\"raw\":\"%s\",\"display\":\"%.*s\"}%s"; + } else { + vformat = "%s%s{\"raw\":\"%s\",\"display\":%.*s}%s"; + } + } else { + if (len) { + vformat = "%s%s{\"raw\":%s,\"display\":\"%.*s\"}%s"; + } else { + vformat = "%s%s{\"raw\":%s,\"display\":%.*s}%s"; + } + } + + if (attr->more == 0) { + vend = "]}"; + } + + *json = apr_psprintf(req->pool, vformat, *json, + vstart, + b64value ? b64value : "null", + len ? len : 4, len ? value : "null", + vend); +} + +gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; + +void mag_get_name_attributes(request_rec *req, struct mag_config *cfg, + gss_name_t name, struct mag_conn *mc) +{ + uint32_t maj, min; + gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; + struct name_attr attr; + char *json = NULL; + char *error; + int count = 0; + int i, j; + + maj = gss_inquire_name(&min, name, NULL, NULL, &attrs); + if (GSS_ERROR(maj)) { + error = mag_error(req, "gss_inquire_name() failed", maj, min); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", error); + apr_table_set(req->subprocess_env, "GSS_NAME_ATTR_ERROR", error); + return; + } + + if (!attrs || attrs->count == 0) { + mc_add_name_attribute(mc, "GSS_NAME_ATTR_ERROR", "0 attributes found"); + } + + if (cfg->name_attributes->output_json) { + + if (attrs) count = attrs->count; + + json = apr_psprintf(req->pool, + "{\"name\":\"%s\",\"attributes\":{", + mc->gss_name); + } else { + count = cfg->name_attributes->map_count; + } + + for (i = 0; i < count; i++) { + + memset(&attr, 0, sizeof(struct name_attr)); + + if (cfg->name_attributes->output_json) { + attr.name = attrs->elements[i]; + for (j = 0; j < cfg->name_attributes->map_count; j++) { + if (strncmp(cfg->name_attributes->map[j].attr_name, + attrs->elements[i].value, + attrs->elements[i].length) == 0) { + attr.env_name = cfg->name_attributes->map[j].env_name; + break; + } + } + } else { + attr.name.length = strlen(cfg->name_attributes->map[i].attr_name); + attr.name.value = cfg->name_attributes->map[i].attr_name; + attr.env_name = cfg->name_attributes->map[i].env_name; + } + + attr.number = 0; + attr.more = -1; + do { + attr.number++; + attr.value = empty_buffer; + attr.display_value = empty_buffer; + + if (!mag_get_name_attr(req, name, &attr)) continue; + + if (cfg->name_attributes->output_json) { + mag_add_json_name_attr(req, i == 0, &attr, &json); + } + if (attr.env_name) { + mag_set_env_name_attr(req, mc, &attr); + } + + gss_release_buffer(&min, &attr.value); + gss_release_buffer(&min, &attr.display_value); + } while (attr.more != 0); + } + + if (cfg->name_attributes->output_json) { + json = apr_psprintf(req->pool, "%s}}", json); + mc_add_name_attribute(mc, "GSS_NAME_ATTRS_JSON", json); + } +} + +static void mag_set_name_attributes(request_rec *req, struct mag_conn *mc) +{ + for (int i = 0; i < mc->na_count; i++) { + apr_table_set(req->subprocess_env, + mc->name_attributes[i].name, + mc->name_attributes[i].value); + } +} static void mag_set_KRB5CCANME(request_rec *req, char *ccname) { @@ -31,6 +267,11 @@ void mag_set_req_data(request_rec *req, req->ap_auth_type = apr_pstrdup(req->pool, mag_str_auth_type(mc->auth_type)); req->user = apr_pstrdup(req->pool, mc->user_name); + + if (mc->name_attributes) { + mag_set_name_attributes(req, mc); + } + if (cfg->deleg_ccache_dir && mc->delegated) { char *ccname; ccname = mag_gss_name_to_ccache_name(req,