@@ -39,11 +39,11 @@ struct _mongoc_uri_t
39
39
char * password ;
40
40
char * database ;
41
41
bson_t options ;
42
+ bson_t credentials ;
42
43
bson_t read_prefs ;
43
44
mongoc_write_concern_t * write_concern ;
44
45
};
45
46
46
-
47
47
static void
48
48
mongoc_uri_do_unescape (char * * str )
49
49
{
@@ -86,27 +86,55 @@ mongoc_uri_append_host (mongoc_uri_t *uri,
86
86
}
87
87
}
88
88
89
+ /*
90
+ *--------------------------------------------------------------------------
91
+ *
92
+ * scan_to_unichar --
93
+ *
94
+ * Scans 'str' until either a character matching 'match' is found,
95
+ * until one of the characters in 'terminators' is encountered, or
96
+ * until we reach the end of 'str'.
97
+ *
98
+ * NOTE: 'terminators' may not include multibyte UTF-8 characters.
99
+ *
100
+ * Returns:
101
+ * If 'match' is found, returns a copy of the section of 'str' before
102
+ * that character. Otherwise, returns NULL.
103
+ *
104
+ * Side Effects:
105
+ * If 'match' is found, sets 'end' to begin at the matching character
106
+ * in 'str'.
107
+ *
108
+ *--------------------------------------------------------------------------
109
+ */
89
110
90
111
static char *
91
112
scan_to_unichar (const char * str ,
92
- bson_unichar_t stop ,
113
+ bson_unichar_t match ,
114
+ const char * terminators ,
93
115
const char * * end )
94
116
{
95
117
bson_unichar_t c ;
96
118
const char * iter ;
97
119
98
120
for (iter = str ;
99
121
iter && * iter && (c = bson_utf8_get_char (iter ));
100
- iter = bson_utf8_next_char (iter ))
101
- {
102
- if (c == stop ) {
122
+ iter = bson_utf8_next_char (iter )) {
123
+ if (c == match ) {
103
124
* end = iter ;
104
125
return bson_strndup (str , iter - str );
105
126
} else if (c == '\\' ) {
106
127
iter = bson_utf8_next_char (iter );
107
128
if (!bson_utf8_get_char (iter )) {
108
129
break ;
109
130
}
131
+ } else {
132
+ const char * term_iter ;
133
+ for (term_iter = terminators ; * term_iter ; term_iter ++ ) {
134
+ if (c == * term_iter ) {
135
+ return NULL ;
136
+ }
137
+ }
110
138
}
111
139
}
112
140
@@ -138,8 +166,8 @@ mongoc_uri_parse_userpass (mongoc_uri_t *uri,
138
166
const char * end_user ;
139
167
char * s ;
140
168
141
- if ((s = scan_to_unichar (str , '@' , & end_userpass ))) {
142
- if ((uri -> username = scan_to_unichar (s , ':' , & end_user ))) {
169
+ if ((s = scan_to_unichar (str , '@' , "" , & end_userpass ))) {
170
+ if ((uri -> username = scan_to_unichar (s , ':' , "" , & end_user ))) {
143
171
uri -> password = bson_strdup (end_user + 1 );
144
172
} else {
145
173
uri -> username = bson_strndup (str , end_userpass - str );
@@ -175,7 +203,7 @@ mongoc_uri_parse_host6 (mongoc_uri_t *uri,
175
203
#endif
176
204
}
177
205
178
- hostname = scan_to_unichar (str + 1 , ']' , & end_host );
206
+ hostname = scan_to_unichar (str + 1 , ']' , "" , & end_host );
179
207
180
208
mongoc_uri_do_unescape (& hostname );
181
209
mongoc_uri_append_host (uri , hostname , port );
@@ -197,7 +225,7 @@ mongoc_uri_parse_host (mongoc_uri_t *uri,
197
225
return mongoc_uri_parse_host6 (uri , str );
198
226
}
199
227
200
- if ((hostname = scan_to_unichar (str , ':' , & end_host ))) {
228
+ if ((hostname = scan_to_unichar (str , ':' , "?/," , & end_host ))) {
201
229
end_host ++ ;
202
230
if (!isdigit (* end_host )) {
203
231
bson_free (hostname );
@@ -234,7 +262,7 @@ _mongoc_host_list_from_string (mongoc_host_list_t *host_list,
234
262
235
263
memset (host_list , 0 , sizeof * host_list );
236
264
237
- if ((hostname = scan_to_unichar (host_and_port , ':' , & end_host ))) {
265
+ if ((hostname = scan_to_unichar (host_and_port , ':' , "" , & end_host ))) {
238
266
end_host ++ ;
239
267
if (!isdigit (* end_host )) {
240
268
bson_free (hostname );
@@ -305,7 +333,7 @@ mongoc_uri_parse_hosts (mongoc_uri_t *uri,
305
333
str ++ ;
306
334
goto again ;
307
335
}
308
- } else if ((s = scan_to_unichar (str , ',' , & end_hostport ))) {
336
+ } else if ((s = scan_to_unichar (str , ',' , "/" , & end_hostport ))) {
309
337
if (!mongoc_uri_parse_host (uri , s )) {
310
338
bson_free (s );
311
339
return false;
@@ -314,8 +342,8 @@ mongoc_uri_parse_hosts (mongoc_uri_t *uri,
314
342
str = end_hostport + 1 ;
315
343
ret = true;
316
344
goto again ;
317
- } else if ((s = scan_to_unichar (str , '/' , & end_hostport )) ||
318
- (s = scan_to_unichar (str , '?' , & end_hostport ))) {
345
+ } else if ((s = scan_to_unichar (str , '/' , "" , & end_hostport )) ||
346
+ (s = scan_to_unichar (str , '?' , "" , & end_hostport ))) {
319
347
if (!mongoc_uri_parse_host (uri , s )) {
320
348
bson_free (s );
321
349
return false;
@@ -342,7 +370,7 @@ mongoc_uri_parse_database (mongoc_uri_t *uri,
342
370
{
343
371
const char * end_database ;
344
372
345
- if ((uri -> database = scan_to_unichar (str , '?' , & end_database ))) {
373
+ if ((uri -> database = scan_to_unichar (str , '?' , "" , & end_database ))) {
346
374
* end = end_database ;
347
375
} else if (* str ) {
348
376
uri -> database = bson_strdup (str );
@@ -355,6 +383,37 @@ mongoc_uri_parse_database (mongoc_uri_t *uri,
355
383
}
356
384
357
385
386
+ static bool
387
+ mongoc_uri_parse_auth_mechanism_properties (mongoc_uri_t * uri ,
388
+ const char * str )
389
+ {
390
+ char * field ;
391
+ char * value ;
392
+ const char * end_scan ;
393
+ bson_t properties ;
394
+
395
+ bson_init (& properties );
396
+
397
+ /* build up the properties document */
398
+ while ((field = scan_to_unichar (str , ':' , "&" , & end_scan ))) {
399
+ str = end_scan + 1 ;
400
+ if (!(value = scan_to_unichar (str , ',' , ":&" , & end_scan ))) {
401
+ value = bson_strdup (str );
402
+ str = "" ;
403
+ } else {
404
+ str = end_scan + 1 ;
405
+ }
406
+ bson_append_utf8 (& properties , field , -1 , value , -1 );
407
+ bson_free (field );
408
+ bson_free (value );
409
+ }
410
+
411
+ /* append our auth properties to our credentials */
412
+ bson_append_document (& uri -> credentials , "mechanismProperties" ,
413
+ -1 , (const bson_t * )& properties );
414
+ return true;
415
+ }
416
+
358
417
static void
359
418
mongoc_uri_parse_tags (mongoc_uri_t * uri , /* IN */
360
419
const char * str , /* IN */
@@ -371,16 +430,16 @@ mongoc_uri_parse_tags (mongoc_uri_t *uri, /* IN */
371
430
bson_init (& b );
372
431
373
432
again :
374
- if ((keyval = scan_to_unichar (str , ',' , & end_keyval ))) {
375
- if ((key = scan_to_unichar (keyval , ':' , & end_key ))) {
433
+ if ((keyval = scan_to_unichar (str , ',' , "" , & end_keyval ))) {
434
+ if ((key = scan_to_unichar (keyval , ':' , "" , & end_key ))) {
376
435
bson_append_utf8 (& b , key , -1 , end_key + 1 , -1 );
377
436
bson_free (key );
378
437
}
379
438
bson_free (keyval );
380
439
str = end_keyval + 1 ;
381
440
goto again ;
382
441
} else {
383
- if ((key = scan_to_unichar (str , ':' , & end_key ))) {
442
+ if ((key = scan_to_unichar (str , ':' , "" , & end_key ))) {
384
443
bson_append_utf8 (& b , key , -1 , end_key + 1 , -1 );
385
444
bson_free (key );
386
445
}
@@ -402,7 +461,7 @@ mongoc_uri_parse_option (mongoc_uri_t *uri,
402
461
char * key ;
403
462
char * value ;
404
463
405
- if (!(key = scan_to_unichar (str , '=' , & end_key ))) {
464
+ if (!(key = scan_to_unichar (str , '=' , "" , & end_key ))) {
406
465
return false;
407
466
}
408
467
@@ -439,6 +498,15 @@ mongoc_uri_parse_option (mongoc_uri_t *uri,
439
498
(0 == strcmp (value , "1" )));
440
499
} else if (!strcasecmp (key , "readpreferencetags" )) {
441
500
mongoc_uri_parse_tags (uri , value , & uri -> read_prefs );
501
+ } else if (!strcasecmp (key , "authmechanism" ) ||
502
+ !strcasecmp (key , "authsource" )) {
503
+ bson_append_utf8 (& uri -> credentials , key , -1 , value , -1 );
504
+ } else if (!strcasecmp (key , "authmechanismproperties" )) {
505
+ if (!mongoc_uri_parse_auth_mechanism_properties (uri , value )) {
506
+ bson_free (key );
507
+ bson_free (value );
508
+ return false;
509
+ }
442
510
} else {
443
511
bson_append_utf8 (& uri -> options , key , -1 , value , -1 );
444
512
}
@@ -458,7 +526,7 @@ mongoc_uri_parse_options (mongoc_uri_t *uri,
458
526
char * option ;
459
527
460
528
again :
461
- if ((option = scan_to_unichar (str , '&' , & end_option ))) {
529
+ if ((option = scan_to_unichar (str , '&' , "" , & end_option ))) {
462
530
if (!mongoc_uri_parse_option (uri , option )) {
463
531
bson_free (option );
464
532
return false;
@@ -476,6 +544,32 @@ mongoc_uri_parse_options (mongoc_uri_t *uri,
476
544
}
477
545
478
546
547
+ static bool
548
+ mongoc_uri_finalize_auth (mongoc_uri_t * uri ) {
549
+ bson_iter_t iter ;
550
+ const char * source = NULL ;
551
+ const char * mechanism = mongoc_uri_get_auth_mechanism (uri );
552
+
553
+ if (bson_iter_init_find_case (& iter , & uri -> credentials , "authSource" )) {
554
+ source = bson_iter_utf8 (& iter , NULL );
555
+ }
556
+
557
+ /* authSource with GSSAPI or X509 should always be external */
558
+ if (mechanism ) {
559
+ if (!strcasecmp (mechanism , "GSSAPI" ) ||
560
+ !strcasecmp (mechanism , "MONGODB-X509" )) {
561
+ if (source ) {
562
+ if (strcasecmp (source , "$external" )) {
563
+ return false;
564
+ }
565
+ } else {
566
+ bson_append_utf8 (& uri -> credentials , "authsource" , -1 , "$external" , -1 );
567
+ }
568
+ }
569
+ }
570
+ return true;
571
+ }
572
+
479
573
static bool
480
574
mongoc_uri_parse (mongoc_uri_t * uri ,
481
575
const char * str )
@@ -512,7 +606,7 @@ mongoc_uri_parse (mongoc_uri_t *uri,
512
606
break ;
513
607
}
514
608
515
- return true ;
609
+ return mongoc_uri_finalize_auth ( uri ) ;
516
610
}
517
611
518
612
@@ -540,14 +634,22 @@ mongoc_uri_get_replica_set (const mongoc_uri_t *uri)
540
634
}
541
635
542
636
637
+ const bson_t *
638
+ mongoc_uri_get_credentials (const mongoc_uri_t * uri )
639
+ {
640
+ bson_return_val_if_fail (uri , NULL );
641
+ return & uri -> credentials ;
642
+ }
643
+
644
+
543
645
const char *
544
646
mongoc_uri_get_auth_mechanism (const mongoc_uri_t * uri )
545
647
{
546
648
bson_iter_t iter ;
547
649
548
650
bson_return_val_if_fail (uri , NULL );
549
651
550
- if (bson_iter_init_find_case (& iter , & uri -> options , "authMechanism" ) &&
652
+ if (bson_iter_init_find_case (& iter , & uri -> credentials , "authMechanism" ) &&
551
653
BSON_ITER_HOLDS_UTF8 (& iter )) {
552
654
return bson_iter_utf8 (& iter , NULL );
553
655
}
@@ -556,6 +658,30 @@ mongoc_uri_get_auth_mechanism (const mongoc_uri_t *uri)
556
658
}
557
659
558
660
661
+ bool
662
+ mongoc_uri_get_mechanism_properties (const mongoc_uri_t * uri , bson_t * properties )
663
+ {
664
+ bson_iter_t iter ;
665
+
666
+ if (!uri ) {
667
+ return false;
668
+ }
669
+
670
+ if (bson_iter_init_find_case (& iter , & uri -> credentials , "mechanismProperties" ) &&
671
+ BSON_ITER_HOLDS_DOCUMENT (& iter )) {
672
+ uint32_t len = 0 ;
673
+ const uint8_t * data = NULL ;
674
+
675
+ bson_iter_document (& iter , & len , & data );
676
+ bson_init_static (properties , data , len );
677
+
678
+ return true;
679
+ }
680
+
681
+ return false;
682
+ }
683
+
684
+
559
685
static void
560
686
_mongoc_uri_build_write_concern (mongoc_uri_t * uri ) /* IN */
561
687
{
@@ -636,6 +762,7 @@ mongoc_uri_new (const char *uri_string)
636
762
637
763
uri = bson_malloc0 (sizeof * uri );
638
764
bson_init (& uri -> options );
765
+ bson_init (& uri -> credentials );
639
766
bson_init (& uri -> read_prefs );
640
767
641
768
if (!uri_string ) {
@@ -704,7 +831,7 @@ mongoc_uri_get_auth_source (const mongoc_uri_t *uri)
704
831
705
832
bson_return_val_if_fail (uri , NULL );
706
833
707
- if (bson_iter_init_find_case (& iter , & uri -> options , "authSource" )) {
834
+ if (bson_iter_init_find_case (& iter , & uri -> credentials , "authSource" )) {
708
835
return bson_iter_utf8 (& iter , NULL );
709
836
}
710
837
@@ -736,6 +863,7 @@ mongoc_uri_destroy (mongoc_uri_t *uri)
736
863
bson_free (uri -> database );
737
864
bson_free (uri -> username );
738
865
bson_destroy (& uri -> options );
866
+ bson_destroy (& uri -> credentials );
739
867
bson_destroy (& uri -> read_prefs );
740
868
mongoc_write_concern_destroy (uri -> write_concern );
741
869
@@ -811,7 +939,7 @@ mongoc_uri_unescape (const char *escaped_string)
811
939
if (!bson_utf8_validate (escaped_string , len , false)) {
812
940
MONGOC_WARNING ("%s(): escaped_string contains invalid UTF-8" ,
813
941
__FUNCTION__ );
814
- return false ;
942
+ return NULL ;
815
943
}
816
944
817
945
ptr = escaped_string ;
0 commit comments