Skip to content

Commit 542a330

Browse files
committed
CDRIVER-3408 add to TLS errors on secure transport
1 parent 396ccb2 commit 542a330

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

src/libmongoc/src/mongoc/mongoc-stream-tls-secure-transport.c

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,82 @@ _set_error_from_osstatus (OSStatus status,
438438
CFRelease (err);
439439
}
440440

441+
/* Always returns a string that must be freed. */
442+
static char *
443+
explain_trust_result (SecTrustRef trust, SecTrustResultType trust_result)
444+
{
445+
bson_string_t *reason;
446+
CFArrayRef cfprops = NULL;
447+
CFIndex count, i;
448+
449+
reason = bson_string_new ("");
450+
switch (trust_result) {
451+
case kSecTrustResultDeny:
452+
bson_string_append (reason, "Certificate trust denied");
453+
break;
454+
case kSecTrustResultRecoverableTrustFailure:
455+
bson_string_append (reason, "Certificate trust failure");
456+
break;
457+
case kSecTrustResultFatalTrustFailure:
458+
bson_string_append (reason, "Certificate trust fatal failure");
459+
break;
460+
case kSecTrustResultInvalid:
461+
bson_string_append (reason, "Certificate trust evaluation failure");
462+
break;
463+
default:
464+
bson_string_append_printf (
465+
reason, "Certificate trust failure #%d", (int) trust_result);
466+
break;
467+
}
468+
bson_string_append (reason, ": ");
469+
470+
cfprops = SecTrustCopyProperties (trust);
471+
/* This contains an array of dictionaries, each representing a cert in the
472+
* chain. Append the first failure reason found. */
473+
if (!cfprops) {
474+
bson_string_append (reason, "Unable to retreive cause for trust failure");
475+
goto done;
476+
}
477+
478+
count = CFArrayGetCount (cfprops);
479+
for (i = 0; i < count; ++i) {
480+
const void *elem = NULL;
481+
const void *reason_elem = NULL;
482+
char *reason_str;
483+
CFDictionaryRef dict;
484+
485+
elem = CFArrayGetValueAtIndex (cfprops, i);
486+
if (CFGetTypeID (elem) != CFDictionaryGetTypeID ()) {
487+
bson_string_append (reason, "Unable to parse cause for trust failure");
488+
goto done;
489+
}
490+
491+
dict = (CFDictionaryRef) elem;
492+
reason_elem = CFDictionaryGetValue (dict, kSecPropertyTypeError);
493+
if (!reason_elem) {
494+
continue;
495+
}
496+
if (CFGetTypeID (reason_elem) != CFStringGetTypeID ()) {
497+
bson_string_append (reason, "Unable to parse trust failure error");
498+
goto done;
499+
}
500+
reason_str = _mongoc_cfstringref_to_cstring (reason_elem);
501+
if (reason_str) {
502+
bson_string_append (reason, reason_str);
503+
bson_free (reason_str);
504+
goto done;
505+
} else {
506+
bson_string_append (reason, "Unable to express trust failure error");
507+
goto done;
508+
}
509+
}
510+
511+
bson_string_append (reason, "No trust failure reason available");
512+
done:
513+
CFReleaseSafe (cfprops);
514+
return bson_string_free (reason, false);
515+
}
516+
441517
/* Returns a boolean indicating success. If false is returned, then an error is
442518
* set.
443519
*/
@@ -499,11 +575,13 @@ _verify_peer (mongoc_stream_t *stream, bson_error_t *error)
499575

500576
if (trust_result != kSecTrustResultProceed &&
501577
trust_result != kSecTrustResultUnspecified) {
578+
char *reason = explain_trust_result (trust, trust_result);
502579
bson_set_error (error,
503580
MONGOC_ERROR_STREAM,
504581
MONGOC_ERROR_STREAM_SOCKET,
505-
"TLS handshake failed (%d)",
506-
trust_result);
582+
"TLS handshake failed (%s)",
583+
reason);
584+
bson_free (reason);
507585
goto fail;
508586
}
509587

0 commit comments

Comments
 (0)