From: Alejandro Perez Date: Thu, 9 Feb 2017 13:10:14 +0000 (+0100) Subject: Add support for escaping JSON strings. X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mod_auth_kerb.git;a=commitdiff_plain;h=51a483b1adabe74a3d469bd157feb7168d5350f1 Add support for escaping JSON strings. JSON strings need to be scaped or attributes which " (such as SAML assertions) will not work as expected. --- diff --git a/gss.c b/gss.c index 9ebba62..75a40bd 100644 --- a/gss.c +++ b/gss.c @@ -352,6 +352,16 @@ static char mag_get_name_attr(request_rec *req, return 1; } +#define GSS_NAME_ATTR_USERDATA "GSS Name Attributes Userdata" + +static apr_status_t mag_gss_name_attrs_cleanup(void *data) +{ + gss_conn_ctx_t *gss_ctx = (struct gss_conn_ctx_t *)data; + free(gss_ctx->name_attributes); + gss_ctx->name_attributes = NULL; + return 0; +} + static void mc_add_name_attribute(gss_conn_ctx_t *gss_ctx, const char *name, const char *value) { @@ -361,6 +371,8 @@ static void mc_add_name_attribute(gss_conn_ctx_t *gss_ctx, size = sizeof(mag_attr) * (gss_ctx->na_count + 16); gss_ctx->name_attributes = realloc(gss_ctx->name_attributes, size); if (!gss_ctx->name_attributes) apr_pool_abort_get(gss_ctx->pool)(ENOMEM); + apr_pool_userdata_setn(gss_ctx, GSS_NAME_ATTR_USERDATA, + mag_gss_name_attrs_cleanup, gss_ctx->pool); } gss_ctx->name_attributes[gss_ctx->na_count].name = apr_pstrdup(gss_ctx->pool, name); @@ -404,6 +416,37 @@ static void mag_set_env_name_attr(request_rec *req, gss_conn_ctx_t *gss_ctx, } } +static char* mag_escape_display_value(request_rec *req, gss_buffer_desc disp_value) +{ + /* This function returns a copy (in the pool) of the given gss_buffer_t where every + * occurrence of " has been replaced by \". This string is NULL terminated */ + int i = 0, j = 0, n_quotes = 0; + char *escaped_value = NULL; + char *value = (char*) disp_value.value; + + // count number of quotes in the input string + for (i = 0, j = 0; i < disp_value.length; i++) + if (value[i] == '"') + n_quotes++; + + // if there are no quotes, just return a copy of the string + if (n_quotes == 0) + return apr_pstrndup(req->pool, value, disp_value.length); + + // gss_buffer_t are not \0 terminated, but our result will be + escaped_value = apr_palloc(req->pool, disp_value.length + n_quotes + 1); + for (i = 0,j = 0; i < disp_value.length; i++, j++) { + if (value[i] == '"') { + escaped_value[j] = '\\'; + j++; + } + escaped_value[j] = value[i]; + } + // make the string NULL terminated + escaped_value[j] = '\0'; + return escaped_value; +} + static void mag_add_json_name_attr(request_rec *req, char first, name_attr *attr, char **json) { @@ -423,8 +466,8 @@ static void mag_add_json_name_attr(request_rec *req, char first, attr->value.length); } if (attr->display_value.length != 0) { - len = attr->display_value.length; - value = (const char *)attr->display_value.value; + value = mag_escape_display_value(req, attr->display_value); + len = strlen(value); } if (attr->number == 1) { *json = apr_psprintf(req->pool, @@ -469,10 +512,6 @@ gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; void mag_get_name_attributes(request_rec *req, gss_auth_config *cfg, gss_name_t name, gss_conn_ctx_t *gss_ctx) { - if (!cfg->name_attributes) { - return; - } - uint32_t maj, min; gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; name_attr attr; @@ -526,7 +565,6 @@ void mag_get_name_attributes(request_rec *req, gss_auth_config *cfg, attr.number = 0; attr.more = -1; do { - char code = 0; attr.number++; attr.value = empty_buffer; attr.display_value = empty_buffer; @@ -569,8 +607,6 @@ void mag_set_req_data(request_rec *req, } } -#define GSS_NAME_ATTR_USERDATA "GSS Name Attributes Userdata" - static apr_status_t mag_name_attrs_cleanup(void *data) { gss_auth_config *cfg = (gss_auth_config *)data; @@ -630,4 +666,4 @@ const char *mag_name_attrs(cmd_parms *parms, void *mconfig, cfg->name_attributes->map_count += 1; return NULL; -} \ No newline at end of file +} diff --git a/mod_auth_gssapi.c b/mod_auth_gssapi.c index 02ea261..d533594 100644 --- a/mod_auth_gssapi.c +++ b/mod_auth_gssapi.c @@ -212,11 +212,13 @@ gss_authenticate(request_rec *r, gss_auth_config *conf, gss_conn_ctx ctx, } major_status = gss_display_name(&minor_status, client_name, &output_token, NULL); - ctx->user = apr_pstrdup(r->pool, output_token.value); + ctx->user = apr_pstrndup(r->pool, output_token.value, output_token.length); + + if (conf->name_attributes) { + mag_get_name_attributes(r, conf, client_name, ctx); + mag_set_req_data(r, conf, ctx); + } - /* TODO: Make it a single call! */ - mag_get_name_attributes(r, conf, client_name, ctx); - mag_set_req_data(r, conf, ctx); gss_release_name(&minor_status, &client_name); if (GSS_ERROR(major_status)) { @@ -248,6 +250,13 @@ end: return ret; } +static int mag_post_config(apr_pool_t *cfgpool, apr_pool_t *log, + apr_pool_t *temp, server_rec *s) +{ + ap_add_version_component(cfgpool, "Moonshot mod_auth_gssapi"); + return OK; +} + static int gss_authenticate_user(request_rec *r) { @@ -335,6 +344,7 @@ static void gss_register_hooks(apr_pool_t *p) { ap_hook_check_user_id(gss_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_post_config(mag_post_config, NULL, NULL, APR_HOOK_MIDDLE); } module AP_MODULE_DECLARE_DATA auth_gssapi_module = {