From 3678757fed68a5814d529619aee491f17fb654c7 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Mon, 12 Jun 2023 19:23:09 +0200 Subject: [PATCH] Do not take IP address as SNI parameter --- CHANGES | 4 ++++ sysutils.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ sysutils.h | 3 +++ xio-openssl.c | 7 +++++- 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 57576a7..978dea5 100644 --- a/CHANGES +++ b/CHANGES @@ -45,6 +45,10 @@ Corrections: Thanks to Gordon W.Ross for reporting and fixing this issue. Test: RESTORE_TTY + The OpenSSL client SNI parameter, when not explicitely specified, is + derived from option commonname or rom target server name. This is not + useful with IP addresses, which Socat now checks and avoids. + Features: VSOCK, VSOCK-L support options pf, socktype, prototype (currently useless) diff --git a/sysutils.c b/sysutils.c index 32e4ba3..a691659 100644 --- a/sysutils.c +++ b/sysutils.c @@ -457,6 +457,72 @@ char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen } #endif /* WITH_IP6 */ + +#if WITH_IP4 +/* Checks if the given string is an IPv4 address. + Returns 0 when it is an address. + Returns 1 when it is not an address. + Returns -1 when an error occurred (bad regex - internal) */ +int check_ip4addr( + const char *address) +{ +#if HAVE_REGEX_H + regex_t preg; + if (regcomp(&preg, "^(25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])\\.(25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])\\.(25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])\\.(25[0-5]|(2[0-4]|1[0-9]|[1-9]?)[0-9])$", REG_EXTENDED|REG_NOSUB) + != 0) { + return -1; /* do not handle, just state that no match */ + } + if (regexec(&preg, address, 0, NULL, 0) == 0) { + return 0; + } +#endif /* HAVE_REGEX_H */ + /* Fallback when no regexec() compiled in */ + return 1; +} +#endif /* WITH_IP4 */ + +#if WITH_IP6 +/* Checks if the given string is an IPv6 address. + Currently a hack, just checks a few criteria. + Returns 0 when it is an address. + Returns 1 when it is not an address. + Returns -1 when an error occurred (bad regex - internal) */ +int check_ip6addr( + const char *address) +{ +#if HAVE_REGEX_H + regex_t preg; + if (regcomp(&preg, "^\\[[0-9a-fA-F:]*\\]$", REG_EXTENDED|REG_NOSUB) + != 0) { + return -1; /* do not handle, just state that no match */ + } + if (regexec(&preg, address, 0, NULL, 0) == 0) { + return 0; + } +#endif /* HAVE_REGEX_H */ + /* Fallback when no regexec() compiled in */ + return 1; +} +#endif /* WITH_IP6 */ + +/* Checks if the given string is an IPv6 address. + Currently a hack, just checks a few criteria. + Returns 0 when it is an address. + Returns 1 when it is not an address or on error. */ +int check_ipaddr( + const char *address) +{ + int res4, res6; + if ((res4 = check_ip4addr(address)) == 0) { + return 0; + } + if ((res6 = check_ip6addr(address)) == 0) { + return 0; + } + return 1; +} + + #if HAVE_GETGROUPLIST || (defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)) /* fills the list with the supplementary group ids of user. caller passes size of list in ngroups, function returns number of groups in diff --git a/sysutils.h b/sysutils.h index c680873..98c150d 100644 --- a/sysutils.h +++ b/sysutils.h @@ -80,6 +80,9 @@ extern int sockaddr_vm_parse(struct sockaddr_vm *sa, const char *cid_str, extern const char *inet_ntop(int pf, const void *binaddr, char *addrtext, socklen_t textlen); #endif +extern int check_ip4addr(const char *address); +extern int check_ip6addr(const char *address); +extern int check_ipaddr(const char *address); #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT) extern int getusergroups(const char *user, gid_t *list, int *ngroups); diff --git a/xio-openssl.c b/xio-openssl.c index f393b9b..8b78cf6 100644 --- a/xio-openssl.c +++ b/xio-openssl.c @@ -270,7 +270,11 @@ static int } #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) - if (opt_snihost == NULL) { + if (opt_snihost != NULL) { + if (check_ipaddr(opt_snihost) == 0) { + Warn1("specified SNI host \"%s\" is an IP address", opt_snihost); + } + } else if (check_ipaddr(opt_commonname) != 0) { opt_snihost = strdup(opt_commonname); if (opt_snihost == NULL) { Error1("strdup("F_Zu"): out of memory", strlen(opt_commonname)+1); @@ -444,6 +448,7 @@ int _xioopen_openssl_connect(struct single *xfd, #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name) if (!no_sni) { + /*Warn1("_xioopen_openssl_connect(): calling SSL_set_tlsext_host_name(snihost=\"%s\")", snihost?snihost:"NULL");*/ if (!SSL_set_tlsext_host_name(ssl, snihost)) { Error1("Failed to set SNI host \"%s\"", snihost); sycSSL_free(xfd->para.openssl.ssl);