summaryrefslogtreecommitdiff
path: root/main/tcptls.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2015-05-15 10:37:58 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2015-05-15 10:37:58 -0500
commite7124a30021bbe9ac90c5cb52b9a806fe42db3fc (patch)
tree0fac76d00e39b6b3ce40e9d4fbdd344996a6b082 /main/tcptls.c
parentc49b0dc2a143c5b75d1e4997f510e766bc0944ee (diff)
parent2415a14ce92885169b514d334370e95aa6273c2b (diff)
Merge "Add X.509 subject alternative name support to TLS certificate verification."
Diffstat (limited to 'main/tcptls.c')
-rw-r--r--main/tcptls.c67
1 files changed, 53 insertions, 14 deletions
diff --git a/main/tcptls.c b/main/tcptls.c
index 8af8501c9..338b8bb36 100644
--- a/main/tcptls.c
+++ b/main/tcptls.c
@@ -555,6 +555,34 @@ static void session_instance_destructor(void *obj)
ao2_cleanup(i->private_data);
}
+#ifdef DO_SSL
+static int check_tcptls_cert_name(ASN1_STRING *cert_str, const char *hostname, const char *desc)
+{
+ unsigned char *str;
+ int ret;
+
+ ret = ASN1_STRING_to_UTF8(&str, cert_str);
+ if (ret < 0 || !str) {
+ return -1;
+ }
+
+ if (strlen((char *) str) != ret) {
+ ast_log(LOG_WARNING, "Invalid certificate %s length (contains NULL bytes?)\n", desc);
+
+ ret = -1;
+ } else if (!strcasecmp(hostname, (char *) str)) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+
+ ast_debug(3, "SSL %s compare s1='%s' s2='%s'\n", desc, hostname, str);
+ OPENSSL_free(str);
+
+ return ret;
+}
+#endif
+
/*! \brief
* creates a FILE * from the fd passed by the accept thread.
* This operation is potentially expensive (certificate verification),
@@ -631,8 +659,8 @@ static void *handle_tcptls_connection(void *data)
}
if (!ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_IGNORE_COMMON_NAME)) {
ASN1_STRING *str;
- unsigned char *str2;
X509_NAME *name = X509_get_subject_name(peer);
+ STACK_OF(GENERAL_NAME) *alt_names;
int pos = -1;
int found = 0;
@@ -643,25 +671,36 @@ static void *handle_tcptls_connection(void *data)
if (pos < 0) {
break;
}
+
str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, pos));
- ret = ASN1_STRING_to_UTF8(&str2, str);
- if (ret < 0) {
- continue;
+ if (!check_tcptls_cert_name(str, tcptls_session->parent->hostname, "common name")) {
+ found = 1;
+ break;
}
+ }
+
+ if (!found) {
+ alt_names = X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
+ if (alt_names != NULL) {
+ int alt_names_count = sk_GENERAL_NAME_num(alt_names);
- if (str2) {
- if (strlen((char *) str2) != ret) {
- ast_log(LOG_WARNING, "Invalid certificate common name length (contains NULL bytes?)\n");
- } else if (!strcasecmp(tcptls_session->parent->hostname, (char *) str2)) {
- found = 1;
+ for (pos = 0; pos < alt_names_count; pos++) {
+ const GENERAL_NAME *alt_name = sk_GENERAL_NAME_value(alt_names, pos);
+
+ if (alt_name->type != GEN_DNS) {
+ continue;
+ }
+
+ if (!check_tcptls_cert_name(alt_name->d.dNSName, tcptls_session->parent->hostname, "alt name")) {
+ found = 1;
+ break;
+ }
}
- ast_debug(3, "SSL Common Name compare s1='%s' s2='%s'\n", tcptls_session->parent->hostname, str2);
- OPENSSL_free(str2);
- }
- if (found) {
- break;
+
+ sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
}
}
+
if (!found) {
ast_log(LOG_ERROR, "Certificate common name did not match (%s)\n", tcptls_session->parent->hostname);
X509_free(peer);