2018-04-20 01:11:55 +08:00
|
|
|
/*
|
2018-04-20 01:19:50 +08:00
|
|
|
* FDBLibTLSSession.cpp
|
2018-04-20 01:11:55 +08:00
|
|
|
*
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
*
|
|
|
|
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
2018-04-13 03:28:52 +08:00
|
|
|
|
2018-10-20 09:53:09 +08:00
|
|
|
#include "FDBLibTLS/FDBLibTLSSession.h"
|
2019-05-21 06:12:28 +08:00
|
|
|
|
|
|
|
#include "flow/flow.h"
|
2018-10-20 09:53:09 +08:00
|
|
|
#include "flow/Trace.h"
|
2018-04-13 03:28:52 +08:00
|
|
|
|
|
|
|
#include <openssl/bio.h>
|
2018-05-09 07:27:21 +08:00
|
|
|
#include <openssl/err.h>
|
2018-04-13 03:28:52 +08:00
|
|
|
#include <openssl/pem.h>
|
|
|
|
#include <openssl/x509.h>
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
#include <openssl/x509v3.h>
|
2018-05-09 07:27:21 +08:00
|
|
|
#include <openssl/x509_vfy.h>
|
2018-04-13 03:28:52 +08:00
|
|
|
|
|
|
|
#include <exception>
|
|
|
|
|
2018-05-24 06:32:56 +08:00
|
|
|
#include <set>
|
2018-04-13 03:28:52 +08:00
|
|
|
#include <string.h>
|
|
|
|
#include <limits.h>
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
static ssize_t tls_read_func(struct tls* ctx, void* buf, size_t buflen, void* cb_arg) {
|
|
|
|
FDBLibTLSSession* session = (FDBLibTLSSession*)cb_arg;
|
2018-04-13 03:28:52 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
int rv = session->recv_func(session->recv_ctx, (uint8_t*)buf, buflen);
|
2018-04-13 03:28:52 +08:00
|
|
|
if (rv < 0)
|
|
|
|
return 0;
|
|
|
|
if (rv == 0)
|
|
|
|
return TLS_WANT_POLLIN;
|
|
|
|
return (ssize_t)rv;
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
static ssize_t tls_write_func(struct tls* ctx, const void* buf, size_t buflen, void* cb_arg) {
|
|
|
|
FDBLibTLSSession* session = (FDBLibTLSSession*)cb_arg;
|
2018-04-13 03:28:52 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
int rv = session->send_func(session->send_ctx, (const uint8_t*)buf, buflen);
|
2018-04-13 03:28:52 +08:00
|
|
|
if (rv < 0)
|
|
|
|
return 0;
|
|
|
|
if (rv == 0)
|
|
|
|
return TLS_WANT_POLLOUT;
|
|
|
|
return (ssize_t)rv;
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
FDBLibTLSSession::FDBLibTLSSession(Reference<FDBLibTLSPolicy> policy,
|
|
|
|
bool is_client,
|
|
|
|
const char* servername,
|
|
|
|
TLSSendCallbackFunc send_func,
|
|
|
|
void* send_ctx,
|
|
|
|
TLSRecvCallbackFunc recv_func,
|
|
|
|
void* recv_ctx,
|
|
|
|
void* uidptr)
|
2020-11-24 10:58:46 +08:00
|
|
|
: tls_ctx(nullptr), tls_sctx(nullptr), is_client(is_client), policy(policy), send_func(send_func), send_ctx(send_ctx),
|
|
|
|
recv_func(recv_func), recv_ctx(recv_ctx), handshake_completed(false), lastVerifyFailureLogged(0.0) {
|
2018-07-13 04:24:40 +08:00
|
|
|
if (uidptr)
|
2021-03-11 02:06:03 +08:00
|
|
|
uid = *(UID*)uidptr;
|
2018-04-13 03:28:52 +08:00
|
|
|
|
|
|
|
if (is_client) {
|
2020-11-24 10:58:46 +08:00
|
|
|
if ((tls_ctx = tls_client()) == nullptr) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSClientError", uid);
|
2018-04-13 03:28:52 +08:00
|
|
|
throw std::runtime_error("FDBLibTLSClientError");
|
|
|
|
}
|
|
|
|
if (tls_configure(tls_ctx, policy->tls_cfg) == -1) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSConfigureError", uid).detail("LibTLSErrorMessage", tls_error(tls_ctx));
|
2018-04-13 03:28:52 +08:00
|
|
|
tls_free(tls_ctx);
|
|
|
|
throw std::runtime_error("FDBLibTLSConfigureError");
|
|
|
|
}
|
2018-05-09 07:27:21 +08:00
|
|
|
if (tls_connect_cbs(tls_ctx, tls_read_func, tls_write_func, this, servername) == -1) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSConnectError", uid).detail("LibTLSErrorMessage", tls_error(tls_ctx));
|
2018-04-13 03:28:52 +08:00
|
|
|
tls_free(tls_ctx);
|
|
|
|
throw std::runtime_error("FDBLibTLSConnectError");
|
|
|
|
}
|
|
|
|
} else {
|
2020-11-24 10:58:46 +08:00
|
|
|
if ((tls_sctx = tls_server()) == nullptr) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSServerError", uid);
|
2018-04-13 03:28:52 +08:00
|
|
|
throw std::runtime_error("FDBLibTLSServerError");
|
|
|
|
}
|
|
|
|
if (tls_configure(tls_sctx, policy->tls_cfg) == -1) {
|
2018-08-10 05:49:29 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSConfigureError", uid).detail("LibTLSErrorMessage", tls_error(tls_sctx));
|
2018-04-13 03:28:52 +08:00
|
|
|
tls_free(tls_sctx);
|
|
|
|
throw std::runtime_error("FDBLibTLSConfigureError");
|
|
|
|
}
|
|
|
|
if (tls_accept_cbs(tls_sctx, &tls_ctx, tls_read_func, tls_write_func, this) == -1) {
|
2018-08-10 05:49:29 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSAcceptError", uid).detail("LibTLSErrorMessage", tls_error(tls_sctx));
|
2018-04-13 03:28:52 +08:00
|
|
|
tls_free(tls_sctx);
|
|
|
|
throw std::runtime_error("FDBLibTLSAcceptError");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FDBLibTLSSession::~FDBLibTLSSession() {
|
|
|
|
// This would ideally call tls_close(), however that means either looping
|
|
|
|
// in a destructor or doing it opportunistically...
|
|
|
|
tls_free(tls_ctx);
|
|
|
|
tls_free(tls_sctx);
|
|
|
|
}
|
|
|
|
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
bool match_criteria_entry(const std::string& criteria, ASN1_STRING* entry, MatchType mt) {
|
2018-04-13 03:28:52 +08:00
|
|
|
bool rc = false;
|
2020-11-24 10:58:46 +08:00
|
|
|
ASN1_STRING* asn_criteria = nullptr;
|
|
|
|
unsigned char* criteria_utf8 = nullptr;
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
int criteria_utf8_len = 0;
|
2020-11-24 10:58:46 +08:00
|
|
|
unsigned char* entry_utf8 = nullptr;
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
int entry_utf8_len = 0;
|
2018-04-13 03:28:52 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
if ((asn_criteria = ASN1_IA5STRING_new()) == nullptr)
|
|
|
|
goto err;
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
if (ASN1_STRING_set(asn_criteria, criteria.c_str(), criteria.size()) != 1)
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
if ((criteria_utf8_len = ASN1_STRING_to_UTF8(&criteria_utf8, asn_criteria)) < 1)
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
if ((entry_utf8_len = ASN1_STRING_to_UTF8(&entry_utf8, entry)) < 1)
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
2018-06-28 09:06:24 +08:00
|
|
|
if (mt == MatchType::EXACT) {
|
2021-03-11 02:06:03 +08:00
|
|
|
if (criteria_utf8_len == entry_utf8_len && memcmp(criteria_utf8, entry_utf8, criteria_utf8_len) == 0)
|
2018-06-28 09:06:24 +08:00
|
|
|
rc = true;
|
|
|
|
} else if (mt == MatchType::PREFIX) {
|
2021-03-11 02:06:03 +08:00
|
|
|
if (criteria_utf8_len <= entry_utf8_len && memcmp(criteria_utf8, entry_utf8, criteria_utf8_len) == 0)
|
2018-06-28 09:06:24 +08:00
|
|
|
rc = true;
|
|
|
|
} else if (mt == MatchType::SUFFIX) {
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
if (criteria_utf8_len <= entry_utf8_len &&
|
|
|
|
memcmp(criteria_utf8, entry_utf8 + (entry_utf8_len - criteria_utf8_len), criteria_utf8_len) == 0)
|
2018-06-28 09:06:24 +08:00
|
|
|
rc = true;
|
|
|
|
}
|
2018-04-13 03:28:52 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
err:
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
ASN1_STRING_free(asn_criteria);
|
2018-04-13 03:28:52 +08:00
|
|
|
free(criteria_utf8);
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
free(entry_utf8);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
bool match_name_criteria(X509_NAME* name, NID nid, const std::string& criteria, MatchType mt) {
|
|
|
|
X509_NAME_ENTRY* name_entry;
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
int idx;
|
|
|
|
|
|
|
|
// If name does not exist, or has multiple of this RDN, refuse to proceed.
|
|
|
|
if ((idx = X509_NAME_get_index_by_NID(name, nid, -1)) < 0)
|
|
|
|
return false;
|
|
|
|
if (X509_NAME_get_index_by_NID(name, nid, idx) != -1)
|
|
|
|
return false;
|
2021-03-11 02:06:03 +08:00
|
|
|
if ((name_entry = X509_NAME_get_entry(name, idx)) == nullptr)
|
|
|
|
return false;
|
2018-04-13 03:28:52 +08:00
|
|
|
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
return match_criteria_entry(criteria, name_entry->value, mt);
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
bool match_extension_criteria(X509* cert, NID nid, const std::string& value, MatchType mt) {
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
if (nid != NID_subject_alt_name && nid != NID_issuer_alt_name) {
|
|
|
|
// I have no idea how other extensions work.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto pos = value.find(':');
|
|
|
|
if (pos == value.npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
std::string value_gen = value.substr(0, pos);
|
2021-03-11 02:06:03 +08:00
|
|
|
std::string value_val = value.substr(pos + 1, value.npos);
|
2020-11-24 10:58:46 +08:00
|
|
|
STACK_OF(GENERAL_NAME)* sans =
|
|
|
|
reinterpret_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i(cert, nid, nullptr, nullptr));
|
|
|
|
if (sans == nullptr) {
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
return false;
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
int num_sans = sk_GENERAL_NAME_num(sans);
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
bool rc = false;
|
2021-03-11 02:06:03 +08:00
|
|
|
for (int i = 0; i < num_sans && !rc; ++i) {
|
|
|
|
GENERAL_NAME* altname = sk_GENERAL_NAME_value(sans, i);
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
std::string matchable;
|
|
|
|
switch (altname->type) {
|
|
|
|
case GEN_OTHERNAME:
|
|
|
|
break;
|
|
|
|
case GEN_EMAIL:
|
2021-03-11 02:06:03 +08:00
|
|
|
if (value_gen == "EMAIL" && match_criteria_entry(value_val, altname->d.rfc822Name, mt)) {
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
rc = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GEN_DNS:
|
2021-03-11 02:06:03 +08:00
|
|
|
if (value_gen == "DNS" && match_criteria_entry(value_val, altname->d.dNSName, mt)) {
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
rc = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GEN_X400:
|
|
|
|
case GEN_DIRNAME:
|
|
|
|
case GEN_EDIPARTY:
|
|
|
|
break;
|
|
|
|
case GEN_URI:
|
2021-03-11 02:06:03 +08:00
|
|
|
if (value_gen == "URI" && match_criteria_entry(value_val, altname->d.uniformResourceIdentifier, mt)) {
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
rc = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GEN_IPADD:
|
2021-03-11 02:06:03 +08:00
|
|
|
if (value_gen == "IP" && match_criteria_entry(value_val, altname->d.iPAddress, mt)) {
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
rc = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GEN_RID:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sk_GENERAL_NAME_pop_free(sans, GENERAL_NAME_free);
|
2018-04-13 03:28:52 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
bool match_criteria(X509* cert,
|
|
|
|
X509_NAME* subject,
|
|
|
|
NID nid,
|
|
|
|
const std::string& criteria,
|
|
|
|
MatchType mt,
|
|
|
|
X509Location loc) {
|
|
|
|
switch (loc) {
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
case X509Location::NAME: {
|
|
|
|
return match_name_criteria(subject, nid, criteria, mt);
|
|
|
|
}
|
|
|
|
case X509Location::EXTENSION: {
|
|
|
|
return match_extension_criteria(cert, nid, criteria, mt);
|
|
|
|
}
|
|
|
|
}
|
2018-07-03 05:30:37 +08:00
|
|
|
// Should never be reachable.
|
|
|
|
return false;
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
std::tuple<bool, std::string> FDBLibTLSSession::check_verify(Reference<FDBLibTLSVerify> verify,
|
|
|
|
struct stack_st_X509* certs) {
|
2020-11-24 10:58:46 +08:00
|
|
|
X509_STORE_CTX* store_ctx = nullptr;
|
2018-04-13 03:28:52 +08:00
|
|
|
X509_NAME *subject, *issuer;
|
|
|
|
bool rc = false;
|
2020-11-24 10:58:46 +08:00
|
|
|
X509* cert = nullptr;
|
2018-05-24 06:32:56 +08:00
|
|
|
// if returning false, give a reason string
|
|
|
|
std::string reason = "";
|
2018-04-13 03:28:52 +08:00
|
|
|
|
|
|
|
// If certificate verification is disabled, there's nothing more to do.
|
2018-05-09 07:27:21 +08:00
|
|
|
if (!verify->verify_cert)
|
2018-05-24 06:32:56 +08:00
|
|
|
return std::make_tuple(true, reason);
|
2018-04-13 03:28:52 +08:00
|
|
|
|
2018-05-09 07:27:21 +08:00
|
|
|
// Verify the certificate.
|
2020-11-24 10:58:46 +08:00
|
|
|
if ((store_ctx = X509_STORE_CTX_new()) == nullptr) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSOutOfMemory", uid);
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Out of memory";
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2020-11-24 10:58:46 +08:00
|
|
|
if (!X509_STORE_CTX_init(store_ctx, nullptr, sk_X509_value(certs, 0), certs)) {
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Store ctx init";
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2018-05-09 07:27:21 +08:00
|
|
|
X509_STORE_CTX_trusted_stack(store_ctx, policy->roots);
|
2018-05-24 06:32:56 +08:00
|
|
|
X509_STORE_CTX_set_default(store_ctx, is_client ? "ssl_server" : "ssl_client");
|
2018-05-09 07:27:21 +08:00
|
|
|
if (!verify->verify_time)
|
|
|
|
X509_VERIFY_PARAM_set_flags(X509_STORE_CTX_get0_param(store_ctx), X509_V_FLAG_NO_CHECK_TIME);
|
|
|
|
if (X509_verify_cert(store_ctx) <= 0) {
|
2021-03-11 02:06:03 +08:00
|
|
|
const char* errstr = X509_verify_cert_error_string(X509_STORE_CTX_get_error(store_ctx));
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Verify cert error: " + std::string(errstr);
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check subject criteria.
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
cert = sk_X509_value(store_ctx->chain, 0);
|
2020-11-24 10:58:46 +08:00
|
|
|
if ((subject = X509_get_subject_name(cert)) == nullptr) {
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Cert subject error";
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
for (auto& pair : verify->subject_criteria) {
|
|
|
|
if (!match_criteria(
|
|
|
|
cert, subject, pair.first, pair.second.criteria, pair.second.match_type, pair.second.location)) {
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Cert subject match failure";
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2018-05-09 07:27:21 +08:00
|
|
|
}
|
2018-04-13 03:28:52 +08:00
|
|
|
|
|
|
|
// Check issuer criteria.
|
2020-11-24 10:58:46 +08:00
|
|
|
if ((issuer = X509_get_issuer_name(cert)) == nullptr) {
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Cert issuer error";
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
for (auto& pair : verify->issuer_criteria) {
|
|
|
|
if (!match_criteria(
|
|
|
|
cert, issuer, pair.first, pair.second.criteria, pair.second.match_type, pair.second.location)) {
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Cert issuer match failure";
|
2018-04-13 03:28:52 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2018-05-09 07:27:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check root criteria - this is the subject of the final certificate in the stack.
|
Fix Subject Alternative Name matching and add test cases.
The previous change was done in the optimistic hope that NID_subject_alt_name
could be handled in the same fashion as all the rest of the attributes we match
against. However, X509 is not a place for optimisim. Instead, it turns out
that the Subject Alternative Name is an X509v3 extension, and needs to be
handled separately.
Therefore, this change...
* Introduces the idea of Criteria matching against a location in the
certificate, and not just against the entirety of the certificate.
* Extracts the Subject Alternative Name extension, and allows iteration and
matching against its components.
* Extends our constraint language to sensibly match against SubjectAlternativeNames.
The `S.subjectAltName` syntax has been kept, but the value is now required to
provide what type of field the rest of the value is intended to match against.
The code currently supports DNS, EMAIL, URI, and IP. Prefix and suffix
matching is supported.
Both verify-test and plugin-test were updated to cover Subject Alternative Name
matching. I've additionally run plugin-test under valgrind to verify that I've
understood object lifetimes correctly.
2018-06-30 08:10:27 +08:00
|
|
|
cert = sk_X509_value(store_ctx->chain, sk_X509_num(store_ctx->chain) - 1);
|
2020-11-24 10:58:46 +08:00
|
|
|
if ((subject = X509_get_subject_name(cert)) == nullptr) {
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Root subject error";
|
2018-05-09 07:27:21 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
for (auto& pair : verify->root_criteria) {
|
|
|
|
if (!match_criteria(
|
|
|
|
cert, subject, pair.first, pair.second.criteria, pair.second.match_type, pair.second.location)) {
|
2019-05-11 05:51:20 +08:00
|
|
|
reason = "Root subject match failure";
|
2018-05-09 07:27:21 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2018-04-13 03:28:52 +08:00
|
|
|
|
|
|
|
// If we got this far, everything checked out...
|
|
|
|
rc = true;
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
err:
|
2018-05-09 07:27:21 +08:00
|
|
|
X509_STORE_CTX_free(store_ctx);
|
|
|
|
|
2018-05-24 06:32:56 +08:00
|
|
|
return std::make_tuple(rc, reason);
|
2018-05-09 07:27:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FDBLibTLSSession::verify_peer() {
|
2020-11-24 10:58:46 +08:00
|
|
|
struct stack_st_X509* certs = nullptr;
|
2021-03-11 02:06:03 +08:00
|
|
|
const uint8_t* cert_pem;
|
2018-05-09 07:27:21 +08:00
|
|
|
size_t cert_pem_len;
|
|
|
|
bool rc = false;
|
2018-05-24 06:32:56 +08:00
|
|
|
std::set<std::string> verify_failure_reasons;
|
|
|
|
bool verify_success;
|
|
|
|
std::string verify_failure_reason;
|
2018-05-09 07:27:21 +08:00
|
|
|
|
|
|
|
// If no verify peer rules have been set, we are relying on standard
|
|
|
|
// libtls verification.
|
|
|
|
if (policy->verify_rules.empty())
|
|
|
|
return true;
|
|
|
|
|
2020-11-24 10:58:46 +08:00
|
|
|
if ((cert_pem = tls_peer_cert_chain_pem(tls_ctx, &cert_pem_len)) == nullptr) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSNoCertError", uid);
|
2018-05-09 07:27:21 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
if ((certs = policy->parse_cert_pem(cert_pem, cert_pem_len)) == nullptr)
|
|
|
|
goto err;
|
2018-05-09 07:27:21 +08:00
|
|
|
|
|
|
|
// Any matching rule is sufficient.
|
2021-03-11 02:06:03 +08:00
|
|
|
for (auto& verify_rule : policy->verify_rules) {
|
2018-05-24 06:32:56 +08:00
|
|
|
std::tie(verify_success, verify_failure_reason) = check_verify(verify_rule, certs);
|
|
|
|
if (verify_success) {
|
2018-05-09 07:27:21 +08:00
|
|
|
rc = true;
|
|
|
|
break;
|
2018-05-24 06:32:56 +08:00
|
|
|
} else {
|
|
|
|
if (verify_failure_reason.length() > 0)
|
|
|
|
verify_failure_reasons.insert(verify_failure_reason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rc) {
|
|
|
|
// log the various failure reasons
|
2021-03-11 02:06:03 +08:00
|
|
|
if (now() - lastVerifyFailureLogged > 1.0) {
|
2019-05-21 06:12:28 +08:00
|
|
|
for (std::string reason : verify_failure_reasons) {
|
|
|
|
lastVerifyFailureLogged = now();
|
2020-01-11 08:19:41 +08:00
|
|
|
TraceEvent("FDBLibTLSVerifyFailure", uid).suppressFor(1.0).detail("Reason", reason);
|
2019-05-21 06:12:28 +08:00
|
|
|
}
|
2018-05-09 07:27:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
err:
|
2018-05-09 07:27:21 +08:00
|
|
|
sk_X509_pop_free(certs, X509_free);
|
2018-04-13 03:28:52 +08:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int FDBLibTLSSession::handshake() {
|
|
|
|
int rv = tls_handshake(tls_ctx);
|
|
|
|
|
|
|
|
switch (rv) {
|
|
|
|
case 0:
|
2018-05-09 07:27:21 +08:00
|
|
|
if (!verify_peer())
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
handshake_completed = true;
|
|
|
|
return SUCCESS;
|
|
|
|
case TLS_WANT_POLLIN:
|
|
|
|
return WANT_READ;
|
|
|
|
case TLS_WANT_POLLOUT:
|
|
|
|
return WANT_WRITE;
|
|
|
|
default:
|
2018-08-02 05:30:57 +08:00
|
|
|
TraceEvent("FDBLibTLSHandshakeError", uid).suppressFor(1.0).detail("LibTLSErrorMessage", tls_error(tls_ctx));
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int FDBLibTLSSession::read(uint8_t* data, int length) {
|
|
|
|
if (!handshake_completed) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSReadHandshakeError");
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t n = tls_read(tls_ctx, data, length);
|
|
|
|
if (n > 0) {
|
|
|
|
if (n > INT_MAX) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSReadOverflow");
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
return (int)n;
|
|
|
|
}
|
|
|
|
if (n == 0) {
|
2018-08-02 05:30:57 +08:00
|
|
|
TraceEvent("FDBLibTLSReadEOF").suppressFor(1.0);
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
if (n == TLS_WANT_POLLIN)
|
|
|
|
return WANT_READ;
|
|
|
|
if (n == TLS_WANT_POLLOUT)
|
|
|
|
return WANT_WRITE;
|
|
|
|
|
2018-08-02 05:30:57 +08:00
|
|
|
TraceEvent("FDBLibTLSReadError", uid).suppressFor(1.0).detail("LibTLSErrorMessage", tls_error(tls_ctx));
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
int FDBLibTLSSession::write(const uint8_t* data, int length) {
|
|
|
|
if (!handshake_completed) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSWriteHandshakeError", uid);
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t n = tls_write(tls_ctx, data, length);
|
|
|
|
if (n > 0) {
|
|
|
|
if (n > INT_MAX) {
|
2018-07-13 04:24:40 +08:00
|
|
|
TraceEvent(SevError, "FDBLibTLSWriteOverflow", uid);
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
return (int)n;
|
|
|
|
}
|
|
|
|
if (n == 0) {
|
2018-08-02 05:30:57 +08:00
|
|
|
TraceEvent("FDBLibTLSWriteEOF", uid).suppressFor(1.0);
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|
|
|
|
if (n == TLS_WANT_POLLIN)
|
|
|
|
return WANT_READ;
|
|
|
|
if (n == TLS_WANT_POLLOUT)
|
|
|
|
return WANT_WRITE;
|
|
|
|
|
2018-08-02 05:30:57 +08:00
|
|
|
TraceEvent("FDBLibTLSWriteError", uid).suppressFor(1.0).detail("LibTLSErrorMessage", tls_error(tls_ctx));
|
2018-04-13 03:28:52 +08:00
|
|
|
return FAILED;
|
|
|
|
}
|