From ee04221ea8063435416c7e6369e6eae76843aa71 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Fri, 13 Jul 2012 17:49:56 +0000 Subject: This commit was manufactured by cvs2git to create tag 'eric_g2k12'. --- src/usr.bin/nc/Makefile | 6 - src/usr.bin/nc/atomicio.c | 69 --- src/usr.bin/nc/atomicio.h | 39 -- src/usr.bin/nc/nc.1 | 467 -------------------- src/usr.bin/nc/netcat.c | 1047 --------------------------------------------- src/usr.bin/nc/socks.c | 340 --------------- 6 files changed, 1968 deletions(-) delete mode 100644 src/usr.bin/nc/Makefile delete mode 100644 src/usr.bin/nc/atomicio.c delete mode 100644 src/usr.bin/nc/atomicio.h delete mode 100644 src/usr.bin/nc/nc.1 delete mode 100644 src/usr.bin/nc/netcat.c delete mode 100644 src/usr.bin/nc/socks.c (limited to 'src/usr.bin') diff --git a/src/usr.bin/nc/Makefile b/src/usr.bin/nc/Makefile deleted file mode 100644 index 150f8295bd..0000000000 --- a/src/usr.bin/nc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $OpenBSD: Makefile,v 1.6 2001/09/02 18:45:41 jakob Exp $ - -PROG= nc -SRCS= netcat.c atomicio.c socks.c - -.include diff --git a/src/usr.bin/nc/atomicio.c b/src/usr.bin/nc/atomicio.c deleted file mode 100644 index feb6f19440..0000000000 --- a/src/usr.bin/nc/atomicio.c +++ /dev/null @@ -1,69 +0,0 @@ -/* $OpenBSD: atomicio.c,v 1.10 2011/01/08 00:47:19 jeremy Exp $ */ -/* - * Copyright (c) 2006 Damien Miller. All rights reserved. - * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. - * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include -#include -#include - -#include "atomicio.h" - -/* - * ensure all of data on socket comes through. f==read || f==vwrite - */ -size_t -atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) -{ - char *s = _s; - size_t pos = 0; - ssize_t res; - struct pollfd pfd; - - pfd.fd = fd; - pfd.events = f == read ? POLLIN : POLLOUT; - while (n > pos) { - res = (f) (fd, s + pos, n - pos); - switch (res) { - case -1: - if (errno == EINTR) - continue; - if ((errno == EAGAIN) || (errno == ENOBUFS)) { - (void)poll(&pfd, 1, -1); - continue; - } - return 0; - case 0: - errno = EPIPE; - return pos; - default: - pos += (size_t)res; - } - } - return (pos); -} diff --git a/src/usr.bin/nc/atomicio.h b/src/usr.bin/nc/atomicio.h deleted file mode 100644 index 7bf5b25418..0000000000 --- a/src/usr.bin/nc/atomicio.h +++ /dev/null @@ -1,39 +0,0 @@ -/* $OpenBSD: atomicio.h,v 1.2 2007/09/07 14:50:44 tobias Exp $ */ - -/* - * Copyright (c) 2006 Damien Miller. All rights reserved. - * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _ATOMICIO_H -#define _ATOMICIO_H - -/* - * Ensure all of data on socket comes through. f==read || f==vwrite - */ -size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t); - -#define vwrite (ssize_t (*)(int, void *, size_t))write - -#endif /* _ATOMICIO_H */ diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1 deleted file mode 100644 index 232b6f5b6e..0000000000 --- a/src/usr.bin/nc/nc.1 +++ /dev/null @@ -1,467 +0,0 @@ -.\" $OpenBSD: nc.1,v 1.61 2012/07/07 15:33:02 haesbaert Exp $ -.\" -.\" Copyright (c) 1996 David Sacerdote -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd $Mdocdate: July 7 2012 $ -.Dt NC 1 -.Os -.Sh NAME -.Nm nc -.Nd arbitrary TCP and UDP connections and listens -.Sh SYNOPSIS -.Nm nc -.Bk -words -.Op Fl 46DdhklnrStUuvz -.Op Fl I Ar length -.Op Fl i Ar interval -.Op Fl O Ar length -.Op Fl P Ar proxy_username -.Op Fl p Ar source_port -.Op Fl s Ar source -.Op Fl T Ar toskeyword -.Op Fl V Ar rtable -.Op Fl w Ar timeout -.Op Fl X Ar proxy_protocol -.Oo Xo -.Fl x Ar proxy_address Ns Oo : Ns -.Ar port Oc -.Xc Oc -.Op Ar destination -.Op Ar port -.Ek -.Sh DESCRIPTION -The -.Nm -(or -.Nm netcat ) -utility is used for just about anything under the sun involving TCP, -UDP, or -.Ux Ns -domain -sockets. -It can open TCP connections, send UDP packets, listen on arbitrary -TCP and UDP ports, do port scanning, and deal with both IPv4 and -IPv6. -Unlike -.Xr telnet 1 , -.Nm -scripts nicely, and separates error messages onto standard error instead -of sending them to standard output, as -.Xr telnet 1 -does with some. -.Pp -Common uses include: -.Pp -.Bl -bullet -offset indent -compact -.It -simple TCP proxies -.It -shell-script based HTTP clients and servers -.It -network daemon testing -.It -a SOCKS or HTTP ProxyCommand for -.Xr ssh 1 -.It -and much, much more -.El -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl 4 -Forces -.Nm -to use IPv4 addresses only. -.It Fl 6 -Forces -.Nm -to use IPv6 addresses only. -.It Fl D -Enable debugging on the socket. -.It Fl d -Do not attempt to read from stdin. -.It Fl h -Prints out -.Nm -help. -.It Fl I Ar length -Specifies the size of the TCP receive buffer. -.It Fl i Ar interval -Specifies a delay time interval between lines of text sent and received. -Also causes a delay time between connections to multiple ports. -.It Fl k -Forces -.Nm -to stay listening for another connection after its current connection -is completed. -It is an error to use this option without the -.Fl l -option. -When used together with the -.Fl u -option, the server socket is not connected and it can receive UDP datagrams from -multiple hosts. -.It Fl l -Used to specify that -.Nm -should listen for an incoming connection rather than initiate a -connection to a remote host. -It is an error to use this option in conjunction with the -.Fl p , -.Fl s , -or -.Fl z -options. -Additionally, any timeouts specified with the -.Fl w -option are ignored. -.It Fl n -Do not do any DNS or service lookups on any specified addresses, -hostnames or ports. -.It Fl O Ar length -Specifies the size of the TCP send buffer. -.It Fl P Ar proxy_username -Specifies a username to present to a proxy server that requires authentication. -If no username is specified then authentication will not be attempted. -Proxy authentication is only supported for HTTP CONNECT proxies at present. -.It Fl p Ar source_port -Specifies the source port -.Nm -should use, subject to privilege restrictions and availability. -It is an error to use this option in conjunction with the -.Fl l -option. -.It Fl r -Specifies that source and/or destination ports should be chosen randomly -instead of sequentially within a range or in the order that the system -assigns them. -.It Fl S -Enables the RFC 2385 TCP MD5 signature option. -.It Fl s Ar source -Specifies the IP of the interface which is used to send the packets. -For -.Ux Ns -domain -datagram sockets, specifies the local temporary socket file -to create and use so that datagrams can be received. -It is an error to use this option in conjunction with the -.Fl l -option. -.It Fl T Ar toskeyword -Change IPv4 TOS value. -.Ar toskeyword -may be one of -.Ar critical , -.Ar inetcontrol , -.Ar lowdelay , -.Ar netcontrol , -.Ar throughput , -.Ar reliability , -or one of the DiffServ Code Points: -.Ar ef , -.Ar af11 ... af43 , -.Ar cs0 ... cs7 ; -or a number in either hex or decimal. -.It Fl t -Causes -.Nm -to send RFC 854 DON'T and WON'T responses to RFC 854 DO and WILL requests. -This makes it possible to use -.Nm -to script telnet sessions. -.It Fl U -Specifies to use -.Ux Ns -domain -sockets. -.It Fl u -Use UDP instead of the default option of TCP. -For -.Ux Ns -domain -sockets, use a datagram socket instead of a stream socket. -If a -.Ux Ns -domain -socket is used, a temporary receiving socket is created in -.Pa /tmp -unless the -.Fl s -flag is given. -.It Fl V Ar rtable -Set the routing table to be used. -The default is 0. -.It Fl v -Have -.Nm -give more verbose output. -.It Fl w Ar timeout -Connections which cannot be established or are idle timeout after -.Ar timeout -seconds. -The -.Fl w -flag has no effect on the -.Fl l -option, i.e.\& -.Nm -will listen forever for a connection, with or without the -.Fl w -flag. -The default is no timeout. -.It Fl X Ar proxy_protocol -Requests that -.Nm -should use the specified protocol when talking to the proxy server. -Supported protocols are -.Dq 4 -(SOCKS v.4), -.Dq 5 -(SOCKS v.5) -and -.Dq connect -(HTTPS proxy). -If the protocol is not specified, SOCKS version 5 is used. -.It Xo -.Fl x Ar proxy_address Ns Oo : Ns -.Ar port Oc -.Xc -Requests that -.Nm -should connect to -.Ar destination -using a proxy at -.Ar proxy_address -and -.Ar port . -If -.Ar port -is not specified, the well-known port for the proxy protocol is used (1080 -for SOCKS, 3128 for HTTPS). -.It Fl z -Specifies that -.Nm -should just scan for listening daemons, without sending any data to them. -It is an error to use this option in conjunction with the -.Fl l -option. -.El -.Pp -.Ar destination -can be a numerical IP address or a symbolic hostname -(unless the -.Fl n -option is given). -In general, a destination must be specified, -unless the -.Fl l -option is given -(in which case the local host is used). -For -.Ux Ns -domain -sockets, a destination is required and is the socket path to connect to -(or listen on if the -.Fl l -option is given). -.Pp -.Ar port -can be a single integer or a range of ports. -Ranges are in the form nn-mm. -In general, -a destination port must be specified, -unless the -.Fl U -option is given. -.Sh CLIENT/SERVER MODEL -It is quite simple to build a very basic client/server model using -.Nm . -On one console, start -.Nm -listening on a specific port for a connection. -For example: -.Pp -.Dl $ nc -l 1234 -.Pp -.Nm -is now listening on port 1234 for a connection. -On a second console -.Pq or a second machine , -connect to the machine and port being listened on: -.Pp -.Dl $ nc 127.0.0.1 1234 -.Pp -There should now be a connection between the ports. -Anything typed at the second console will be concatenated to the first, -and vice-versa. -After the connection has been set up, -.Nm -does not really care which side is being used as a -.Sq server -and which side is being used as a -.Sq client . -The connection may be terminated using an -.Dv EOF -.Pq Sq ^D . -.Sh DATA TRANSFER -The example in the previous section can be expanded to build a -basic data transfer model. -Any information input into one end of the connection will be output -to the other end, and input and output can be easily captured in order to -emulate file transfer. -.Pp -Start by using -.Nm -to listen on a specific port, with output captured into a file: -.Pp -.Dl $ nc -l 1234 \*(Gt filename.out -.Pp -Using a second machine, connect to the listening -.Nm -process, feeding it the file which is to be transferred: -.Pp -.Dl $ nc host.example.com 1234 \*(Lt filename.in -.Pp -After the file has been transferred, the connection will close automatically. -.Sh TALKING TO SERVERS -It is sometimes useful to talk to servers -.Dq by hand -rather than through a user interface. -It can aid in troubleshooting, -when it might be necessary to verify what data a server is sending -in response to commands issued by the client. -For example, to retrieve the home page of a web site: -.Bd -literal -offset indent -$ printf "GET / HTTP/1.0\er\en\er\en" | nc host.example.com 80 -.Ed -.Pp -Note that this also displays the headers sent by the web server. -They can be filtered, using a tool such as -.Xr sed 1 , -if necessary. -.Pp -More complicated examples can be built up when the user knows the format -of requests required by the server. -As another example, an email may be submitted to an SMTP server using: -.Bd -literal -offset indent -$ nc localhost 25 \*(Lt\*(Lt EOF -HELO host.example.com -MAIL FROM:\*(Ltuser@host.example.com\*(Gt -RCPT TO:\*(Ltuser2@host.example.com\*(Gt -DATA -Body of email. -\&. -QUIT -EOF -.Ed -.Sh PORT SCANNING -It may be useful to know which ports are open and running services on -a target machine. -The -.Fl z -flag can be used to tell -.Nm -to report open ports, -rather than initiate a connection. -For example: -.Bd -literal -offset indent -$ nc -z host.example.com 20-30 -Connection to host.example.com 22 port [tcp/ssh] succeeded! -Connection to host.example.com 25 port [tcp/smtp] succeeded! -.Ed -.Pp -The port range was specified to limit the search to ports 20 \- 30. -.Pp -Alternatively, it might be useful to know which server software -is running, and which versions. -This information is often contained within the greeting banners. -In order to retrieve these, it is necessary to first make a connection, -and then break the connection when the banner has been retrieved. -This can be accomplished by specifying a small timeout with the -.Fl w -flag, or perhaps by issuing a -.Qq Dv QUIT -command to the server: -.Bd -literal -offset indent -$ echo "QUIT" | nc host.example.com 20-30 -SSH-1.99-OpenSSH_3.6.1p2 -Protocol mismatch. -220 host.example.com IMS SMTP Receiver Version 0.84 Ready -.Ed -.Sh EXAMPLES -Open a TCP connection to port 42 of host.example.com, using port 31337 as -the source port, with a timeout of 5 seconds: -.Pp -.Dl $ nc -p 31337 -w 5 host.example.com 42 -.Pp -Open a UDP connection to port 53 of host.example.com: -.Pp -.Dl $ nc -u host.example.com 53 -.Pp -Open a TCP connection to port 42 of host.example.com using 10.1.2.3 as the -IP for the local end of the connection: -.Pp -.Dl $ nc -s 10.1.2.3 host.example.com 42 -.Pp -Create and listen on a -.Ux Ns -domain -stream socket: -.Pp -.Dl $ nc -lU /var/tmp/dsocket -.Pp -Connect to port 42 of host.example.com via an HTTP proxy at 10.2.3.4, -port 8080. -This example could also be used by -.Xr ssh 1 ; -see the -.Cm ProxyCommand -directive in -.Xr ssh_config 5 -for more information. -.Pp -.Dl $ nc -x10.2.3.4:8080 -Xconnect host.example.com 42 -.Pp -The same example again, this time enabling proxy authentication with username -.Dq ruser -if the proxy requires it: -.Pp -.Dl $ nc -x10.2.3.4:8080 -Xconnect -Pruser host.example.com 42 -.Sh SEE ALSO -.Xr cat 1 , -.Xr ssh 1 -.Sh AUTHORS -Original implementation by *Hobbit* -.Aq hobbit@avian.org . -.br -Rewritten with IPv6 support by -.An Eric Jackson Aq ericj@monkey.org . -.Sh CAVEATS -UDP port scans using the -.Fl uz -combination of flags will always report success irrespective of -the target machine's state. -However, -in conjunction with a traffic sniffer either on the target machine -or an intermediary device, -the -.Fl uz -combination could be useful for communications diagnostics. -Note that the amount of UDP traffic generated may be limited either -due to hardware resources and/or configuration settings. diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c deleted file mode 100644 index a034bbab8c..0000000000 --- a/src/usr.bin/nc/netcat.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* $OpenBSD: netcat.c,v 1.109 2012/07/07 15:33:02 haesbaert Exp $ */ -/* - * Copyright (c) 2001 Eric Jackson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Re-written nc(1) for OpenBSD. Original implementation by - * *Hobbit* . - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "atomicio.h" - -#ifndef SUN_LEN -#define SUN_LEN(su) \ - (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) -#endif - -#define PORT_MAX 65535 -#define PORT_MAX_LEN 6 -#define UNIX_DG_TMP_SOCKET_SIZE 19 - -/* Command Line Options */ -int dflag; /* detached, no stdin */ -unsigned int iflag; /* Interval Flag */ -int kflag; /* More than one connect */ -int lflag; /* Bind to local port */ -int nflag; /* Don't do name look up */ -char *Pflag; /* Proxy username */ -char *pflag; /* Localport flag */ -int rflag; /* Random ports flag */ -char *sflag; /* Source Address */ -int tflag; /* Telnet Emulation */ -int uflag; /* UDP - Default to TCP */ -int vflag; /* Verbosity */ -int xflag; /* Socks proxy */ -int zflag; /* Port Scan Flag */ -int Dflag; /* sodebug */ -int Iflag; /* TCP receive buffer size */ -int Oflag; /* TCP send buffer size */ -int Sflag; /* TCP MD5 signature option */ -int Tflag = -1; /* IP Type of Service */ -u_int rtableid; - -int timeout = -1; -int family = AF_UNSPEC; -char *portlist[PORT_MAX+1]; -char *unix_dg_tmp_socket; - -void atelnet(int, unsigned char *, unsigned int); -void build_ports(char *); -void help(void); -int local_listen(char *, char *, struct addrinfo); -void readwrite(int); -int remote_connect(const char *, const char *, struct addrinfo); -int timeout_connect(int, const struct sockaddr *, socklen_t); -int socks_connect(const char *, const char *, struct addrinfo, - const char *, const char *, struct addrinfo, int, const char *); -int udptest(int); -int unix_bind(char *); -int unix_connect(char *); -int unix_listen(char *); -void set_common_sockopts(int); -int map_tos(char *, int *); -void report_connect(const struct sockaddr *, socklen_t); -void usage(int); - -int -main(int argc, char *argv[]) -{ - int ch, s, ret, socksv; - char *host, *uport; - struct addrinfo hints; - struct servent *sv; - socklen_t len; - struct sockaddr_storage cliaddr; - char *proxy; - const char *errstr, *proxyhost = "", *proxyport = NULL; - struct addrinfo proxyhints; - char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE]; - - ret = 1; - s = 0; - socksv = 5; - host = NULL; - uport = NULL; - sv = NULL; - - while ((ch = getopt(argc, argv, - "46DdhI:i:klnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) { - switch (ch) { - case '4': - family = AF_INET; - break; - case '6': - family = AF_INET6; - break; - case 'U': - family = AF_UNIX; - break; - case 'X': - if (strcasecmp(optarg, "connect") == 0) - socksv = -1; /* HTTP proxy CONNECT */ - else if (strcmp(optarg, "4") == 0) - socksv = 4; /* SOCKS v.4 */ - else if (strcmp(optarg, "5") == 0) - socksv = 5; /* SOCKS v.5 */ - else - errx(1, "unsupported proxy protocol"); - break; - case 'd': - dflag = 1; - break; - case 'h': - help(); - break; - case 'i': - iflag = strtonum(optarg, 0, UINT_MAX, &errstr); - if (errstr) - errx(1, "interval %s: %s", errstr, optarg); - break; - case 'k': - kflag = 1; - break; - case 'l': - lflag = 1; - break; - case 'n': - nflag = 1; - break; - case 'P': - Pflag = optarg; - break; - case 'p': - pflag = optarg; - break; - case 'r': - rflag = 1; - break; - case 's': - sflag = optarg; - break; - case 't': - tflag = 1; - break; - case 'u': - uflag = 1; - break; - case 'V': - rtableid = (unsigned int)strtonum(optarg, 0, - RT_TABLEID_MAX, &errstr); - if (errstr) - errx(1, "rtable %s: %s", errstr, optarg); - break; - case 'v': - vflag = 1; - break; - case 'w': - timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr); - if (errstr) - errx(1, "timeout %s: %s", errstr, optarg); - timeout *= 1000; - break; - case 'x': - xflag = 1; - if ((proxy = strdup(optarg)) == NULL) - err(1, NULL); - break; - case 'z': - zflag = 1; - break; - case 'D': - Dflag = 1; - break; - case 'I': - Iflag = strtonum(optarg, 1, 65536 << 14, &errstr); - if (errstr != NULL) - errx(1, "TCP receive window %s: %s", - errstr, optarg); - break; - case 'O': - Oflag = strtonum(optarg, 1, 65536 << 14, &errstr); - if (errstr != NULL) - errx(1, "TCP send window %s: %s", - errstr, optarg); - break; - case 'S': - Sflag = 1; - break; - case 'T': - errstr = NULL; - errno = 0; - if (map_tos(optarg, &Tflag)) - break; - if (strlen(optarg) > 1 && optarg[0] == '0' && - optarg[1] == 'x') - Tflag = (int)strtol(optarg, NULL, 16); - else - Tflag = (int)strtonum(optarg, 0, 255, - &errstr); - if (Tflag < 0 || Tflag > 255 || errstr || errno) - errx(1, "illegal tos value %s", optarg); - break; - default: - usage(1); - } - } - argc -= optind; - argv += optind; - - /* Cruft to make sure options are clean, and used properly. */ - if (argv[0] && !argv[1] && family == AF_UNIX) { - host = argv[0]; - uport = NULL; - } else if (argv[0] && !argv[1]) { - if (!lflag) - usage(1); - uport = argv[0]; - host = NULL; - } else if (argv[0] && argv[1]) { - host = argv[0]; - uport = argv[1]; - } else - usage(1); - - if (lflag && sflag) - errx(1, "cannot use -s and -l"); - if (lflag && pflag) - errx(1, "cannot use -p and -l"); - if (lflag && zflag) - errx(1, "cannot use -z and -l"); - if (!lflag && kflag) - errx(1, "must use -l with -k"); - - /* Get name of temporary socket for unix datagram client */ - if ((family == AF_UNIX) && uflag && !lflag) { - if (sflag) { - unix_dg_tmp_socket = sflag; - } else { - strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX", - UNIX_DG_TMP_SOCKET_SIZE); - if (mktemp(unix_dg_tmp_socket_buf) == NULL) - err(1, "mktemp"); - unix_dg_tmp_socket = unix_dg_tmp_socket_buf; - } - } - - /* Initialize addrinfo structure. */ - if (family != AF_UNIX) { - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = family; - hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; - hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; - if (nflag) - hints.ai_flags |= AI_NUMERICHOST; - } - - if (xflag) { - if (uflag) - errx(1, "no proxy support for UDP mode"); - - if (lflag) - errx(1, "no proxy support for listen"); - - if (family == AF_UNIX) - errx(1, "no proxy support for unix sockets"); - - /* XXX IPv6 transport to proxy would probably work */ - if (family == AF_INET6) - errx(1, "no proxy support for IPv6"); - - if (sflag) - errx(1, "no proxy support for local source address"); - - proxyhost = strsep(&proxy, ":"); - proxyport = proxy; - - memset(&proxyhints, 0, sizeof(struct addrinfo)); - proxyhints.ai_family = family; - proxyhints.ai_socktype = SOCK_STREAM; - proxyhints.ai_protocol = IPPROTO_TCP; - if (nflag) - proxyhints.ai_flags |= AI_NUMERICHOST; - } - - if (lflag) { - int connfd; - ret = 0; - - if (family == AF_UNIX) { - if (uflag) - s = unix_bind(host); - else - s = unix_listen(host); - } - - /* Allow only one connection at a time, but stay alive. */ - for (;;) { - if (family != AF_UNIX) - s = local_listen(host, uport, hints); - if (s < 0) - err(1, NULL); - /* - * For UDP and -k, don't connect the socket, let it - * receive datagrams from multiple socket pairs. - */ - if (uflag && kflag) - readwrite(s); - /* - * For UDP and not -k, we will use recvfrom() initially - * to wait for a caller, then use the regular functions - * to talk to the caller. - */ - else if (uflag && !kflag) { - int rv, plen; - char buf[16384]; - struct sockaddr_storage z; - - len = sizeof(z); - plen = 2048; - rv = recvfrom(s, buf, plen, MSG_PEEK, - (struct sockaddr *)&z, &len); - if (rv < 0) - err(1, "recvfrom"); - - rv = connect(s, (struct sockaddr *)&z, len); - if (rv < 0) - err(1, "connect"); - - if (vflag) - report_connect((struct sockaddr *)&z, len); - - readwrite(s); - } else { - len = sizeof(cliaddr); - connfd = accept(s, (struct sockaddr *)&cliaddr, - &len); - if (connfd == -1) - err(1, "accept"); - - if (vflag) - report_connect((struct sockaddr *)&cliaddr, len); - - readwrite(connfd); - close(connfd); - } - - if (family != AF_UNIX) - close(s); - else if (uflag) { - if (connect(s, NULL, 0) < 0) - err(1, "connect"); - } - - if (!kflag) - break; - } - } else if (family == AF_UNIX) { - ret = 0; - - if ((s = unix_connect(host)) > 0 && !zflag) { - readwrite(s); - close(s); - } else - ret = 1; - - if (uflag) - unlink(unix_dg_tmp_socket); - exit(ret); - - } else { - int i = 0; - - /* Construct the portlist[] array. */ - build_ports(uport); - - /* Cycle through portlist, connecting to each port. */ - for (i = 0; portlist[i] != NULL; i++) { - if (s) - close(s); - - if (xflag) - s = socks_connect(host, portlist[i], hints, - proxyhost, proxyport, proxyhints, socksv, - Pflag); - else - s = remote_connect(host, portlist[i], hints); - - if (s < 0) - continue; - - ret = 0; - if (vflag || zflag) { - /* For UDP, make sure we are connected. */ - if (uflag) { - if (udptest(s) == -1) { - ret = 1; - continue; - } - } - - /* Don't look up port if -n. */ - if (nflag) - sv = NULL; - else { - sv = getservbyport( - ntohs(atoi(portlist[i])), - uflag ? "udp" : "tcp"); - } - - fprintf(stderr, - "Connection to %s %s port [%s/%s] " - "succeeded!\n", host, portlist[i], - uflag ? "udp" : "tcp", - sv ? sv->s_name : "*"); - } - if (!zflag) - readwrite(s); - } - } - - if (s) - close(s); - - exit(ret); -} - -/* - * unix_bind() - * Returns a unix socket bound to the given path - */ -int -unix_bind(char *path) -{ - struct sockaddr_un sun; - int s; - - /* Create unix domain socket. */ - if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM, - 0)) < 0) - return (-1); - - memset(&sun, 0, sizeof(struct sockaddr_un)); - sun.sun_family = AF_UNIX; - - if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= - sizeof(sun.sun_path)) { - close(s); - errno = ENAMETOOLONG; - return (-1); - } - - if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { - close(s); - return (-1); - } - return (s); -} - -/* - * unix_connect() - * Returns a socket connected to a local unix socket. Returns -1 on failure. - */ -int -unix_connect(char *path) -{ - struct sockaddr_un sun; - int s; - - if (uflag) { - if ((s = unix_bind(unix_dg_tmp_socket)) < 0) - return (-1); - } else { - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - return (-1); - } - (void)fcntl(s, F_SETFD, 1); - - memset(&sun, 0, sizeof(struct sockaddr_un)); - sun.sun_family = AF_UNIX; - - if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= - sizeof(sun.sun_path)) { - close(s); - errno = ENAMETOOLONG; - return (-1); - } - if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { - close(s); - return (-1); - } - return (s); - -} - -/* - * unix_listen() - * Create a unix domain socket, and listen on it. - */ -int -unix_listen(char *path) -{ - int s; - if ((s = unix_bind(path)) < 0) - return (-1); - - if (listen(s, 5) < 0) { - close(s); - return (-1); - } - return (s); -} - -/* - * remote_connect() - * Returns a socket connected to a remote host. Properly binds to a local - * port or source address if needed. Returns -1 on failure. - */ -int -remote_connect(const char *host, const char *port, struct addrinfo hints) -{ - struct addrinfo *res, *res0; - int s, error, on = 1; - - if ((error = getaddrinfo(host, port, &hints, &res))) - errx(1, "getaddrinfo: %s", gai_strerror(error)); - - res0 = res; - do { - if ((s = socket(res0->ai_family, res0->ai_socktype, - res0->ai_protocol)) < 0) - continue; - - if (rtableid) { - if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid, - sizeof(rtableid)) == -1) - err(1, "setsockopt SO_RTABLE"); - } - - /* Bind to a local port or source address if specified. */ - if (sflag || pflag) { - struct addrinfo ahints, *ares; - - /* try SO_BINDANY, but don't insist */ - setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on)); - memset(&ahints, 0, sizeof(struct addrinfo)); - ahints.ai_family = res0->ai_family; - ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; - ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; - ahints.ai_flags = AI_PASSIVE; - if ((error = getaddrinfo(sflag, pflag, &ahints, &ares))) - errx(1, "getaddrinfo: %s", gai_strerror(error)); - - if (bind(s, (struct sockaddr *)ares->ai_addr, - ares->ai_addrlen) < 0) - errx(1, "bind failed: %s", strerror(errno)); - freeaddrinfo(ares); - } - - set_common_sockopts(s); - - if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0) - break; - else if (vflag) - warn("connect to %s port %s (%s) failed", host, port, - uflag ? "udp" : "tcp"); - - close(s); - s = -1; - } while ((res0 = res0->ai_next) != NULL); - - freeaddrinfo(res); - - return (s); -} - -int -timeout_connect(int s, const struct sockaddr *name, socklen_t namelen) -{ - struct pollfd pfd; - socklen_t optlen; - int flags, optval; - int ret; - - if (timeout != -1) { - flags = fcntl(s, F_GETFL, 0); - if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) - err(1, "set non-blocking mode"); - } - - if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) { - pfd.fd = s; - pfd.events = POLLOUT; - if ((ret = poll(&pfd, 1, timeout)) == 1) { - optlen = sizeof(optval); - if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR, - &optval, &optlen)) == 0) { - errno = optval; - ret = optval == 0 ? 0 : -1; - } - } else if (ret == 0) { - errno = ETIMEDOUT; - ret = -1; - } else - err(1, "poll failed"); - } - - if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1) - err(1, "restoring flags"); - - return (ret); -} - -/* - * local_listen() - * Returns a socket listening on a local port, binds to specified source - * address. Returns -1 on failure. - */ -int -local_listen(char *host, char *port, struct addrinfo hints) -{ - struct addrinfo *res, *res0; - int s, ret, x = 1; - int error; - - /* Allow nodename to be null. */ - hints.ai_flags |= AI_PASSIVE; - - /* - * In the case of binding to a wildcard address - * default to binding to an ipv4 address. - */ - if (host == NULL && hints.ai_family == AF_UNSPEC) - hints.ai_family = AF_INET; - - if ((error = getaddrinfo(host, port, &hints, &res))) - errx(1, "getaddrinfo: %s", gai_strerror(error)); - - res0 = res; - do { - if ((s = socket(res0->ai_family, res0->ai_socktype, - res0->ai_protocol)) < 0) - continue; - - if (rtableid) { - if (setsockopt(s, IPPROTO_IP, SO_RTABLE, &rtableid, - sizeof(rtableid)) == -1) - err(1, "setsockopt SO_RTABLE"); - } - - ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); - if (ret == -1) - err(1, NULL); - - set_common_sockopts(s); - - if (bind(s, (struct sockaddr *)res0->ai_addr, - res0->ai_addrlen) == 0) - break; - - close(s); - s = -1; - } while ((res0 = res0->ai_next) != NULL); - - if (!uflag && s != -1) { - if (listen(s, 1) < 0) - err(1, "listen"); - } - - freeaddrinfo(res); - - return (s); -} - -/* - * readwrite() - * Loop that polls on the network file descriptor and stdin. - */ -void -readwrite(int nfd) -{ - struct pollfd pfd[2]; - unsigned char buf[16384]; - int n, wfd = fileno(stdin); - int lfd = fileno(stdout); - int plen; - - plen = 2048; - - /* Setup Network FD */ - pfd[0].fd = nfd; - pfd[0].events = POLLIN; - - /* Set up STDIN FD. */ - pfd[1].fd = wfd; - pfd[1].events = POLLIN; - - while (pfd[0].fd != -1) { - if (iflag) - sleep(iflag); - - if ((n = poll(pfd, 2 - dflag, timeout)) < 0) { - close(nfd); - err(1, "Polling Error"); - } - - if (n == 0) - return; - - if (pfd[0].revents & POLLIN) { - if ((n = read(nfd, buf, plen)) < 0) - return; - else if (n == 0) { - shutdown(nfd, SHUT_RD); - pfd[0].fd = -1; - pfd[0].events = 0; - } else { - if (tflag) - atelnet(nfd, buf, n); - if (atomicio(vwrite, lfd, buf, n) != n) - return; - } - } - - if (!dflag && pfd[1].revents & POLLIN) { - if ((n = read(wfd, buf, plen)) < 0) - return; - else if (n == 0) { - shutdown(nfd, SHUT_WR); - pfd[1].fd = -1; - pfd[1].events = 0; - } else { - if (atomicio(vwrite, nfd, buf, n) != n) - return; - } - } - } -} - -/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */ -void -atelnet(int nfd, unsigned char *buf, unsigned int size) -{ - unsigned char *p, *end; - unsigned char obuf[4]; - - if (size < 3) - return; - end = buf + size - 2; - - for (p = buf; p < end; p++) { - if (*p != IAC) - continue; - - obuf[0] = IAC; - p++; - if ((*p == WILL) || (*p == WONT)) - obuf[1] = DONT; - else if ((*p == DO) || (*p == DONT)) - obuf[1] = WONT; - else - continue; - - p++; - obuf[2] = *p; - if (atomicio(vwrite, nfd, obuf, 3) != 3) - warn("Write Error!"); - } -} - -/* - * build_ports() - * Build an array of ports in portlist[], listing each port - * that we should try to connect to. - */ -void -build_ports(char *p) -{ - const char *errstr; - char *n; - int hi, lo, cp; - int x = 0; - - if ((n = strchr(p, '-')) != NULL) { - *n = '\0'; - n++; - - /* Make sure the ports are in order: lowest->highest. */ - hi = strtonum(n, 1, PORT_MAX, &errstr); - if (errstr) - errx(1, "port number %s: %s", errstr, n); - lo = strtonum(p, 1, PORT_MAX, &errstr); - if (errstr) - errx(1, "port number %s: %s", errstr, p); - - if (lo > hi) { - cp = hi; - hi = lo; - lo = cp; - } - - /* Load ports sequentially. */ - for (cp = lo; cp <= hi; cp++) { - portlist[x] = calloc(1, PORT_MAX_LEN); - if (portlist[x] == NULL) - err(1, NULL); - snprintf(portlist[x], PORT_MAX_LEN, "%d", cp); - x++; - } - - /* Randomly swap ports. */ - if (rflag) { - int y; - char *c; - - for (x = 0; x <= (hi - lo); x++) { - y = (arc4random() & 0xFFFF) % (hi - lo); - c = portlist[x]; - portlist[x] = portlist[y]; - portlist[y] = c; - } - } - } else { - hi = strtonum(p, 1, PORT_MAX, &errstr); - if (errstr) - errx(1, "port number %s: %s", errstr, p); - portlist[0] = strdup(p); - if (portlist[0] == NULL) - err(1, NULL); - } -} - -/* - * udptest() - * Do a few writes to see if the UDP port is there. - * Fails once PF state table is full. - */ -int -udptest(int s) -{ - int i, ret; - - for (i = 0; i <= 3; i++) { - if (write(s, "X", 1) == 1) - ret = 1; - else - ret = -1; - } - return (ret); -} - -void -set_common_sockopts(int s) -{ - int x = 1; - - if (Sflag) { - if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, - &x, sizeof(x)) == -1) - err(1, NULL); - } - if (Dflag) { - if (setsockopt(s, SOL_SOCKET, SO_DEBUG, - &x, sizeof(x)) == -1) - err(1, NULL); - } - if (Tflag != -1) { - if (setsockopt(s, IPPROTO_IP, IP_TOS, - &Tflag, sizeof(Tflag)) == -1) - err(1, "set IP ToS"); - } - if (Iflag) { - if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, - &Iflag, sizeof(Iflag)) == -1) - err(1, "set TCP receive buffer size"); - } - if (Oflag) { - if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, - &Oflag, sizeof(Oflag)) == -1) - err(1, "set TCP send buffer size"); - } -} - -int -map_tos(char *s, int *val) -{ - /* DiffServ Codepoints and other TOS mappings */ - const struct toskeywords { - const char *keyword; - int val; - } *t, toskeywords[] = { - { "af11", IPTOS_DSCP_AF11 }, - { "af12", IPTOS_DSCP_AF12 }, - { "af13", IPTOS_DSCP_AF13 }, - { "af21", IPTOS_DSCP_AF21 }, - { "af22", IPTOS_DSCP_AF22 }, - { "af23", IPTOS_DSCP_AF23 }, - { "af31", IPTOS_DSCP_AF31 }, - { "af32", IPTOS_DSCP_AF32 }, - { "af33", IPTOS_DSCP_AF33 }, - { "af41", IPTOS_DSCP_AF41 }, - { "af42", IPTOS_DSCP_AF42 }, - { "af43", IPTOS_DSCP_AF43 }, - { "critical", IPTOS_PREC_CRITIC_ECP }, - { "cs0", IPTOS_DSCP_CS0 }, - { "cs1", IPTOS_DSCP_CS1 }, - { "cs2", IPTOS_DSCP_CS2 }, - { "cs3", IPTOS_DSCP_CS3 }, - { "cs4", IPTOS_DSCP_CS4 }, - { "cs5", IPTOS_DSCP_CS5 }, - { "cs6", IPTOS_DSCP_CS6 }, - { "cs7", IPTOS_DSCP_CS7 }, - { "ef", IPTOS_DSCP_EF }, - { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, - { "lowdelay", IPTOS_LOWDELAY }, - { "netcontrol", IPTOS_PREC_NETCONTROL }, - { "reliability", IPTOS_RELIABILITY }, - { "throughput", IPTOS_THROUGHPUT }, - { NULL, -1 }, - }; - - for (t = toskeywords; t->keyword != NULL; t++) { - if (strcmp(s, t->keyword) == 0) { - *val = t->val; - return (1); - } - } - - return (0); -} - -void -report_connect(const struct sockaddr *sa, socklen_t salen) -{ - char remote_host[NI_MAXHOST]; - char remote_port[NI_MAXSERV]; - int herr; - int flags = NI_NUMERICSERV; - - if (nflag) - flags |= NI_NUMERICHOST; - - if ((herr = getnameinfo(sa, salen, - remote_host, sizeof(remote_host), - remote_port, sizeof(remote_port), - flags)) != 0) { - if (herr == EAI_SYSTEM) - err(1, "getnameinfo"); - else - errx(1, "getnameinfo: %s", gai_strerror(herr)); - } - - fprintf(stderr, - "Connection from %s %s " - "received!\n", remote_host, remote_port); -} - -void -help(void) -{ - usage(0); - fprintf(stderr, "\tCommand Summary:\n\ - \t-4 Use IPv4\n\ - \t-6 Use IPv6\n\ - \t-D Enable the debug socket option\n\ - \t-d Detach from stdin\n\ - \t-h This help text\n\ - \t-I length TCP receive buffer length\n\ - \t-i secs\t Delay interval for lines sent, ports scanned\n\ - \t-k Keep inbound sockets open for multiple connects\n\ - \t-l Listen mode, for inbound connects\n\ - \t-n Suppress name/port resolutions\n\ - \t-O length TCP send buffer length\n\ - \t-P proxyuser\tUsername for proxy authentication\n\ - \t-p port\t Specify local port for remote connects\n\ - \t-r Randomize remote ports\n\ - \t-S Enable the TCP MD5 signature option\n\ - \t-s addr\t Local source address\n\ - \t-T toskeyword\tSet IP Type of Service\n\ - \t-t Answer TELNET negotiation\n\ - \t-U Use UNIX domain socket\n\ - \t-u UDP mode\n\ - \t-V rtable Specify alternate routing table\n\ - \t-v Verbose\n\ - \t-w secs\t Timeout for connects and final net reads\n\ - \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ - \t-x addr[:port]\tSpecify proxy address and port\n\ - \t-z Zero-I/O mode [used for scanning]\n\ - Port numbers can be individual or ranges: lo-hi [inclusive]\n"); - exit(1); -} - -void -usage(int ret) -{ - fprintf(stderr, - "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n" - "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n" - "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" - "\t [-x proxy_address[:port]] [destination] [port]\n"); - if (ret) - exit(1); -} diff --git a/src/usr.bin/nc/socks.c b/src/usr.bin/nc/socks.c deleted file mode 100644 index f8adda463a..0000000000 --- a/src/usr.bin/nc/socks.c +++ /dev/null @@ -1,340 +0,0 @@ -/* $OpenBSD: socks.c,v 1.20 2012/03/08 09:56:28 espie Exp $ */ - -/* - * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. - * Copyright (c) 2004, 2005 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "atomicio.h" - -#define SOCKS_PORT "1080" -#define HTTP_PROXY_PORT "3128" -#define HTTP_MAXHDRS 64 -#define SOCKS_V5 5 -#define SOCKS_V4 4 -#define SOCKS_NOAUTH 0 -#define SOCKS_NOMETHOD 0xff -#define SOCKS_CONNECT 1 -#define SOCKS_IPV4 1 -#define SOCKS_DOMAIN 3 -#define SOCKS_IPV6 4 - -int remote_connect(const char *, const char *, struct addrinfo); -int socks_connect(const char *, const char *, struct addrinfo, - const char *, const char *, struct addrinfo, int, - const char *); - -static int -decode_addrport(const char *h, const char *p, struct sockaddr *addr, - socklen_t addrlen, int v4only, int numeric) -{ - int r; - struct addrinfo hints, *res; - - bzero(&hints, sizeof(hints)); - hints.ai_family = v4only ? PF_INET : PF_UNSPEC; - hints.ai_flags = numeric ? AI_NUMERICHOST : 0; - hints.ai_socktype = SOCK_STREAM; - r = getaddrinfo(h, p, &hints, &res); - /* Don't fatal when attempting to convert a numeric address */ - if (r != 0) { - if (!numeric) { - errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p, - gai_strerror(r)); - } - return (-1); - } - if (addrlen < res->ai_addrlen) { - freeaddrinfo(res); - errx(1, "internal error: addrlen < res->ai_addrlen"); - } - memcpy(addr, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); - return (0); -} - -static int -proxy_read_line(int fd, char *buf, size_t bufsz) -{ - size_t off; - - for(off = 0;;) { - if (off >= bufsz) - errx(1, "proxy read too long"); - if (atomicio(read, fd, buf + off, 1) != 1) - err(1, "proxy read"); - /* Skip CR */ - if (buf[off] == '\r') - continue; - if (buf[off] == '\n') { - buf[off] = '\0'; - break; - } - off++; - } - return (off); -} - -static const char * -getproxypass(const char *proxyuser, const char *proxyhost) -{ - char prompt[512]; - static char pw[256]; - - snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ", - proxyuser, proxyhost); - if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL) - errx(1, "Unable to read proxy passphrase"); - return (pw); -} - -int -socks_connect(const char *host, const char *port, - struct addrinfo hints __attribute__ ((__unused__)), - const char *proxyhost, const char *proxyport, struct addrinfo proxyhints, - int socksv, const char *proxyuser) -{ - int proxyfd, r, authretry = 0; - size_t hlen, wlen; - unsigned char buf[1024]; - size_t cnt; - struct sockaddr_storage addr; - struct sockaddr_in *in4 = (struct sockaddr_in *)&addr; - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr; - in_port_t serverport; - const char *proxypass = NULL; - - if (proxyport == NULL) - proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT; - - /* Abuse API to lookup port */ - if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr, - sizeof(addr), 1, 1) == -1) - errx(1, "unknown port \"%.64s\"", port); - serverport = in4->sin_port; - - again: - if (authretry++ > 3) - errx(1, "Too many authentication failures"); - - proxyfd = remote_connect(proxyhost, proxyport, proxyhints); - - if (proxyfd < 0) - return (-1); - - if (socksv == 5) { - if (decode_addrport(host, port, (struct sockaddr *)&addr, - sizeof(addr), 0, 1) == -1) - addr.ss_family = 0; /* used in switch below */ - - /* Version 5, one method: no authentication */ - buf[0] = SOCKS_V5; - buf[1] = 1; - buf[2] = SOCKS_NOAUTH; - cnt = atomicio(vwrite, proxyfd, buf, 3); - if (cnt != 3) - err(1, "write failed (%zu/3)", cnt); - - cnt = atomicio(read, proxyfd, buf, 2); - if (cnt != 2) - err(1, "read failed (%zu/3)", cnt); - - if (buf[1] == SOCKS_NOMETHOD) - errx(1, "authentication method negotiation failed"); - - switch (addr.ss_family) { - case 0: - /* Version 5, connect: domain name */ - - /* Max domain name length is 255 bytes */ - hlen = strlen(host); - if (hlen > 255) - errx(1, "host name too long for SOCKS5"); - buf[0] = SOCKS_V5; - buf[1] = SOCKS_CONNECT; - buf[2] = 0; - buf[3] = SOCKS_DOMAIN; - buf[4] = hlen; - memcpy(buf + 5, host, hlen); - memcpy(buf + 5 + hlen, &serverport, sizeof serverport); - wlen = 7 + hlen; - break; - case AF_INET: - /* Version 5, connect: IPv4 address */ - buf[0] = SOCKS_V5; - buf[1] = SOCKS_CONNECT; - buf[2] = 0; - buf[3] = SOCKS_IPV4; - memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); - memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port); - wlen = 10; - break; - case AF_INET6: - /* Version 5, connect: IPv6 address */ - buf[0] = SOCKS_V5; - buf[1] = SOCKS_CONNECT; - buf[2] = 0; - buf[3] = SOCKS_IPV6; - memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr); - memcpy(buf + 20, &in6->sin6_port, - sizeof in6->sin6_port); - wlen = 22; - break; - default: - errx(1, "internal error: silly AF"); - } - - cnt = atomicio(vwrite, proxyfd, buf, wlen); - if (cnt != wlen) - err(1, "write failed (%zu/%zu)", cnt, wlen); - - cnt = atomicio(read, proxyfd, buf, 4); - if (cnt != 4) - err(1, "read failed (%zu/4)", cnt); - if (buf[1] != 0) - errx(1, "connection failed, SOCKS error %d", buf[1]); - switch (buf[3]) { - case SOCKS_IPV4: - cnt = atomicio(read, proxyfd, buf + 4, 6); - if (cnt != 6) - err(1, "read failed (%zu/6)", cnt); - break; - case SOCKS_IPV6: - cnt = atomicio(read, proxyfd, buf + 4, 18); - if (cnt != 18) - err(1, "read failed (%zu/18)", cnt); - break; - default: - errx(1, "connection failed, unsupported address type"); - } - } else if (socksv == 4) { - /* This will exit on lookup failure */ - decode_addrport(host, port, (struct sockaddr *)&addr, - sizeof(addr), 1, 0); - - /* Version 4 */ - buf[0] = SOCKS_V4; - buf[1] = SOCKS_CONNECT; /* connect */ - memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port); - memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); - buf[8] = 0; /* empty username */ - wlen = 9; - - cnt = atomicio(vwrite, proxyfd, buf, wlen); - if (cnt != wlen) - err(1, "write failed (%zu/%zu)", cnt, wlen); - - cnt = atomicio(read, proxyfd, buf, 8); - if (cnt != 8) - err(1, "read failed (%zu/8)", cnt); - if (buf[1] != 90) - errx(1, "connection failed, SOCKS error %d", buf[1]); - } else if (socksv == -1) { - /* HTTP proxy CONNECT */ - - /* Disallow bad chars in hostname */ - if (strcspn(host, "\r\n\t []:") != strlen(host)) - errx(1, "Invalid hostname"); - - /* Try to be sane about numeric IPv6 addresses */ - if (strchr(host, ':') != NULL) { - r = snprintf(buf, sizeof(buf), - "CONNECT [%s]:%d HTTP/1.0\r\n", - host, ntohs(serverport)); - } else { - r = snprintf(buf, sizeof(buf), - "CONNECT %s:%d HTTP/1.0\r\n", - host, ntohs(serverport)); - } - if (r == -1 || (size_t)r >= sizeof(buf)) - errx(1, "hostname too long"); - r = strlen(buf); - - cnt = atomicio(vwrite, proxyfd, buf, r); - if (cnt != r) - err(1, "write failed (%zu/%d)", cnt, r); - - if (authretry > 1) { - char resp[1024]; - - proxypass = getproxypass(proxyuser, proxyhost); - r = snprintf(buf, sizeof(buf), "%s:%s", - proxyuser, proxypass); - if (r == -1 || (size_t)r >= sizeof(buf) || - b64_ntop(buf, strlen(buf), resp, - sizeof(resp)) == -1) - errx(1, "Proxy username/password too long"); - r = snprintf(buf, sizeof(buf), "Proxy-Authorization: " - "Basic %s\r\n", resp); - if (r == -1 || (size_t)r >= sizeof(buf)) - errx(1, "Proxy auth response too long"); - r = strlen(buf); - if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r) - err(1, "write failed (%zu/%d)", cnt, r); - } - - /* Terminate headers */ - if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2) - err(1, "write failed (2/%d)", r); - - /* Read status reply */ - proxy_read_line(proxyfd, buf, sizeof(buf)); - if (proxyuser != NULL && - strncmp(buf, "HTTP/1.0 407 ", 12) == 0) { - if (authretry > 1) { - fprintf(stderr, "Proxy authentication " - "failed\n"); - } - close(proxyfd); - goto again; - } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 && - strncmp(buf, "HTTP/1.1 200 ", 12) != 0) - errx(1, "Proxy error: \"%s\"", buf); - - /* Headers continue until we hit an empty line */ - for (r = 0; r < HTTP_MAXHDRS; r++) { - proxy_read_line(proxyfd, buf, sizeof(buf)); - if (*buf == '\0') - break; - } - if (*buf != '\0') - errx(1, "Too many proxy headers received"); - } else - errx(1, "Unknown proxy protocol %d", socksv); - - return (proxyfd); -} -- cgit v1.2.3-55-g6feb