@@ -43,6 +43,75 @@ static apr_status_t mag_mc_name_attrs_cleanup(void *data)
4343 return 0 ;
4444}
4545
46+ static apr_status_t mag_mc_req_name_attrs_cleanup (void * data )
47+ {
48+ struct mag_conn * mc = (struct mag_conn * )data ;
49+
50+ free (mc -> required_name_attrs );
51+ free (mc -> required_name_vals );
52+ mc -> required_name_attrs = NULL ;
53+ mc -> required_name_vals = NULL ;
54+ return 0 ;
55+ }
56+
57+ static void mag_set_required_name_attr (request_rec * req ,
58+ struct mag_conn * mc ,
59+ struct name_attr * attr )
60+ {
61+ size_t count , len ;
62+ char * val = NULL , * attrval = NULL ;
63+
64+ /* Count the existing name attribute and value pairs. Both
65+ * required_name_attrs and required_name_vals are allocated together and
66+ * hold the same number of strings, with pairs corresponding by index. */
67+ for (count = 0 ; mc -> required_name_attrs != NULL &&
68+ mc -> required_name_attrs [count ] != NULL &&
69+ mc -> required_name_vals != NULL &&
70+ mc -> required_name_vals [count ] != NULL ; count ++ );
71+
72+ /* Prefer a display value string. */
73+ if (attr -> display_value .length != 0 ) {
74+ len = attr -> display_value .length ;
75+ attrval = attr -> display_value .value ;
76+ } else if (attr -> value .length != 0 ) {
77+ len = attr -> value .length ;
78+ attrval = attr -> value .value ;
79+ } else {
80+ ap_log_rerror (APLOG_MARK , APLOG_DEBUG , 0 , req ,
81+ "no name attribute value available" );
82+ return ;
83+ }
84+
85+ /* Prepend the value length. */
86+ val = apr_pcalloc (mc -> pool , sizeof (len ) + len + 1 );
87+ memcpy (val , & len , sizeof (len ));
88+ memcpy (val + sizeof (len ), attrval , len );
89+
90+ /* Allocate/realloc a new bunch. */
91+ if (count % 16 == 0 ) {
92+ size_t size = sizeof (* mc -> required_name_attrs ) * (count + 16 + 2 );
93+ mc -> required_name_attrs = realloc (mc -> required_name_attrs , size );
94+ mc -> required_name_vals = realloc (mc -> required_name_vals , size );
95+ if (!mc -> required_name_attrs || !mc -> required_name_vals ) {
96+ apr_pool_abort_get (mc -> pool )(ENOMEM );
97+ }
98+ apr_pool_userdata_setn (mc , GSS_NAME_ATTR_USERDATA ,
99+ mag_mc_req_name_attrs_cleanup , mc -> pool );
100+ }
101+
102+ mc -> required_name_attrs [count ] = apr_pstrndup (mc -> pool , attr -> name .value ,
103+ attr -> name .length );
104+ mc -> required_name_attrs [count + 1 ] = NULL ;
105+ mc -> required_name_vals [count ] = val ;
106+ mc -> required_name_vals [count + 1 ] = NULL ;
107+
108+ ap_log_rerror (APLOG_MARK , APLOG_DEBUG , 0 , req ,
109+ "found name attribute '%s' with length %lu" ,
110+ mc -> required_name_attrs [count ], len );
111+ ap_log_rdata (APLOG_MARK , APLOG_DEBUG , req , mc -> required_name_attrs [count ],
112+ mc -> required_name_vals [count ] + sizeof (len ), len , 0 );
113+ }
114+
46115static void mc_add_name_attribute (struct mag_conn * mc ,
47116 const char * name , const char * value )
48117{
@@ -221,17 +290,17 @@ gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
221290void mag_get_name_attributes (request_rec * req , struct mag_config * cfg ,
222291 gss_name_t name , struct mag_conn * mc )
223292{
224- if (!cfg -> name_attributes ) {
225- return ;
226- }
227-
228293 uint32_t maj , min ;
229294 gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET ;
230295 struct name_attr attr ;
231296 char * json = NULL ;
232297 char * error ;
233- int count = 0 ;
234- int i , j ;
298+ int count = 0 , map_count = 0 ;
299+ int i ;
300+
301+ if (!cfg -> name_attributes && !cfg -> required_na_expr ) {
302+ return ;
303+ }
235304
236305 maj = gss_inquire_name (& min , name , NULL , NULL , & attrs );
237306 if (GSS_ERROR (maj )) {
@@ -242,62 +311,77 @@ void mag_get_name_attributes(request_rec *req, struct mag_config *cfg,
242311 }
243312
244313 if (!attrs || attrs -> count == 0 ) {
245- mc_add_name_attribute (mc , "GSS_NAME_ATTR_ERROR" , "0 attributes found" );
314+ if (cfg -> name_attributes ) {
315+ mc_add_name_attribute (mc , "GSS_NAME_ATTR_ERROR" , "0 attributes found" );
316+ }
317+ ap_log_rerror (APLOG_MARK , APLOG_DEBUG , 0 , req , "no name attributes found" );
246318 }
247319
248- if (cfg -> name_attributes -> output_json ) {
320+ if (attrs ) {
321+ count = attrs -> count ;
322+ }
249323
250- if (attrs ) count = attrs -> count ;
324+ if (cfg -> name_attributes ) {
325+ map_count = cfg -> name_attributes -> map_count ;
326+ }
251327
328+ if (cfg -> name_attributes && cfg -> name_attributes -> output_json ) {
252329 json = apr_psprintf (req -> pool ,
253330 "{\"name\":\"%s\",\"attributes\":{" ,
254331 mc -> gss_name );
255- } else {
256- count = cfg -> name_attributes -> map_count ;
257332 }
258333
334+ /* Collect all name attributes */
259335 for (i = 0 ; i < count ; i ++ ) {
260-
261336 memset (& attr , 0 , sizeof (struct name_attr ));
262337
263- if (cfg -> name_attributes -> output_json ) {
264- attr .name = attrs -> elements [i ];
265- for (j = 0 ; j < cfg -> name_attributes -> map_count ; j ++ ) {
338+ attr .name = attrs -> elements [i ];
339+ if (map_count ) {
340+ /* Use the environment variable name matching the attribute name
341+ * from the map. */
342+ for (int j = 0 ; j < map_count ; j ++ ) {
266343 if (strncmp (cfg -> name_attributes -> map [j ].attr_name ,
267- attrs -> elements [ i ] .value ,
268- attrs -> elements [ i ] .length ) == 0 ) {
344+ attr . name .value ,
345+ attr . name .length ) == 0 ) {
269346 attr .env_name = cfg -> name_attributes -> map [j ].env_name ;
270347 break ;
271348 }
272349 }
273- } else {
274- attr .name .length = strlen (cfg -> name_attributes -> map [i ].attr_name );
275- attr .name .value = cfg -> name_attributes -> map [i ].attr_name ;
276- attr .env_name = cfg -> name_attributes -> map [i ].env_name ;
277350 }
278-
279351 attr .number = 0 ;
280352 attr .more = -1 ;
281353 do {
282354 attr .number ++ ;
283355 attr .value = empty_buffer ;
284356 attr .display_value = empty_buffer ;
285357
286- if (!mag_get_name_attr (req , name , & attr )) break ;
358+ /* Fetch the next attribute value. */
359+ if (!mag_get_name_attr (req , name , & attr )) {
360+ break ;
361+ }
287362
288- if (cfg -> name_attributes -> output_json ) {
363+ /* Add as a JSON value if needed. */
364+ if (cfg -> name_attributes && cfg -> name_attributes -> output_json ) {
289365 mag_add_json_name_attr (req , i == 0 , & attr , & json );
290366 }
367+
368+ /* Add as an environment variable if needed. */
291369 if (attr .env_name ) {
292370 mag_set_env_name_attr (req , mc , & attr );
293371 }
294372
373+ /* Add to the list of name attributes lined up for the requirement
374+ * check if needed. */
375+ if (cfg -> required_na_expr ) {
376+ mag_set_required_name_attr (req , mc , & attr );
377+ }
378+
295379 gss_release_buffer (& min , & attr .value );
296380 gss_release_buffer (& min , & attr .display_value );
297381 } while (attr .more != 0 );
298382 }
299383
300- if (cfg -> name_attributes -> output_json ) {
384+ if (cfg -> name_attributes && cfg -> name_attributes -> output_json ) {
301385 json = apr_psprintf (req -> pool , "%s}}" , json );
302386 mc_add_name_attribute (mc , "GSS_NAME_ATTRS_JSON" , json );
303387 }
@@ -393,6 +477,14 @@ void mag_set_req_data(request_rec *req,
393477 mag_export_req_env (req , mc -> env );
394478}
395479
480+ void mag_set_req_attr_fail (request_rec * req , struct mag_config * cfg ,
481+ struct mag_conn * mc )
482+ {
483+ apr_table_set (mc -> env , "GSS_NAME_ATTR_ERROR" ,
484+ "required name attributes check unsatisfied" );
485+ mag_set_req_data (req , cfg , mc );
486+ }
487+
396488void mag_publish_error (request_rec * req , uint32_t maj , uint32_t min ,
397489 const char * gss_err , const char * mag_err )
398490{
0 commit comments