From: Thomas Habets Date: Sat, 18 Feb 2017 21:07:22 +0000 Subject: Set TCP MD5SIG correctly for client connections --- netcat.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) --- a/netcat.c +++ b/netcat.c @@ -47,6 +47,9 @@ #ifdef __linux__ # include #endif +#if defined(TCP_MD5SIG) && defined(TCP_MD5SIG_MAXKEYLEN) +# include +#endif #ifndef IPTOS_LOWDELAY # define IPTOS_LOWDELAY 0x10 @@ -172,6 +175,9 @@ char *tls_expecthash; /* required hash int Cflag = 0; /* CRLF line-ending */ # endif +# if defined(TCP_MD5SIG) && defined(TCP_MD5SIG_MAXKEYLEN) +char Sflag_password[TCP_MD5SIG_MAXKEYLEN]; +# endif int timeout = -1; int family = AF_UNSPEC; char *portlist[PORT_MAX+1]; @@ -200,7 +206,7 @@ int udptest(int); 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 map_tos(char *, int *); # if defined(TLS) int map_tls(char *, int *); @@ -427,7 +433,10 @@ main(int argc, char *argv[]) break; # endif case 'S': -# if defined(TCP_MD5SIG) +# if defined(TCP_MD5SIG) && 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"); @@ -1120,7 +1129,7 @@ remote_connect(const char *host, const c freeaddrinfo(ares); } - set_common_sockopts(s, res->ai_family); + set_common_sockopts(s, res->ai_addr); char *proto = proto_name(uflag, dccpflag); if ((error = connect_with_timeout(s, res->ai_addr, res->ai_addrlen, timeout)) == CONNECTION_SUCCESS) @@ -1274,7 +1283,7 @@ local_listen(char *host, char *port, str 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) @@ -1788,14 +1797,22 @@ udptest(int s) } 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; -# if defined(TCP_MD5SIG) +# if defined(TCP_MD5SIG) && defined(TCP_MD5SIG_MAXKEYLEN) if (Sflag) { + 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); + strlcpy(sig.tcpm_key, Sflag_password, sig.tcpm_keylen); if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, - &x, sizeof(x)) == -1) + &sig, sizeof(sig)) == -1) err(1, NULL); } # endif