Support verify TLS hostname
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include "util.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/filter.h>
|
||||
#include <netdb.h>
|
||||
@@ -623,6 +624,38 @@ int dns_client_spki_decode(const char *spki, unsigned char *spki_data_out)
|
||||
return spki_data_len;
|
||||
}
|
||||
|
||||
static char *_dns_client_server_get_tls_host_check(struct dns_server_info *server_info)
|
||||
{
|
||||
char *tls_host_check = NULL;
|
||||
|
||||
switch (server_info->type) {
|
||||
case DNS_SERVER_UDP: {
|
||||
} break;
|
||||
case DNS_SERVER_HTTPS: {
|
||||
struct client_dns_server_flag_https *flag_https = &server_info->flags.https;
|
||||
tls_host_check = flag_https->tls_host_check;
|
||||
} break;
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &server_info->flags.tls;
|
||||
tls_host_check = flag_tls->tls_host_check;
|
||||
} break;
|
||||
break;
|
||||
case DNS_SERVER_TCP:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tls_host_check) {
|
||||
if (tls_host_check[0] == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return tls_host_check;
|
||||
}
|
||||
|
||||
static char *_dns_client_server_get_spki(struct dns_server_info *server_info, int *spki_len)
|
||||
{
|
||||
*spki_len = 0;
|
||||
@@ -1874,6 +1907,34 @@ static inline int _dns_client_to_hex(int c)
|
||||
}
|
||||
}
|
||||
|
||||
static int _dns_client_tls_matchName(const char *host, const char *pattern, int size)
|
||||
{
|
||||
int match = -1;
|
||||
int i = 0, j = 0;
|
||||
|
||||
while (i < size && host[j] != '\0') {
|
||||
if (toupper(pattern[i]) == toupper(host[j])) {
|
||||
i++;
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
if (pattern[i] == '*') {
|
||||
while (host[j] != '.' && host[j] != '\0') {
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == size && host[j] == '\0') {
|
||||
match = 0;
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
static int _dns_client_tls_verify(struct dns_server_info *server_info)
|
||||
{
|
||||
X509 *cert = NULL;
|
||||
@@ -1886,6 +1947,7 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
|
||||
unsigned char *key_sha256 = NULL;
|
||||
char *spki = NULL;
|
||||
int spki_len = 0;
|
||||
char *tls_host_check = NULL;
|
||||
|
||||
cert = SSL_get_peer_certificate(server_info->ssl);
|
||||
if (cert == NULL) {
|
||||
@@ -1896,6 +1958,15 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
|
||||
X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, peer_CN, 256);
|
||||
tlog(TLOG_DEBUG, "peer CN: %s", peer_CN);
|
||||
|
||||
/* check tls host */
|
||||
tls_host_check = _dns_client_server_get_tls_host_check(server_info);
|
||||
if (tls_host_check) {
|
||||
if (_dns_client_tls_matchName(peer_CN, tls_host_check, strnlen(tls_host_check, DNS_MAX_CNAME_LEN)) != 0) {
|
||||
tlog(TLOG_INFO, "server %s CN is invalid, peer CN: %s, expect CN: %s", server_info->ip, peer_CN, tls_host_check);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* get spki pin */
|
||||
key_len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
|
||||
if (key_len <= 0) {
|
||||
|
||||
@@ -45,6 +45,7 @@ struct client_dns_server_flag_tls {
|
||||
char spki[DNS_SERVER_SPKI_LEN];
|
||||
int spi_len;
|
||||
char hostname[DNS_MAX_CNAME_LEN];
|
||||
char tls_host_check[DNS_MAX_CNAME_LEN];
|
||||
};
|
||||
|
||||
struct client_dns_server_flag_https {
|
||||
@@ -53,6 +54,7 @@ struct client_dns_server_flag_https {
|
||||
char hostname[DNS_MAX_CNAME_LEN];
|
||||
char httphost[DNS_MAX_CNAME_LEN];
|
||||
char path[DNS_MAX_CNAME_LEN];
|
||||
char tls_host_check[DNS_MAX_CNAME_LEN];
|
||||
};
|
||||
|
||||
struct client_dns_server_flags {
|
||||
|
||||
@@ -181,6 +181,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
{"spki-pin", required_argument, NULL, 'p'}, /* check SPKI pin */
|
||||
{"host-name", required_argument, NULL, 'h'}, /* host name */
|
||||
{"http-host", required_argument, NULL, 'H'}, /* http host */
|
||||
{"tls-host-check", required_argument, NULL, 'V' }, /* check tls hostname */
|
||||
{"group", required_argument, NULL, 'g'}, /* add to group */
|
||||
{"exclude-default-group", no_argument, NULL, 'E'}, /* ecluse this from default group */
|
||||
{NULL, no_argument, NULL, 0}
|
||||
@@ -201,6 +202,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
server->path[0] = '\0';
|
||||
server->hostname[0] = '\0';
|
||||
server->httphost[0] = '\0';
|
||||
server->tls_host_check[0] = '\0';
|
||||
|
||||
ip = argv[1];
|
||||
|
||||
@@ -269,6 +271,10 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
safe_strncpy(server->spki, optarg, DNS_MAX_SPKI_LEN);
|
||||
break;
|
||||
}
|
||||
case 'V': {
|
||||
safe_strncpy(server->tls_host_check, optarg, DNS_MAX_CNAME_LEN);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ struct dns_servers {
|
||||
char spki[DNS_MAX_SPKI_LEN];
|
||||
char hostname[DNS_MAX_CNAME_LEN];
|
||||
char httphost[DNS_MAX_CNAME_LEN];
|
||||
char tls_host_check[DNS_MAX_CNAME_LEN];
|
||||
char path[DNS_MAX_URL_LEN];
|
||||
};
|
||||
|
||||
|
||||
@@ -157,11 +157,13 @@ static int _smartdns_add_servers(void)
|
||||
safe_strncpy(flag_http->hostname, dns_conf_servers[i].hostname, sizeof(flag_http->hostname));
|
||||
safe_strncpy(flag_http->path, dns_conf_servers[i].path, sizeof(flag_http->path));
|
||||
safe_strncpy(flag_http->httphost, dns_conf_servers[i].httphost, sizeof(flag_http->httphost));
|
||||
safe_strncpy(flag_http->tls_host_check, dns_conf_servers[i].tls_host_check, sizeof(flag_http->tls_host_check));
|
||||
} break;
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &flags.tls;
|
||||
flag_tls->spi_len = dns_client_spki_decode(dns_conf_servers[i].spki, (unsigned char *)flag_tls->spki);
|
||||
safe_strncpy(flag_tls->hostname, dns_conf_servers[i].hostname, sizeof(flag_tls->hostname));
|
||||
safe_strncpy(flag_tls->tls_host_check, dns_conf_servers[i].tls_host_check, sizeof(flag_tls->tls_host_check));
|
||||
} break;
|
||||
break;
|
||||
case DNS_SERVER_TCP:
|
||||
|
||||
Reference in New Issue
Block a user