From: Thomas Habets Date: Sat, 18 Feb 2017 21:07:22 +0000 Subject: Fix TCP MD5SIG for client connections --- netcat.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/netcat.c b/netcat.c index 8291173..990c31b 100644 --- a/netcat.c +++ b/netcat.c @@ -46,6 +46,9 @@ #ifdef __linux__ # include #endif +#if defined(TCP_MD5SIG_EXT) && defined(TCP_MD5SIG_MAXKEYLEN) +# include +#endif #ifndef IPTOS_LOWDELAY # define IPTOS_LOWDELAY 0x10 @@ -175,6 +178,9 @@ FILE *Zflag; /* file to save peer cert */ int Cflag = 0; /* CRLF line-ending */ #endif +#if defined(TCP_MD5SIG_EXT) && defined(TCP_MD5SIG_MAXKEYLEN) +char Sflag_password[TCP_MD5SIG_MAXKEYLEN]; +#endif int recvcount, recvlimit; int timeout = -1; int family = AF_UNSPEC; @@ -206,7 +212,7 @@ void connection_info(const char *, const char *, const char *, const char *); int unix_bind(char *, int); int unix_connect(char *); int unix_listen(char *); -void set_common_sockopts(int, int); +void set_common_sockopts(int, const struct sockaddr *); int process_tos_opt(char *, int *); #ifdef HAVE_TLS int process_tls_opt(char *, int *); @@ -456,7 +462,10 @@ main(int argc, char *argv[]) break; #endif case 'S': -#ifdef TCP_MD5SIG +#if defined(TCP_MD5SIG_EXT) && defined(TCP_MD5SIG_MAXKEYLEN) + if (readpassphrase("TCP MD5SIG password: ", + Sflag_password, TCP_MD5SIG_MAXKEYLEN, RPP_REQUIRE_TTY) == NULL) + errx(1, "Unable to read TCP MD5SIG password"); Sflag = 1; #else errx(1, "no TCP MD5 signature support available"); @@ -1161,7 +1170,7 @@ remote_connect(const char *host, const char *port, struct addrinfo hints, freeaddrinfo(ares); } - set_common_sockopts(s, res->ai_family); + set_common_sockopts(s, res->ai_addr); if (ipaddr != NULL) { herr = getnameinfo(res->ai_addr, res->ai_addrlen, @@ -1336,7 +1345,7 @@ local_listen(const char *host, const char *port, struct addrinfo hints) err(1, NULL); #endif - set_common_sockopts(s, res->ai_family); + set_common_sockopts(s, res->ai_addr); if (bind(s, (struct sockaddr *)res->ai_addr, res->ai_addrlen) == 0) @@ -1910,9 +1919,10 @@ connection_info(const char *host, const char *port, const char *proto, } void -set_common_sockopts(int s, int af) +set_common_sockopts(int s, const struct sockaddr* sa) { int x = 1; + int af = sa->sa_family; #ifdef SO_BROADCAST if (bflag) { @@ -1923,10 +1933,18 @@ set_common_sockopts(int s, int af) err(1, NULL); } #endif -#ifdef TCP_MD5SIG +#if defined(TCP_MD5SIG_EXT) && defined(TCP_MD5SIG_MAXKEYLEN) if (Sflag) { - if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, - &x, sizeof(x)) == -1) + struct tcp_md5sig sig; + memset(&sig, 0, sizeof(sig)); + memcpy(&sig.tcpm_addr, sa, sizeof(struct sockaddr_storage)); + sig.tcpm_keylen = TCP_MD5SIG_MAXKEYLEN < strlen(Sflag_password) + ? TCP_MD5SIG_MAXKEYLEN + : strlen(Sflag_password); + memcpy(sig.tcpm_key, Sflag_password, sig.tcpm_keylen); + sig.tcpm_flags = TCP_MD5SIG_FLAG_PREFIX; + if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG_EXT, + &sig, sizeof(sig)) == -1) err(1, NULL); } #endif