diff options
Diffstat (limited to 'src/usr.bin/nc')
| -rw-r--r-- | src/usr.bin/nc/nc.1 | 14 | ||||
| -rw-r--r-- | src/usr.bin/nc/netcat.c | 26 | ||||
| -rw-r--r-- | src/usr.bin/nc/socks.c | 36 |
3 files changed, 58 insertions, 18 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. | |||
| 257 | The following TLS options specify a value in the form of a | 257 | The 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 |
| 259 | pair: | 259 | pair: |
| 260 | .Cm alpn , | ||
| 261 | which allows the TLS ALPN to be specified (see | ||
| 262 | .Xr tls_config_set_alpn 3 | ||
| 263 | for further details); | ||
| 260 | .Cm ciphers , | 264 | .Cm ciphers , |
| 261 | which allows the supported TLS ciphers to be specified (see | 265 | which 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. | |||
| 338 | Supported protocols are | 342 | Supported 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) |
| 343 | and | 349 | and |
| 344 | .Cm connect | 350 | .Cm connect |
| 345 | (HTTPS proxy). | 351 | (HTTPS proxy). |
| 346 | If the protocol is not specified, SOCKS version 5 is used. | 352 | If the protocol is not specified, SOCKS version 5 is used. |
| 353 | Note that the SOCKS v.4 protocol is very limited and can only be used when | ||
| 354 | the destination host can be resolved to an IPv4 address. | ||
| 355 | The other protocols pass the destination as a string to be interpreted | ||
| 356 | by 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 |
| 348 | Connect to | 358 | Connect 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..6438fbbc5d 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.237 2025/12/06 09:48:30 phessler 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 */ | |||
| 108 | char *tls_expecthash; /* required hash of peer cert */ | 108 | char *tls_expecthash; /* required hash of peer cert */ |
| 109 | char *tls_ciphers; /* TLS ciphers */ | 109 | char *tls_ciphers; /* TLS ciphers */ |
| 110 | char *tls_protocols; /* TLS protocols */ | 110 | char *tls_protocols; /* TLS protocols */ |
| 111 | char *tls_alpn; /* TLS ALPN */ | ||
| 111 | FILE *Zflag; /* file to save peer cert */ | 112 | FILE *Zflag; /* file to save peer cert */ |
| 112 | 113 | ||
| 113 | int recvcount, recvlimit; | 114 | int 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) |
| @@ -1537,7 +1542,12 @@ connection_info(const char *host, const char *port, const char *proto, | |||
| 1537 | 1542 | ||
| 1538 | /* Look up service name unless -n. */ | 1543 | /* Look up service name unless -n. */ |
| 1539 | if (!nflag) { | 1544 | if (!nflag) { |
| 1540 | sv = getservbyport(ntohs(atoi(port)), proto); | 1545 | const char *errstr; |
| 1546 | |||
| 1547 | int p = strtonum(port, 1, PORT_MAX, &errstr); | ||
| 1548 | if (errstr) | ||
| 1549 | errx(1, "port number %s: %s", errstr, port); | ||
| 1550 | sv = getservbyport(htons(p), proto); | ||
| 1541 | if (sv != NULL) | 1551 | if (sv != NULL) |
| 1542 | service = sv->s_name; | 1552 | service = sv->s_name; |
| 1543 | } | 1553 | } |
| @@ -1645,6 +1655,7 @@ process_tos_opt(char *s, int *val) | |||
| 1645 | { "netcontrol", IPTOS_PREC_NETCONTROL }, | 1655 | { "netcontrol", IPTOS_PREC_NETCONTROL }, |
| 1646 | { "reliability", IPTOS_RELIABILITY }, | 1656 | { "reliability", IPTOS_RELIABILITY }, |
| 1647 | { "throughput", IPTOS_THROUGHPUT }, | 1657 | { "throughput", IPTOS_THROUGHPUT }, |
| 1658 | { "va", IPTOS_DSCP_VA }, | ||
| 1648 | { NULL, -1 }, | 1659 | { NULL, -1 }, |
| 1649 | }; | 1660 | }; |
| 1650 | 1661 | ||
| @@ -1669,11 +1680,12 @@ process_tls_opt(char *s, int *flags) | |||
| 1669 | int flag; | 1680 | int flag; |
| 1670 | char **value; | 1681 | char **value; |
| 1671 | } *t, tlskeywords[] = { | 1682 | } *t, tlskeywords[] = { |
| 1683 | { "alpn", -1, &tls_alpn }, | ||
| 1672 | { "ciphers", -1, &tls_ciphers }, | 1684 | { "ciphers", -1, &tls_ciphers }, |
| 1673 | { "clientcert", TLS_CCERT, NULL }, | 1685 | { "clientcert", TLS_CCERT, NULL }, |
| 1674 | { "muststaple", TLS_MUSTSTAPLE, NULL }, | 1686 | { "muststaple", TLS_MUSTSTAPLE, NULL }, |
| 1675 | { "noverify", TLS_NOVERIFY, NULL }, | ||
| 1676 | { "noname", TLS_NONAME, NULL }, | 1687 | { "noname", TLS_NONAME, NULL }, |
| 1688 | { "noverify", TLS_NOVERIFY, NULL }, | ||
| 1677 | { "protocols", -1, &tls_protocols }, | 1689 | { "protocols", -1, &tls_protocols }, |
| 1678 | { NULL, -1, NULL }, | 1690 | { NULL, -1, NULL }, |
| 1679 | }; | 1691 | }; |
| @@ -1692,6 +1704,8 @@ process_tls_opt(char *s, int *flags) | |||
| 1692 | errx(1, "invalid tls value `%s'", s); | 1704 | errx(1, "invalid tls value `%s'", s); |
| 1693 | *t->value = v; | 1705 | *t->value = v; |
| 1694 | } else { | 1706 | } else { |
| 1707 | if (v != NULL) | ||
| 1708 | errx(1, "invalid tls value `%s'", s); | ||
| 1695 | *flags |= t->flag; | 1709 | *flags |= t->flag; |
| 1696 | } | 1710 | } |
| 1697 | return 1; | 1711 | return 1; |
| @@ -1718,7 +1732,7 @@ void | |||
| 1718 | report_tls(struct tls *tls_ctx, char *host) | 1732 | report_tls(struct tls *tls_ctx, char *host) |
| 1719 | { | 1733 | { |
| 1720 | time_t t; | 1734 | time_t t; |
| 1721 | const char *ocsp_url; | 1735 | const char *alpn_proto, *ocsp_url; |
| 1722 | 1736 | ||
| 1723 | fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n", | 1737 | fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n", |
| 1724 | tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host); | 1738 | tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host); |
| @@ -1770,6 +1784,8 @@ report_tls(struct tls *tls_ctx, char *host) | |||
| 1770 | tls_peer_ocsp_result(tls_ctx)); | 1784 | tls_peer_ocsp_result(tls_ctx)); |
| 1771 | break; | 1785 | break; |
| 1772 | } | 1786 | } |
| 1787 | if ((alpn_proto = tls_conn_alpn_selected(tls_ctx)) != NULL) | ||
| 1788 | fprintf(stderr, "Application Layer Protocol: %s\n", alpn_proto); | ||
| 1773 | } | 1789 | } |
| 1774 | 1790 | ||
| 1775 | void | 1791 | void |
| @@ -1842,7 +1858,7 @@ help(void) | |||
| 1842 | \t-v Verbose\n\ | 1858 | \t-v Verbose\n\ |
| 1843 | \t-W recvlimit Terminate after receiving a number of packets\n\ | 1859 | \t-W recvlimit Terminate after receiving a number of packets\n\ |
| 1844 | \t-w timeout Timeout for connects and final net reads\n\ | 1860 | \t-w timeout Timeout for connects and final net reads\n\ |
| 1845 | \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ | 1861 | \t-X proto Proxy protocol: \"4\", \"4A\", \"5\" (SOCKS) or \"connect\"\n\ |
| 1846 | \t-x addr[:port]\tSpecify proxy address and port\n\ | 1862 | \t-x addr[:port]\tSpecify proxy address and port\n\ |
| 1847 | \t-Z Peer certificate file\n\ | 1863 | \t-Z Peer certificate file\n\ |
| 1848 | \t-z Zero-I/O mode [used for scanning]\n\ | 1864 | \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 */ |
