39
39
40
40
from __future__ import absolute_import
41
41
42
+ import base64
42
43
import os
43
44
import time
44
45
@@ -231,6 +232,66 @@ def split_comma_concat(value_list, sep=','):
231
232
return result
232
233
233
234
235
+ def lookup_filter_illegal_handler (filter_method ):
236
+ """Get the illegal handler function to match filter_method. The output is
237
+ directly suitable for the filter_X helpers with illegal_handler argument.
238
+ """
239
+ # NOTE: the None value is a special case that means skip illegal values
240
+ if filter_method in ('' , 'skip' ):
241
+ return None
242
+ elif filter_method == 'hexlify' :
243
+ def hex_wrap (val ):
244
+ """Insert a clearly marked hex representation of val"""
245
+ # NOTE: use '.X' as '.x' will typically be capitalized in use anyway
246
+ return ".X%s" % base64 .b16encode (val )
247
+ return hex_wrap
248
+ else :
249
+ raise ValueError ("unsupported filter_method: %r" % filter_method )
250
+
251
+
252
+ def populate_prefilters (configuration , prefilter_map , auth_type ):
253
+ """Populate the prefilter map applied to input values before anything else
254
+ so that they can be used e.g. to mangle illegal values into compliance.
255
+ Particularly useful for making sure we keep file system names to something
256
+ we can actually safely handle.
257
+ """
258
+ _logger = configuration .logger
259
+ _logger .debug ("populate prefilters for %s" % auth_type )
260
+ # TODO: add better reversible filters like punycode or base64 on whole name
261
+ filter_name = configuration .auto_add_filter_method
262
+ illegal_handler = lookup_filter_illegal_handler (filter_name )
263
+ _logger .debug ("populate prefilters found filter illegal char handler %s" %
264
+ illegal_handler )
265
+ if auth_type == AUTH_OPENID_V2 :
266
+ if filter_name and 'full_name' in configuration .auto_add_filter_fields :
267
+ def _filter_helper (x ):
268
+ return filter_commonname (x , illegal_handler )
269
+ # NOTE: KUIT OpenID 2.0 provides full name as 'fullname'
270
+ for name in ('openid.sreg.fullname' , 'openid.sreg.full_name' ):
271
+ prefilter_map [name ] = _filter_helper
272
+ elif auth_type == AUTH_OPENID_CONNECT :
273
+ if configuration .auto_add_filter_method and \
274
+ 'full_name' in configuration .auto_add_filter_fields :
275
+ def _filter_helper (x ):
276
+ return filter_commonname (x , illegal_handler )
277
+ # NOTE: WAYF provides full name as 'name'
278
+ for name in ('oidc.claim.fullname' , 'oidc.claim.full_name' ,
279
+ 'oidc.claim.name' ):
280
+ prefilter_map [name ] = _filter_helper
281
+ elif auth_type == AUTH_CERTIFICATE :
282
+ if configuration .auto_add_filter_method and \
283
+ 'full_name' in configuration .auto_add_filter_fields :
284
+ def _filter_helper (x ):
285
+ return filter_commonname (x , illegal_handler )
286
+ for name in ('cert_name' , ):
287
+ prefilter_map [name ] = _filter_helper
288
+ else :
289
+ raise ValueError ("unsupported auth_type in populate_prefilters: %r" %
290
+ auth_type )
291
+ _logger .debug ("populate prefilters returns: %s" % prefilter_map )
292
+ return prefilter_map
293
+
294
+
234
295
def main (client_id , user_arguments_dict , environ = None ):
235
296
"""Main function used by front end"""
236
297
@@ -257,6 +318,8 @@ def main(client_id, user_arguments_dict, environ=None):
257
318
output_objects .append ({'object_type' : 'error_text' , 'text' :
258
319
'%s sign up not supported' % auth_flavor })
259
320
return (output_objects , returnvalues .SYSTEM_ERROR )
321
+ # NOTE: simple filters to handle unsupported chars e.g. in full name
322
+ populate_prefilters (configuration , prefilter_map , auth_type )
260
323
elif identity and auth_type == AUTH_OPENID_V2 :
261
324
if auth_flavor == AUTH_MIG_OID :
262
325
base_url = configuration .migserver_https_mig_oid_url
@@ -267,9 +330,8 @@ def main(client_id, user_arguments_dict, environ=None):
267
330
output_objects .append ({'object_type' : 'error_text' , 'text' :
268
331
'%s sign up not supported' % auth_flavor })
269
332
return (output_objects , returnvalues .SYSTEM_ERROR )
270
- for name in ('openid.sreg.cn' , 'openid.sreg.fullname' ,
271
- 'openid.sreg.full_name' ):
272
- prefilter_map [name ] = filter_commonname
333
+ # NOTE: simple filters to handle unsupported chars e.g. in full name
334
+ populate_prefilters (configuration , prefilter_map , auth_type )
273
335
elif identity and auth_type == AUTH_OPENID_CONNECT :
274
336
if auth_flavor == AUTH_MIG_OIDC :
275
337
base_url = configuration .migserver_https_mig_oidc_url
@@ -286,6 +348,8 @@ def main(client_id, user_arguments_dict, environ=None):
286
348
low_key = key .replace ('OIDC_CLAIM_' , 'oidc.claim.' ).lower ()
287
349
if low_key in oidc_keys :
288
350
user_arguments_dict [low_key ] = [environ [key ]]
351
+ # NOTE: simple filters to handle unsupported chars e.g. in full name
352
+ populate_prefilters (configuration , prefilter_map , auth_type )
289
353
else :
290
354
logger .error ('autocreate without ID rejected for %s' % client_id )
291
355
output_objects .append ({'object_type' : 'error_text' ,
0 commit comments