summaryrefslogtreecommitdiff
path: root/src/usr.bin/nc
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.bin/nc')
-rw-r--r--src/usr.bin/nc/nc.114
-rw-r--r--src/usr.bin/nc/netcat.c18
-rw-r--r--src/usr.bin/nc/socks.c36
3 files changed, 51 insertions, 17 deletions
diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1
index 76b6dc018e..2ffdcd1ea6 100644
--- a/src/usr.bin/nc/nc.1
+++ b/src/usr.bin/nc/nc.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: nc.1,v 1.98 2024/04/01 12:40:18 deraadt Exp $ 1.\" $OpenBSD: nc.1,v 1.101 2025/06/24 13:37:39 tb Exp $
2.\" 2.\"
3.\" Copyright (c) 1996 David Sacerdote 3.\" Copyright (c) 1996 David Sacerdote
4.\" All rights reserved. 4.\" All rights reserved.
@@ -25,7 +25,7 @@
25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27.\" 27.\"
28.Dd $Mdocdate: April 1 2024 $ 28.Dd $Mdocdate: June 24 2025 $
29.Dt NC 1 29.Dt NC 1
30.Os 30.Os
31.Sh NAME 31.Sh NAME
@@ -257,6 +257,10 @@ with the handshake.
257The following TLS options specify a value in the form of a 257The following TLS options specify a value in the form of a
258.Ar key Ns = Ns Ar value 258.Ar key Ns = Ns Ar value
259pair: 259pair:
260.Cm alpn ,
261which allows the TLS ALPN to be specified (see
262.Xr tls_config_set_alpn 3
263for further details);
260.Cm ciphers , 264.Cm ciphers ,
261which allows the supported TLS ciphers to be specified (see 265which allows the supported TLS ciphers to be specified (see
262.Xr tls_config_set_ciphers 3 266.Xr tls_config_set_ciphers 3
@@ -338,12 +342,18 @@ when talking to the proxy server.
338Supported protocols are 342Supported protocols are
339.Cm 4 343.Cm 4
340(SOCKS v.4), 344(SOCKS v.4),
345.Cm 4A
346(SOCKS v.4A),
341.Cm 5 347.Cm 5
342(SOCKS v.5) 348(SOCKS v.5)
343and 349and
344.Cm connect 350.Cm connect
345(HTTPS proxy). 351(HTTPS proxy).
346If the protocol is not specified, SOCKS version 5 is used. 352If the protocol is not specified, SOCKS version 5 is used.
353Note that the SOCKS v.4 protocol is very limited and can only be used when
354the destination host can be resolved to an IPv4 address.
355The other protocols pass the destination as a string to be interpreted
356by the remote proxy and do not have this limitation.
347.It Fl x Ar proxy_address Ns Op : Ns Ar port 357.It Fl x Ar proxy_address Ns Op : Ns Ar port
348Connect to 358Connect to
349.Ar destination 359.Ar destination
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
index 8c60fd1882..e3c9c939e2 100644
--- a/src/usr.bin/nc/netcat.c
+++ b/src/usr.bin/nc/netcat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: netcat.c,v 1.229 2024/11/02 17:19:27 tb Exp $ */ 1/* $OpenBSD: netcat.c,v 1.234 2025/06/24 13:37:11 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 * Copyright (c) 2015 Bob Beck. All rights reserved. 4 * Copyright (c) 2015 Bob Beck. All rights reserved.
@@ -108,6 +108,7 @@ char *tls_expectname; /* required name in peer cert */
108char *tls_expecthash; /* required hash of peer cert */ 108char *tls_expecthash; /* required hash of peer cert */
109char *tls_ciphers; /* TLS ciphers */ 109char *tls_ciphers; /* TLS ciphers */
110char *tls_protocols; /* TLS protocols */ 110char *tls_protocols; /* TLS protocols */
111char *tls_alpn; /* TLS ALPN */
111FILE *Zflag; /* file to save peer cert */ 112FILE *Zflag; /* file to save peer cert */
112 113
113int recvcount, recvlimit; 114int recvcount, recvlimit;
@@ -190,6 +191,8 @@ main(int argc, char *argv[])
190 socksv = -1; /* HTTP proxy CONNECT */ 191 socksv = -1; /* HTTP proxy CONNECT */
191 else if (strcmp(optarg, "4") == 0) 192 else if (strcmp(optarg, "4") == 0)
192 socksv = 4; /* SOCKS v.4 */ 193 socksv = 4; /* SOCKS v.4 */
194 else if (strcasecmp(optarg, "4A") == 0)
195 socksv = 44; /* SOCKS v.4A */
193 else if (strcmp(optarg, "5") == 0) 196 else if (strcmp(optarg, "5") == 0)
194 socksv = 5; /* SOCKS v.5 */ 197 socksv = 5; /* SOCKS v.5 */
195 else 198 else
@@ -532,6 +535,8 @@ main(int argc, char *argv[])
532 errx(1, "%s", tls_config_error(tls_cfg)); 535 errx(1, "%s", tls_config_error(tls_cfg));
533 if (tls_config_set_ciphers(tls_cfg, tls_ciphers) == -1) 536 if (tls_config_set_ciphers(tls_cfg, tls_ciphers) == -1)
534 errx(1, "%s", tls_config_error(tls_cfg)); 537 errx(1, "%s", tls_config_error(tls_cfg));
538 if (tls_alpn != NULL && tls_config_set_alpn(tls_cfg, tls_alpn) == -1)
539 errx(1, "%s", tls_config_error(tls_cfg));
535 if (!lflag && (TLSopt & TLS_CCERT)) 540 if (!lflag && (TLSopt & TLS_CCERT))
536 errx(1, "clientcert is only valid with -l"); 541 errx(1, "clientcert is only valid with -l");
537 if (TLSopt & TLS_NONAME) 542 if (TLSopt & TLS_NONAME)
@@ -1669,11 +1674,12 @@ process_tls_opt(char *s, int *flags)
1669 int flag; 1674 int flag;
1670 char **value; 1675 char **value;
1671 } *t, tlskeywords[] = { 1676 } *t, tlskeywords[] = {
1677 { "alpn", -1, &tls_alpn },
1672 { "ciphers", -1, &tls_ciphers }, 1678 { "ciphers", -1, &tls_ciphers },
1673 { "clientcert", TLS_CCERT, NULL }, 1679 { "clientcert", TLS_CCERT, NULL },
1674 { "muststaple", TLS_MUSTSTAPLE, NULL }, 1680 { "muststaple", TLS_MUSTSTAPLE, NULL },
1675 { "noverify", TLS_NOVERIFY, NULL },
1676 { "noname", TLS_NONAME, NULL }, 1681 { "noname", TLS_NONAME, NULL },
1682 { "noverify", TLS_NOVERIFY, NULL },
1677 { "protocols", -1, &tls_protocols }, 1683 { "protocols", -1, &tls_protocols },
1678 { NULL, -1, NULL }, 1684 { NULL, -1, NULL },
1679 }; 1685 };
@@ -1692,6 +1698,8 @@ process_tls_opt(char *s, int *flags)
1692 errx(1, "invalid tls value `%s'", s); 1698 errx(1, "invalid tls value `%s'", s);
1693 *t->value = v; 1699 *t->value = v;
1694 } else { 1700 } else {
1701 if (v != NULL)
1702 errx(1, "invalid tls value `%s'", s);
1695 *flags |= t->flag; 1703 *flags |= t->flag;
1696 } 1704 }
1697 return 1; 1705 return 1;
@@ -1718,7 +1726,7 @@ void
1718report_tls(struct tls *tls_ctx, char *host) 1726report_tls(struct tls *tls_ctx, char *host)
1719{ 1727{
1720 time_t t; 1728 time_t t;
1721 const char *ocsp_url; 1729 const char *alpn_proto, *ocsp_url;
1722 1730
1723 fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n", 1731 fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n",
1724 tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host); 1732 tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host);
@@ -1770,6 +1778,8 @@ report_tls(struct tls *tls_ctx, char *host)
1770 tls_peer_ocsp_result(tls_ctx)); 1778 tls_peer_ocsp_result(tls_ctx));
1771 break; 1779 break;
1772 } 1780 }
1781 if ((alpn_proto = tls_conn_alpn_selected(tls_ctx)) != NULL)
1782 fprintf(stderr, "Application Layer Protocol: %s\n", alpn_proto);
1773} 1783}
1774 1784
1775void 1785void
@@ -1842,7 +1852,7 @@ help(void)
1842 \t-v Verbose\n\ 1852 \t-v Verbose\n\
1843 \t-W recvlimit Terminate after receiving a number of packets\n\ 1853 \t-W recvlimit Terminate after receiving a number of packets\n\
1844 \t-w timeout Timeout for connects and final net reads\n\ 1854 \t-w timeout Timeout for connects and final net reads\n\
1845 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ 1855 \t-X proto Proxy protocol: \"4\", \"4A\", \"5\" (SOCKS) or \"connect\"\n\
1846 \t-x addr[:port]\tSpecify proxy address and port\n\ 1856 \t-x addr[:port]\tSpecify proxy address and port\n\
1847 \t-Z Peer certificate file\n\ 1857 \t-Z Peer certificate file\n\
1848 \t-z Zero-I/O mode [used for scanning]\n\ 1858 \t-z Zero-I/O mode [used for scanning]\n\
diff --git a/src/usr.bin/nc/socks.c b/src/usr.bin/nc/socks.c
index 7c7448c9c5..1f1fb96e2a 100644
--- a/src/usr.bin/nc/socks.c
+++ b/src/usr.bin/nc/socks.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: socks.c,v 1.31 2022/06/08 20:20:26 djm Exp $ */ 1/* $OpenBSD: socks.c,v 1.34 2025/05/22 06:40:26 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. 4 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
@@ -293,19 +293,33 @@ socks_connect(const char *host, const char *port,
293 default: 293 default:
294 errx(1, "connection failed, unsupported address type"); 294 errx(1, "connection failed, unsupported address type");
295 } 295 }
296 } else if (socksv == 4) { 296 } else if (socksv == 4 || socksv == 44) {
297 /* This will exit on lookup failure */ 297 if (socksv == 4) {
298 decode_addrport(host, port, (struct sockaddr *)&addr, 298 /* This will exit on lookup failure */
299 sizeof(addr), 1, 0); 299 decode_addrport(host, port, (struct sockaddr *)&addr,
300 sizeof(addr), 1, 0);
301 }
300 302
301 /* Version 4 */ 303 /* Version 4 */
302 buf[0] = SOCKS_V4; 304 buf[0] = SOCKS_V4;
303 buf[1] = SOCKS_CONNECT; /* connect */ 305 buf[1] = SOCKS_CONNECT; /* connect */
304 memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port); 306 memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port);
305 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); 307 if (socksv == 4) {
308 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
309 } else {
310 /* SOCKS4A uses addr of 0.0.0.x, and hostname later */
311 buf[4] = buf[5] = buf[6] = 0;
312 buf[7] = 1;
313 }
306 buf[8] = 0; /* empty username */ 314 buf[8] = 0; /* empty username */
307 wlen = 9; 315 wlen = 9;
308 316 if (socksv == 44) {
317 /* SOCKS4A has nul-terminated hostname after user */
318 if (strlcpy(buf + 9, host,
319 sizeof(buf) - 9) >= sizeof(buf) - 9)
320 errx(1, "hostname too big");
321 wlen = 9 + strlen(host) + 1;
322 }
309 cnt = atomicio(vwrite, proxyfd, buf, wlen); 323 cnt = atomicio(vwrite, proxyfd, buf, wlen);
310 if (cnt != wlen) 324 if (cnt != wlen)
311 err(1, "write failed (%zu/%zu)", cnt, wlen); 325 err(1, "write failed (%zu/%zu)", cnt, wlen);
@@ -373,16 +387,16 @@ socks_connect(const char *host, const char *port,
373 /* Read status reply */ 387 /* Read status reply */
374 proxy_read_line(proxyfd, buf, sizeof(buf)); 388 proxy_read_line(proxyfd, buf, sizeof(buf));
375 if (proxyuser != NULL && 389 if (proxyuser != NULL &&
376 (strncmp(buf, "HTTP/1.0 407 ", 12) == 0 || 390 (strncmp(buf, "HTTP/1.0 407 ", 13) == 0 ||
377 strncmp(buf, "HTTP/1.1 407 ", 12) == 0)) { 391 strncmp(buf, "HTTP/1.1 407 ", 13) == 0)) {
378 if (authretry > 1) { 392 if (authretry > 1) {
379 fprintf(stderr, "Proxy authentication " 393 fprintf(stderr, "Proxy authentication "
380 "failed\n"); 394 "failed\n");
381 } 395 }
382 close(proxyfd); 396 close(proxyfd);
383 goto again; 397 goto again;
384 } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 && 398 } else if (strncmp(buf, "HTTP/1.0 200 ", 13) != 0 &&
385 strncmp(buf, "HTTP/1.1 200 ", 12) != 0) 399 strncmp(buf, "HTTP/1.1 200 ", 13) != 0)
386 errx(1, "Proxy error: \"%s\"", buf); 400 errx(1, "Proxy error: \"%s\"", buf);
387 401
388 /* Headers continue until we hit an empty line */ 402 /* Headers continue until we hit an empty line */