@@ -344,3 +344,217 @@ ngx_int_t oauth2_nginx_http_response_set(oauth2_log_t *log,
344
344
345
345
return nrc ;
346
346
}
347
+
348
+ typedef struct oauth2_nginx_claim_hash_t {
349
+ ngx_hash_keys_arrays_t keys ;
350
+ ngx_hash_t h ;
351
+ } oauth2_nginx_claim_hash_t ;
352
+
353
+ static inline ngx_str_t oauth2_nginx_chr2str (ngx_pool_t * p , const char * k )
354
+ {
355
+ ngx_str_t in = {strlen (k ), (u_char * )k };
356
+ ngx_str_t out = {in .len , ngx_pstrdup (p , & in )};
357
+ return out ;
358
+ }
359
+
360
+ char * oauth2_nginx_str2chr (ngx_pool_t * p , const ngx_str_t * str )
361
+ {
362
+ char * s = ngx_pnalloc (p , str -> len + 1 );
363
+ if (s != NULL ) {
364
+ memcpy (s , str -> data , str -> len );
365
+ s [str -> len ] = '\0' ;
366
+ }
367
+ return s ;
368
+ }
369
+
370
+ static inline char * oauth2_nginx_chr2chr (ngx_pool_t * p , const char * str )
371
+ {
372
+ ngx_str_t s = {strlen (str ), (u_char * )str };
373
+ return oauth2_nginx_str2chr (p , & s );
374
+ }
375
+
376
+ ngx_int_t oauth2_nginx_claim_variable (ngx_module_t module ,
377
+ ngx_http_request_t * r ,
378
+ ngx_http_variable_value_t * v ,
379
+ uintptr_t data )
380
+ {
381
+ oauth2_nginx_claim_hash_t * claims = NULL ;
382
+ const char * value = NULL ;
383
+ ngx_str_t key = {strlen ((const char * )data ), (u_char * )data };
384
+
385
+ claims =
386
+ (oauth2_nginx_claim_hash_t * )ngx_http_get_module_ctx (r , module );
387
+
388
+ if (claims == NULL ) {
389
+ v -> not_found = 1 ;
390
+ return NGX_OK ;
391
+ }
392
+
393
+ value = (const char * )ngx_hash_find (
394
+ & claims -> h , ngx_hash_key (key .data , key .len ), key .data , key .len );
395
+
396
+ if (value != NULL ) {
397
+ ngx_log_debug2 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
398
+ "oauth2_nginx_claim_variable: %V=%s" , & key ,
399
+ value );
400
+ v -> data = (u_char * )value ;
401
+ v -> len = strlen (value );
402
+ v -> no_cacheable = 1 ;
403
+ v -> not_found = 0 ;
404
+ } else {
405
+ ngx_log_debug1 (NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 ,
406
+ "oauth2_nginx_claim_variable: %V=(null)" , & key );
407
+ v -> not_found = 1 ;
408
+ }
409
+
410
+ return NGX_OK ;
411
+ }
412
+
413
+ static const size_t MAX_BUF = 128 ;
414
+
415
+ char * oauth2_nginx_set_claim (ngx_module_t module ,
416
+ ngx_http_get_variable_pt handler , ngx_conf_t * cf ,
417
+ ngx_command_t * cmd , void * conf )
418
+ {
419
+ ngx_http_variable_t * v ;
420
+ char buf [MAX_BUF ];
421
+ int n = 0 ;
422
+ char * s = NULL ;
423
+ ngx_str_t * value = cf -> args -> elts ;
424
+
425
+ if (value [2 ].len <= 1 || value [2 ].data [0 ] != '$' ) {
426
+ n = snprintf (buf , sizeof (buf ), "Invalid variable name %.*s" ,
427
+ (int )value [2 ].len , value [2 ].data );
428
+ ngx_str_t msg = {n , (u_char * )& buf [0 ]};
429
+ s = oauth2_nginx_str2chr (cf -> pool , & msg );
430
+ return s ? s : NGX_CONF_ERROR ;
431
+ }
432
+
433
+ value [2 ].len -- ;
434
+ value [2 ].data ++ ;
435
+
436
+ v = ngx_http_add_variable (cf , & value [2 ], NGX_HTTP_VAR_CHANGEABLE );
437
+ if (!v ) {
438
+ ngx_str_t msg = ngx_string ("ngx_http_add_variable failed" );
439
+ s = oauth2_nginx_str2chr (cf -> pool , & msg );
440
+ return s ? s : NGX_CONF_ERROR ;
441
+ }
442
+
443
+ v -> get_handler = handler ;
444
+ char * claim = oauth2_nginx_str2chr (cf -> pool , & value [1 ]);
445
+ if (!claim ) {
446
+ ngx_str_t msg = ngx_string ("Out of memory" );
447
+ s = oauth2_nginx_str2chr (cf -> pool , & msg );
448
+ return s ? s : NGX_CONF_ERROR ;
449
+ }
450
+ v -> data = (uintptr_t )claim ;
451
+
452
+ return NGX_CONF_OK ;
453
+ }
454
+
455
+ static ngx_int_t ngx_set_target_variable (oauth2_nginx_claim_hash_t * claims ,
456
+ oauth2_nginx_request_context_t * ctx ,
457
+ const char * k , const char * v )
458
+ {
459
+ ngx_str_t key = oauth2_nginx_chr2str (claims -> keys .pool , k );
460
+ if (key .data == NULL )
461
+ return NGX_ERROR ;
462
+ const char * value = oauth2_nginx_chr2chr (claims -> keys .pool , v );
463
+ if (value == NULL )
464
+ return NGX_ERROR ;
465
+ return ngx_hash_add_key (& claims -> keys , & key , (char * )value ,
466
+ NGX_HASH_READONLY_KEY );
467
+ }
468
+
469
+ static ngx_int_t ngx_oauth2_init_keys (ngx_pool_t * pool ,
470
+ oauth2_nginx_claim_hash_t * claims )
471
+ {
472
+ claims -> keys .pool = pool ;
473
+ claims -> keys .temp_pool = pool ;
474
+ return ngx_hash_keys_array_init (& claims -> keys , NGX_HASH_SMALL );
475
+ }
476
+
477
+ static ngx_int_t ngx_oauth2_init_hash (ngx_pool_t * pool ,
478
+ oauth2_nginx_claim_hash_t * claims )
479
+ {
480
+ ngx_hash_init_t init ;
481
+ init .hash = & claims -> h ;
482
+ init .key = ngx_hash_key ;
483
+ init .max_size = 64 ;
484
+ init .bucket_size = ngx_align (64 , ngx_cacheline_size );
485
+ init .name = "claims" ;
486
+ init .pool = pool ;
487
+ init .temp_pool = pool ;
488
+ return ngx_hash_init (& init , claims -> keys .keys .elts ,
489
+ claims -> keys .keys .nelts );
490
+ }
491
+
492
+ ngx_int_t oauth2_nginx_set_target_variables (ngx_module_t module ,
493
+ oauth2_nginx_request_context_t * ctx ,
494
+ json_t * json_token )
495
+ {
496
+ void * iter = NULL ;
497
+ const char * key = NULL , * val = NULL ;
498
+ json_t * value = NULL ;
499
+ oauth2_nginx_claim_hash_t * claims = NULL ;
500
+ int rc = NGX_OK ;
501
+
502
+ claims = (oauth2_nginx_claim_hash_t * )ngx_http_get_module_ctx (ctx -> r ,
503
+ module );
504
+
505
+ if (claims == NULL ) {
506
+
507
+ claims = ngx_palloc (ctx -> r -> pool , sizeof (* claims ));
508
+
509
+ if (claims == NULL ) {
510
+ oauth2_error (ctx -> log , "error allocating claims hash" );
511
+ return NGX_ERROR ;
512
+ }
513
+
514
+ rc = ngx_oauth2_init_keys (ctx -> r -> pool , claims );
515
+
516
+ if (rc != NGX_OK ) {
517
+ oauth2_error (ctx -> log ,
518
+ "error %d initializing hash keys" , rc );
519
+ return rc ;
520
+ }
521
+
522
+ ngx_http_set_ctx (ctx -> r , claims , module );
523
+ }
524
+
525
+ iter = json_object_iter (json_token );
526
+ while (iter ) {
527
+
528
+ key = json_object_iter_key (iter );
529
+ value = json_object_iter_value (iter );
530
+
531
+ if (json_is_string (value )) {
532
+ rc = ngx_set_target_variable (claims , ctx , key ,
533
+ json_string_value (value ));
534
+ } else {
535
+ val = oauth2_json_encode (ctx -> log , value ,
536
+ JSON_ENCODE_ANY );
537
+ rc = ngx_set_target_variable (claims , ctx , key , val );
538
+ oauth2_mem_free ((char * )val );
539
+ }
540
+
541
+ if (rc != NGX_OK ) {
542
+ oauth2_error (
543
+ ctx -> log ,
544
+ "error %d setting value of key %s in claims hash" ,
545
+ rc , key );
546
+ return rc ;
547
+ }
548
+
549
+ iter = json_object_iter_next (json_token , iter );
550
+ }
551
+
552
+ rc = ngx_oauth2_init_hash (ctx -> r -> pool , claims );
553
+
554
+ if (rc != NGX_OK ) {
555
+ oauth2_error (ctx -> log , "error %d initializing claims hash" , rc );
556
+ return rc ;
557
+ }
558
+
559
+ return NGX_OK ;
560
+ }
0 commit comments