1 /* Copyright (C) 2015 mod_auth_gssapi authors - See COPYING for (C) terms */
3 #include "mod_auth_gssapi.h"
10 gss_buffer_desc display_value;
16 static bool mag_get_name_attr(request_rec *req,
17 gss_name_t name, struct name_attr *attr)
21 maj = gss_get_name_attribute(&min, name, &attr->name,
28 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
29 "gss_get_name_attribute() failed on %.*s%s",
30 (int)attr->name.length, (char *)attr->name.value,
31 mag_error(req, "", maj, min));
38 static void mc_add_name_attribute(struct mag_conn *mc,
39 const char *name, const char *value)
43 if (mc->na_count % 16 == 0) {
44 size = sizeof(struct mag_attr) * (mc->na_count + 16);
45 mc->name_attributes = realloc(mc->name_attributes, size);
46 if (!mc->name_attributes) apr_pool_abort_get(mc->pool)(ENOMEM);
49 mc->name_attributes[mc->na_count].name = apr_pstrdup(mc->pool, name);
50 mc->name_attributes[mc->na_count].value = apr_pstrdup(mc->pool, value);
54 static void mag_set_env_name_attr(request_rec *req, struct mag_conn *mc,
55 struct name_attr *attr)
60 /* Prefer a display_value, otherwise fallback to value */
61 if (attr->display_value.length != 0) {
62 len = attr->display_value.length;
63 value = (char *)attr->display_value.value;
64 } else if (attr->value.length != 0) {
65 len = apr_base64_encode_len(attr->value.length);
66 value = apr_pcalloc(req->pool, len);
67 len = apr_base64_encode(value,
68 (char *)attr->value.value,
72 if (attr->number == 1) {
73 mc_add_name_attribute(mc,
75 apr_psprintf(req->pool, "%.*s", len, value));
77 if (attr->more != 0 || attr->number > 1) {
78 mc_add_name_attribute(mc,
79 apr_psprintf(req->pool, "%s_%d",
80 attr->env_name, attr->number),
81 apr_psprintf(req->pool, "%.*s", len, value));
83 if (attr->more == 0 && attr->number > 1) {
84 mc_add_name_attribute(mc,
85 apr_psprintf(req->pool, "%s_N", attr->env_name),
86 apr_psprintf(req->pool, "%d", attr->number - 1));
90 static void mag_add_json_name_attr(request_rec *req, bool first,
91 struct name_attr *attr, char **json)
93 const char *value = "";
95 char *b64value = NULL;
97 const char *vstart = "";
98 const char *vend = "";
101 if (attr->value.length != 0) {
102 b64len = apr_base64_encode_len(attr->value.length);
103 b64value = apr_pcalloc(req->pool, b64len);
104 b64len = apr_base64_encode(b64value,
105 (char *)attr->value.value,
108 if (attr->display_value.length != 0) {
109 len = attr->display_value.length;
110 value = (const char *)attr->display_value.value;
112 if (attr->number == 1) {
113 *json = apr_psprintf(req->pool,
114 "%s%s\"%.*s\":{\"authenticated\":%s,"
117 *json, (first ? "" : ","),
118 (int)attr->name.length, (char *)attr->name.value,
119 attr->authenticated ? "true" : "false",
120 attr->complete ? "true" : "false");
127 vformat = "%s%s{\"raw\":\"%s\",\"display\":\"%.*s\"}%s";
129 vformat = "%s%s{\"raw\":\"%s\",\"display\":%.*s}%s";
133 vformat = "%s%s{\"raw\":%s,\"display\":\"%.*s\"}%s";
135 vformat = "%s%s{\"raw\":%s,\"display\":%.*s}%s";
139 if (attr->more == 0) {
143 *json = apr_psprintf(req->pool, vformat, *json,
145 b64value ? b64value : "null",
146 len ? len : 4, len ? value : "null",
150 gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
152 void mag_get_name_attributes(request_rec *req, struct mag_config *cfg,
153 gss_name_t name, struct mag_conn *mc)
155 if (!cfg->name_attributes) {
160 gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET;
161 struct name_attr attr;
167 maj = gss_inquire_name(&min, name, NULL, NULL, &attrs);
168 if (GSS_ERROR(maj)) {
169 error = mag_error(req, "gss_inquire_name() failed", maj, min);
170 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", error);
171 apr_table_set(req->subprocess_env, "GSS_NAME_ATTR_ERROR", error);
175 if (!attrs || attrs->count == 0) {
176 mc_add_name_attribute(mc, "GSS_NAME_ATTR_ERROR", "0 attributes found");
179 if (cfg->name_attributes->output_json) {
181 if (attrs) count = attrs->count;
183 json = apr_psprintf(req->pool,
184 "{\"name\":\"%s\",\"attributes\":{",
187 count = cfg->name_attributes->map_count;
190 for (i = 0; i < count; i++) {
192 memset(&attr, 0, sizeof(struct name_attr));
194 if (cfg->name_attributes->output_json) {
195 attr.name = attrs->elements[i];
196 for (j = 0; j < cfg->name_attributes->map_count; j++) {
197 if (strncmp(cfg->name_attributes->map[j].attr_name,
198 attrs->elements[i].value,
199 attrs->elements[i].length) == 0) {
200 attr.env_name = cfg->name_attributes->map[j].env_name;
205 attr.name.length = strlen(cfg->name_attributes->map[i].attr_name);
206 attr.name.value = cfg->name_attributes->map[i].attr_name;
207 attr.env_name = cfg->name_attributes->map[i].env_name;
214 attr.value = empty_buffer;
215 attr.display_value = empty_buffer;
217 if (!mag_get_name_attr(req, name, &attr)) break;
219 if (cfg->name_attributes->output_json) {
220 mag_add_json_name_attr(req, i == 0, &attr, &json);
223 mag_set_env_name_attr(req, mc, &attr);
226 gss_release_buffer(&min, &attr.value);
227 gss_release_buffer(&min, &attr.display_value);
228 } while (attr.more != 0);
231 if (cfg->name_attributes->output_json) {
232 json = apr_psprintf(req->pool, "%s}}", json);
233 mc_add_name_attribute(mc, "GSS_NAME_ATTRS_JSON", json);
237 static void mag_set_name_attributes(request_rec *req, struct mag_conn *mc)
239 for (int i = 0; i < mc->na_count; i++) {
240 apr_table_set(req->subprocess_env,
241 mc->name_attributes[i].name,
242 mc->name_attributes[i].value);
246 static void mag_set_KRB5CCANME(request_rec *req, char *ccname)
252 status = apr_stat(&finfo, ccname, APR_FINFO_MIN, req->pool);
253 if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
254 /* set the file cache anyway, but warn */
255 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
256 "KRB5CCNAME file (%s) lookup failed!", ccname);
259 value = apr_psprintf(req->pool, "FILE:%s", ccname);
260 apr_table_set(req->subprocess_env, "KRB5CCNAME", value);
263 void mag_set_req_data(request_rec *req,
264 struct mag_config *cfg,
267 apr_table_set(req->subprocess_env, "GSS_NAME", mc->gss_name);
268 apr_table_set(req->subprocess_env, "GSS_SESSION_EXPIRATION",
269 apr_psprintf(req->pool,
270 "%ld", (long)mc->expiration));
271 req->ap_auth_type = apr_pstrdup(req->pool,
272 mag_str_auth_type(mc->auth_type));
273 req->user = apr_pstrdup(req->pool, mc->user_name);
275 if (mc->name_attributes) {
276 mag_set_name_attributes(req, mc);
279 #ifdef HAVE_CRED_STORE
280 if (cfg->deleg_ccache_dir && mc->delegated) {
282 ccname = mag_gss_name_to_ccache_name(req,
283 cfg->deleg_ccache_dir,
286 mag_set_KRB5CCANME(req, ccname);