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 @@ -176,6 +179,9 @@ FILE *Zflag; /* file to save peer ce int Cflag = 0; /* CRLF line-ending */ # endif +# if defined(TCP_MD5SIG) && 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 @@ 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 process_tos_opt(char *, int *); # if defined(TLS) int process_tls_opt(char *, int *); @@ -456,7 +462,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"); @@ -1171,7 +1180,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) @@ -1325,7 +1334,7 @@ local_listen(const char *host, const cha 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) @@ -1845,9 +1854,10 @@ 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(SO_BROADCAST) if (bflag) { @@ -1858,10 +1868,17 @@ set_common_sockopts(int s, int af) err(1, NULL); } # endif -# 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