Skip to content

Commit eff245d

Browse files
samantharitterhanumantmk
authored andcommitted
CDRIVER-437 Add authMechanismProperties to URI
Closes #111
1 parent 26c1e52 commit eff245d

File tree

5 files changed

+307
-52
lines changed

5 files changed

+307
-52
lines changed

build/cmake/libmongoc-ssl.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,10 @@ mongoc_uri_copy
182182
mongoc_uri_destroy
183183
mongoc_uri_get_auth_mechanism
184184
mongoc_uri_get_auth_source
185+
mongoc_uri_get_credentials
185186
mongoc_uri_get_database
186187
mongoc_uri_get_hosts
188+
mongoc_uri_get_mechanism_properties
187189
mongoc_uri_get_options
188190
mongoc_uri_get_password
189191
mongoc_uri_get_read_prefs

src/libmongoc.symbols

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,10 @@ mongoc_uri_copy
191191
mongoc_uri_destroy
192192
mongoc_uri_get_auth_mechanism
193193
mongoc_uri_get_auth_source
194+
mongoc_uri_get_credentials
194195
mongoc_uri_get_database
195196
mongoc_uri_get_hosts
197+
mongoc_uri_get_mechanism_properties
196198
mongoc_uri_get_options
197199
mongoc_uri_get_password
198200
mongoc_uri_get_read_prefs

src/mongoc/mongoc-uri.c

Lines changed: 151 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ struct _mongoc_uri_t
3939
char *password;
4040
char *database;
4141
bson_t options;
42+
bson_t credentials;
4243
bson_t read_prefs;
4344
mongoc_write_concern_t *write_concern;
4445
};
4546

46-
4747
static void
4848
mongoc_uri_do_unescape (char **str)
4949
{
@@ -86,27 +86,55 @@ mongoc_uri_append_host (mongoc_uri_t *uri,
8686
}
8787
}
8888

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+
*/
89110

90111
static char *
91112
scan_to_unichar (const char *str,
92-
bson_unichar_t stop,
113+
bson_unichar_t match,
114+
const char *terminators,
93115
const char **end)
94116
{
95117
bson_unichar_t c;
96118
const char *iter;
97119

98120
for (iter = str;
99121
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) {
103124
*end = iter;
104125
return bson_strndup(str, iter - str);
105126
} else if (c == '\\') {
106127
iter = bson_utf8_next_char(iter);
107128
if (!bson_utf8_get_char(iter)) {
108129
break;
109130
}
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+
}
110138
}
111139
}
112140

@@ -138,8 +166,8 @@ mongoc_uri_parse_userpass (mongoc_uri_t *uri,
138166
const char *end_user;
139167
char *s;
140168

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))) {
143171
uri->password = bson_strdup(end_user + 1);
144172
} else {
145173
uri->username = bson_strndup(str, end_userpass - str);
@@ -175,7 +203,7 @@ mongoc_uri_parse_host6 (mongoc_uri_t *uri,
175203
#endif
176204
}
177205

178-
hostname = scan_to_unichar (str + 1, ']', &end_host);
206+
hostname = scan_to_unichar (str + 1, ']', "", &end_host);
179207

180208
mongoc_uri_do_unescape (&hostname);
181209
mongoc_uri_append_host (uri, hostname, port);
@@ -197,7 +225,7 @@ mongoc_uri_parse_host (mongoc_uri_t *uri,
197225
return mongoc_uri_parse_host6 (uri, str);
198226
}
199227

200-
if ((hostname = scan_to_unichar(str, ':', &end_host))) {
228+
if ((hostname = scan_to_unichar(str, ':', "?/,", &end_host))) {
201229
end_host++;
202230
if (!isdigit(*end_host)) {
203231
bson_free(hostname);
@@ -234,7 +262,7 @@ _mongoc_host_list_from_string (mongoc_host_list_t *host_list,
234262

235263
memset(host_list, 0, sizeof *host_list);
236264

237-
if ((hostname = scan_to_unichar(host_and_port, ':', &end_host))) {
265+
if ((hostname = scan_to_unichar(host_and_port, ':', "", &end_host))) {
238266
end_host++;
239267
if (!isdigit(*end_host)) {
240268
bson_free(hostname);
@@ -305,7 +333,7 @@ mongoc_uri_parse_hosts (mongoc_uri_t *uri,
305333
str++;
306334
goto again;
307335
}
308-
} else if ((s = scan_to_unichar(str, ',', &end_hostport))) {
336+
} else if ((s = scan_to_unichar(str, ',', "/", &end_hostport))) {
309337
if (!mongoc_uri_parse_host(uri, s)) {
310338
bson_free(s);
311339
return false;
@@ -314,8 +342,8 @@ mongoc_uri_parse_hosts (mongoc_uri_t *uri,
314342
str = end_hostport + 1;
315343
ret = true;
316344
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))) {
319347
if (!mongoc_uri_parse_host(uri, s)) {
320348
bson_free(s);
321349
return false;
@@ -342,7 +370,7 @@ mongoc_uri_parse_database (mongoc_uri_t *uri,
342370
{
343371
const char *end_database;
344372

345-
if ((uri->database = scan_to_unichar(str, '?', &end_database))) {
373+
if ((uri->database = scan_to_unichar(str, '?', "", &end_database))) {
346374
*end = end_database;
347375
} else if (*str) {
348376
uri->database = bson_strdup(str);
@@ -355,6 +383,37 @@ mongoc_uri_parse_database (mongoc_uri_t *uri,
355383
}
356384

357385

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+
358417
static void
359418
mongoc_uri_parse_tags (mongoc_uri_t *uri, /* IN */
360419
const char *str, /* IN */
@@ -371,16 +430,16 @@ mongoc_uri_parse_tags (mongoc_uri_t *uri, /* IN */
371430
bson_init(&b);
372431

373432
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))) {
376435
bson_append_utf8(&b, key, -1, end_key + 1, -1);
377436
bson_free(key);
378437
}
379438
bson_free(keyval);
380439
str = end_keyval + 1;
381440
goto again;
382441
} else {
383-
if ((key = scan_to_unichar(str, ':', &end_key))) {
442+
if ((key = scan_to_unichar(str, ':', "", &end_key))) {
384443
bson_append_utf8(&b, key, -1, end_key + 1, -1);
385444
bson_free(key);
386445
}
@@ -402,7 +461,7 @@ mongoc_uri_parse_option (mongoc_uri_t *uri,
402461
char *key;
403462
char *value;
404463

405-
if (!(key = scan_to_unichar(str, '=', &end_key))) {
464+
if (!(key = scan_to_unichar(str, '=', "", &end_key))) {
406465
return false;
407466
}
408467

@@ -439,6 +498,15 @@ mongoc_uri_parse_option (mongoc_uri_t *uri,
439498
(0 == strcmp (value, "1")));
440499
} else if (!strcasecmp(key, "readpreferencetags")) {
441500
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+
}
442510
} else {
443511
bson_append_utf8(&uri->options, key, -1, value, -1);
444512
}
@@ -458,7 +526,7 @@ mongoc_uri_parse_options (mongoc_uri_t *uri,
458526
char *option;
459527

460528
again:
461-
if ((option = scan_to_unichar(str, '&', &end_option))) {
529+
if ((option = scan_to_unichar(str, '&', "", &end_option))) {
462530
if (!mongoc_uri_parse_option(uri, option)) {
463531
bson_free(option);
464532
return false;
@@ -476,6 +544,32 @@ mongoc_uri_parse_options (mongoc_uri_t *uri,
476544
}
477545

478546

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+
479573
static bool
480574
mongoc_uri_parse (mongoc_uri_t *uri,
481575
const char *str)
@@ -512,7 +606,7 @@ mongoc_uri_parse (mongoc_uri_t *uri,
512606
break;
513607
}
514608

515-
return true;
609+
return mongoc_uri_finalize_auth(uri);
516610
}
517611

518612

@@ -540,14 +634,22 @@ mongoc_uri_get_replica_set (const mongoc_uri_t *uri)
540634
}
541635

542636

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+
543645
const char *
544646
mongoc_uri_get_auth_mechanism (const mongoc_uri_t *uri)
545647
{
546648
bson_iter_t iter;
547649

548650
bson_return_val_if_fail (uri, NULL);
549651

550-
if (bson_iter_init_find_case (&iter, &uri->options, "authMechanism") &&
652+
if (bson_iter_init_find_case (&iter, &uri->credentials, "authMechanism") &&
551653
BSON_ITER_HOLDS_UTF8 (&iter)) {
552654
return bson_iter_utf8 (&iter, NULL);
553655
}
@@ -556,6 +658,30 @@ mongoc_uri_get_auth_mechanism (const mongoc_uri_t *uri)
556658
}
557659

558660

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+
559685
static void
560686
_mongoc_uri_build_write_concern (mongoc_uri_t *uri) /* IN */
561687
{
@@ -636,6 +762,7 @@ mongoc_uri_new (const char *uri_string)
636762

637763
uri = bson_malloc0(sizeof *uri);
638764
bson_init(&uri->options);
765+
bson_init(&uri->credentials);
639766
bson_init(&uri->read_prefs);
640767

641768
if (!uri_string) {
@@ -704,7 +831,7 @@ mongoc_uri_get_auth_source (const mongoc_uri_t *uri)
704831

705832
bson_return_val_if_fail(uri, NULL);
706833

707-
if (bson_iter_init_find_case(&iter, &uri->options, "authSource")) {
834+
if (bson_iter_init_find_case(&iter, &uri->credentials, "authSource")) {
708835
return bson_iter_utf8(&iter, NULL);
709836
}
710837

@@ -736,6 +863,7 @@ mongoc_uri_destroy (mongoc_uri_t *uri)
736863
bson_free(uri->database);
737864
bson_free(uri->username);
738865
bson_destroy(&uri->options);
866+
bson_destroy(&uri->credentials);
739867
bson_destroy(&uri->read_prefs);
740868
mongoc_write_concern_destroy(uri->write_concern);
741869

@@ -811,7 +939,7 @@ mongoc_uri_unescape (const char *escaped_string)
811939
if (!bson_utf8_validate(escaped_string, len, false)) {
812940
MONGOC_WARNING("%s(): escaped_string contains invalid UTF-8",
813941
__FUNCTION__);
814-
return false;
942+
return NULL;
815943
}
816944

817945
ptr = escaped_string;

0 commit comments

Comments
 (0)