This commit was generated by cvs2svn to compensate for changes in r141261,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
8f70b0946d
56
contrib/netcat/atomicio.c
Normal file
56
contrib/netcat/atomicio.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
ssize_t atomicio(ssize_t (*f)(int, void *, size_t), int fd, void *_s, size_t n);
|
||||
|
||||
/*
|
||||
* ensure all of data on socket comes through. f==read || f==write
|
||||
*/
|
||||
ssize_t
|
||||
atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
|
||||
{
|
||||
char *s = _s;
|
||||
ssize_t res, pos = 0;
|
||||
|
||||
while (n > pos) {
|
||||
res = (f) (fd, s + pos, n - pos);
|
||||
switch (res) {
|
||||
case -1:
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
case 0:
|
||||
return (res);
|
||||
default:
|
||||
pos += res;
|
||||
}
|
||||
}
|
||||
return (pos);
|
||||
}
|
387
contrib/netcat/nc.1
Normal file
387
contrib/netcat/nc.1
Normal file
@ -0,0 +1,387 @@
|
||||
.\" $OpenBSD: nc.1,v 1.36 2005/01/07 10:11:31 jmc 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 June 25, 2001
|
||||
.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 interval
|
||||
.Op Fl p Ar source_port
|
||||
.Op Fl s Ar source_ip_address
|
||||
.Op Fl w Ar timeout
|
||||
.Op Fl X Ar proxy_protocol
|
||||
.Oo Xo
|
||||
.Fl x Ar proxy_address Ns Oo : Ns
|
||||
.Ar port Oc Oc
|
||||
.Xc
|
||||
.Op Ar hostname
|
||||
.Op Ar port Ns Bq Ar s
|
||||
.Ek
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
(or
|
||||
.Nm netcat )
|
||||
utility is used for just about anything under the sun involving TCP
|
||||
or UDP.
|
||||
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 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.
|
||||
.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 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_ip_address
|
||||
Specifies the IP of the interface which is used to send the packets.
|
||||
It is an error to use this option in conjunction with the
|
||||
.Fl l
|
||||
option.
|
||||
.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 Unix Domain Sockets.
|
||||
.It Fl u
|
||||
Use UDP instead of the default option of TCP.
|
||||
.It Fl v
|
||||
Have
|
||||
.Nm
|
||||
give more verbose output.
|
||||
.It Fl w Ar timeout
|
||||
If a connection and stdin are idle for more than
|
||||
.Ar timeout
|
||||
seconds, then the connection is silently closed.
|
||||
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_version
|
||||
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 hostname
|
||||
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 hostname
|
||||
can be a numerical IP address or a symbolic hostname
|
||||
(unless the
|
||||
.Fl n
|
||||
option is given).
|
||||
In general, a hostname must be specified,
|
||||
unless the
|
||||
.Fl l
|
||||
option is given
|
||||
(in which case the local host is used).
|
||||
.Pp
|
||||
.Ar port Ns Op Ar s
|
||||
can be single integers or ranges.
|
||||
Ranges are in the form nn-mm.
|
||||
In general,
|
||||
a destination port must be specified,
|
||||
unless the
|
||||
.Fl U
|
||||
option is given
|
||||
(in which case a socket must be specified).
|
||||
.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:
|
||||
.Pp
|
||||
.Dl $ echo \&"GET\&" | nc host.example.com 80
|
||||
.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
|
||||
not to initiate a connection,
|
||||
together with the
|
||||
.Fl v
|
||||
.Pq verbose
|
||||
flag,
|
||||
to report open ports.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ nc -vz 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 hostname, using port 31337 as
|
||||
the source port, with a timeout of 5 seconds:
|
||||
.Pp
|
||||
.Dl $ nc -p 31337 -w 5 hostname 42
|
||||
.Pp
|
||||
Open a UDP connection to port 53 of hostname:
|
||||
.Pp
|
||||
.Dl $ nc -u hostname 53
|
||||
.Pp
|
||||
Open a TCP connection to port 42 of example.host using 10.1.2.3 as the
|
||||
IP for the local end of the connection:
|
||||
.Pp
|
||||
.Dl $ nc -s 10.1.2.3 example.host 42
|
||||
.Pp
|
||||
Send UDP packets to ports 20-30 of example.host, and report which ones
|
||||
responded with an ICMP packet after three seconds:
|
||||
.Pp
|
||||
.Dl $ nc -uvz -w 3 hostname 20-30
|
||||
.Pp
|
||||
Create and listen on a Unix Domain Socket:
|
||||
.Pp
|
||||
.Dl $ nc -lU /var/tmp/dsocket
|
||||
.Pp
|
||||
Connect to port 42 of hostname via an HTTP proxy at 10.2.3.4, port 8080:
|
||||
.Pp
|
||||
.Dl $ nc -x10.2.3.4:8080 -Xconnect hostname 42
|
||||
.Sh SEE ALSO
|
||||
.Xr cat 1
|
||||
.Sh AUTHORS
|
||||
Original implementation by *Hobbit*
|
||||
.Aq hobbit@avian.org .
|
||||
.br
|
||||
Rewritten with IPv6 support by
|
||||
.An Eric Jackson Aq ericj@monkey.org .
|
802
contrib/netcat/netcat.c
Normal file
802
contrib/netcat/netcat.c
Normal file
@ -0,0 +1,802 @@
|
||||
/* $OpenBSD: netcat.c,v 1.76 2004/12/10 16:51:31 hshoexer Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
|
||||
*
|
||||
* 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* <hobbit@avian.org>.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/telnet.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <poll.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.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
|
||||
|
||||
/* Command Line Options */
|
||||
int dflag; /* detached, no stdin */
|
||||
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; /* 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 Sflag; /* TCP MD5 signature option */
|
||||
|
||||
int timeout = -1;
|
||||
int family = AF_UNSPEC;
|
||||
char *portlist[PORT_MAX+1];
|
||||
|
||||
ssize_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
|
||||
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(char *, char *, struct addrinfo);
|
||||
int socks_connect(char *, char *, struct addrinfo, char *, char *,
|
||||
struct addrinfo, int);
|
||||
int udptest(int);
|
||||
int unix_connect(char *);
|
||||
int unix_listen(char *);
|
||||
void usage(int);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, s, ret, socksv;
|
||||
char *host, *uport, *endp;
|
||||
struct addrinfo hints;
|
||||
struct servent *sv;
|
||||
socklen_t len;
|
||||
struct sockaddr_storage cliaddr;
|
||||
char *proxy;
|
||||
char *proxyhost = "", *proxyport = NULL;
|
||||
struct addrinfo proxyhints;
|
||||
|
||||
ret = 1;
|
||||
s = 0;
|
||||
socksv = 5;
|
||||
host = NULL;
|
||||
uport = NULL;
|
||||
endp = NULL;
|
||||
sv = NULL;
|
||||
|
||||
while ((ch = getopt(argc, argv, "46Ddhi:klnp:rSs:tUuvw: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 = (int)strtoul(optarg, &endp, 10);
|
||||
if (iflag < 0 || *endp != '\0')
|
||||
errx(1, "interval cannot be negative");
|
||||
break;
|
||||
case 'k':
|
||||
kflag = 1;
|
||||
break;
|
||||
case 'l':
|
||||
lflag = 1;
|
||||
break;
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
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':
|
||||
vflag = 1;
|
||||
break;
|
||||
case 'w':
|
||||
timeout = (int)strtoul(optarg, &endp, 10);
|
||||
if (timeout < 0 || *endp != '\0')
|
||||
errx(1, "timeout cannot be negative");
|
||||
if (timeout >= (INT_MAX / 1000))
|
||||
errx(1, "timeout too large");
|
||||
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 'S':
|
||||
Sflag = 1;
|
||||
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) {
|
||||
if (uflag)
|
||||
errx(1, "cannot use -u and -U");
|
||||
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");
|
||||
|
||||
/* 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)
|
||||
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, we will use recvfrom() initially
|
||||
* to wait for a caller, then use the regular
|
||||
* functions to talk to the caller.
|
||||
*/
|
||||
if (uflag) {
|
||||
int rv;
|
||||
char buf[1024];
|
||||
struct sockaddr_storage z;
|
||||
|
||||
len = sizeof(z);
|
||||
rv = recvfrom(s, buf, sizeof(buf), 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");
|
||||
|
||||
connfd = s;
|
||||
} else {
|
||||
connfd = accept(s, (struct sockaddr *)&cliaddr,
|
||||
&len);
|
||||
}
|
||||
|
||||
readwrite(connfd);
|
||||
close(connfd);
|
||||
if (family != AF_UNIX)
|
||||
close(s);
|
||||
|
||||
if (!kflag)
|
||||
break;
|
||||
}
|
||||
} else if (family == AF_UNIX) {
|
||||
ret = 0;
|
||||
|
||||
if ((s = unix_connect(host)) > 0 && !zflag) {
|
||||
readwrite(s);
|
||||
close(s);
|
||||
} else
|
||||
ret = 1;
|
||||
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
||||
printf("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_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 ((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)
|
||||
{
|
||||
struct sockaddr_un sun;
|
||||
int s;
|
||||
|
||||
/* Create unix domain socket. */
|
||||
if ((s = socket(AF_UNIX, 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);
|
||||
}
|
||||
|
||||
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(char *host, char *port, struct addrinfo hints)
|
||||
{
|
||||
struct addrinfo *res, *res0;
|
||||
int s, error, x = 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;
|
||||
|
||||
/* Bind to a local port or source address if specified. */
|
||||
if (sflag || pflag) {
|
||||
struct addrinfo ahints, *ares;
|
||||
|
||||
if (!(sflag && pflag)) {
|
||||
if (!sflag)
|
||||
sflag = NULL;
|
||||
else
|
||||
pflag = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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 (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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
|
||||
if (ret == -1)
|
||||
err(1, NULL);
|
||||
if (Sflag) {
|
||||
ret = setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
|
||||
&x, sizeof(x));
|
||||
if (ret == -1)
|
||||
err(1, NULL);
|
||||
}
|
||||
if (Dflag) {
|
||||
if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
|
||||
&x, sizeof(x)) == -1)
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
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[BUFSIZ];
|
||||
int wfd = fileno(stdin), n;
|
||||
int lfd = fileno(stdout);
|
||||
|
||||
/* 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, sizeof(buf))) < 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((ssize_t (*)(int, void *, size_t))write,
|
||||
lfd, buf, n) != n)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dflag && pfd[1].revents & POLLIN) {
|
||||
if ((n = read(wfd, buf, sizeof(buf))) < 0)
|
||||
return;
|
||||
else if (n == 0) {
|
||||
shutdown(nfd, SHUT_WR);
|
||||
pfd[1].fd = -1;
|
||||
pfd[1].events = 0;
|
||||
} else {
|
||||
if (atomicio((ssize_t (*)(int, void *, size_t))write,
|
||||
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];
|
||||
|
||||
end = buf + size;
|
||||
obuf[0] = '\0';
|
||||
|
||||
for (p = buf; p < end; p++) {
|
||||
if (*p != IAC)
|
||||
break;
|
||||
|
||||
obuf[0] = IAC;
|
||||
p++;
|
||||
if ((*p == WILL) || (*p == WONT))
|
||||
obuf[1] = DONT;
|
||||
if ((*p == DO) || (*p == DONT))
|
||||
obuf[1] = WONT;
|
||||
if (obuf) {
|
||||
p++;
|
||||
obuf[2] = *p;
|
||||
obuf[3] = '\0';
|
||||
if (atomicio((ssize_t (*)(int, void *, size_t))write,
|
||||
nfd, obuf, 3) != 3)
|
||||
warnx("Write Error!");
|
||||
obuf[0] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* build_ports()
|
||||
* Build an array or ports in portlist[], listing each port
|
||||
* that we should try to connect to.
|
||||
*/
|
||||
void
|
||||
build_ports(char *p)
|
||||
{
|
||||
char *n, *endp;
|
||||
int hi, lo, cp;
|
||||
int x = 0;
|
||||
|
||||
if ((n = strchr(p, '-')) != NULL) {
|
||||
if (lflag)
|
||||
errx(1, "Cannot use -l with multiple ports!");
|
||||
|
||||
*n = '\0';
|
||||
n++;
|
||||
|
||||
/* Make sure the ports are in order: lowest->highest. */
|
||||
hi = (int)strtoul(n, &endp, 10);
|
||||
if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
|
||||
errx(1, "port range not valid");
|
||||
lo = (int)strtoul(p, &endp, 10);
|
||||
if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
|
||||
errx(1, "port range not valid");
|
||||
|
||||
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 = (int)strtoul(p, &endp, 10);
|
||||
if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
|
||||
errx(1, "port range not valid");
|
||||
portlist[0] = calloc(1, PORT_MAX_LEN);
|
||||
if (portlist[0] == NULL)
|
||||
err(1, NULL);
|
||||
portlist[0] = p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* udptest()
|
||||
* Do a few writes to see if the UDP port is there.
|
||||
* XXX - Better way of doing this? Doesn't work for IPv6.
|
||||
* Also fails after around 100 ports checked.
|
||||
*/
|
||||
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
|
||||
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 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-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 Answer TELNET negotiation\n\
|
||||
\t-U Use UNIX domain socket\n\
|
||||
\t-u UDP mode\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 interval] [-p source_port]\n");
|
||||
fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X proxy_version]\n");
|
||||
fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n");
|
||||
if (ret)
|
||||
exit(1);
|
||||
}
|
235
contrib/netcat/socks.c
Normal file
235
contrib/netcat/socks.c
Normal file
@ -0,0 +1,235 @@
|
||||
/* $OpenBSD: socks.c,v 1.9 2004/10/17 03:13:55 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Niklas Hallqvist. 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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.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
|
||||
|
||||
|
||||
int remote_connect(char *, char *, struct addrinfo);
|
||||
int socks_connect(char *host, char *port, struct addrinfo hints,
|
||||
char *proxyhost, char *proxyport, struct addrinfo proxyhints,
|
||||
int socksv);
|
||||
|
||||
static in_addr_t
|
||||
decode_addr(const char *s)
|
||||
{
|
||||
struct hostent *hp = gethostbyname (s);
|
||||
struct in_addr retval;
|
||||
|
||||
if (hp)
|
||||
return *(in_addr_t *)hp->h_addr_list[0];
|
||||
if (inet_aton (s, &retval))
|
||||
return retval.s_addr;
|
||||
errx (1, "cannot decode address \"%s\"", s);
|
||||
}
|
||||
|
||||
static in_port_t
|
||||
decode_port(const char *s)
|
||||
{
|
||||
struct servent *sp;
|
||||
in_port_t port;
|
||||
char *p;
|
||||
|
||||
port = strtol (s, &p, 10);
|
||||
if (s == p) {
|
||||
sp = getservbyname (s, "tcp");
|
||||
if (sp)
|
||||
return sp->s_port;
|
||||
}
|
||||
if (*s != '\0' && *p == '\0')
|
||||
return htons (port);
|
||||
errx (1, "cannot decode port \"%s\"", s);
|
||||
}
|
||||
|
||||
static int
|
||||
proxy_read_line(int fd, char *buf, int bufsz)
|
||||
{
|
||||
int r, off;
|
||||
|
||||
for(off = 0;;) {
|
||||
if (off >= bufsz)
|
||||
errx(1, "proxy read too long");
|
||||
if ((r = read(fd, buf + off, 1)) <= 0) {
|
||||
if (r == -1 && errno == EINTR)
|
||||
continue;
|
||||
err(1, "proxy read");
|
||||
}
|
||||
/* Skip CR */
|
||||
if (buf[off] == '\r')
|
||||
continue;
|
||||
if (buf[off] == '\n') {
|
||||
buf[off] = '\0';
|
||||
break;
|
||||
}
|
||||
off++;
|
||||
}
|
||||
return (off);
|
||||
}
|
||||
|
||||
int
|
||||
socks_connect(char *host, char *port, struct addrinfo hints,
|
||||
char *proxyhost, char *proxyport, struct addrinfo proxyhints,
|
||||
int socksv)
|
||||
{
|
||||
int proxyfd, r;
|
||||
unsigned char buf[1024];
|
||||
ssize_t cnt;
|
||||
in_addr_t serveraddr;
|
||||
in_port_t serverport;
|
||||
|
||||
if (proxyport == NULL)
|
||||
proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
|
||||
|
||||
proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
|
||||
|
||||
if (proxyfd < 0)
|
||||
return -1;
|
||||
|
||||
serveraddr = decode_addr (host);
|
||||
serverport = decode_port (port);
|
||||
|
||||
if (socksv == 5) {
|
||||
/* Version 5, one method: no authentication */
|
||||
buf[0] = SOCKS_V5;
|
||||
buf[1] = 1;
|
||||
buf[2] = SOCKS_NOAUTH;
|
||||
cnt = write (proxyfd, buf, 3);
|
||||
if (cnt == -1)
|
||||
err (1, "write failed");
|
||||
if (cnt != 3)
|
||||
errx (1, "short write, %d (expected 3)", cnt);
|
||||
|
||||
read (proxyfd, buf, 2);
|
||||
if (buf[1] == SOCKS_NOMETHOD)
|
||||
errx (1, "authentication method negotiation failed");
|
||||
|
||||
/* Version 5, connect: IPv4 address */
|
||||
buf[0] = SOCKS_V5;
|
||||
buf[1] = SOCKS_CONNECT;
|
||||
buf[2] = 0;
|
||||
buf[3] = SOCKS_IPV4;
|
||||
memcpy (buf + 4, &serveraddr, sizeof serveraddr);
|
||||
memcpy (buf + 8, &serverport, sizeof serverport);
|
||||
|
||||
/* XXX Handle short writes better */
|
||||
cnt = write (proxyfd, buf, 10);
|
||||
if (cnt == -1)
|
||||
err (1, "write failed");
|
||||
if (cnt != 10)
|
||||
errx (1, "short write, %d (expected 10)", cnt);
|
||||
|
||||
/* XXX Handle short reads better */
|
||||
cnt = read (proxyfd, buf, sizeof buf);
|
||||
if (cnt == -1)
|
||||
err (1, "read failed");
|
||||
if (cnt != 10)
|
||||
errx (1, "unexpected reply size %d (expected 10)", cnt);
|
||||
if (buf[1] != 0)
|
||||
errx (1, "connection failed, SOCKS error %d", buf[1]);
|
||||
} else if (socksv == 4) {
|
||||
/* Version 4 */
|
||||
buf[0] = SOCKS_V4;
|
||||
buf[1] = SOCKS_CONNECT; /* connect */
|
||||
memcpy (buf + 2, &serverport, sizeof serverport);
|
||||
memcpy (buf + 4, &serveraddr, sizeof serveraddr);
|
||||
buf[8] = 0; /* empty username */
|
||||
|
||||
cnt = write (proxyfd, buf, 9);
|
||||
if (cnt == -1)
|
||||
err (1, "write failed");
|
||||
if (cnt != 9)
|
||||
errx (1, "short write, %d (expected 9)", cnt);
|
||||
|
||||
/* XXX Handle short reads better */
|
||||
cnt = read (proxyfd, buf, 8);
|
||||
if (cnt == -1)
|
||||
err (1, "read failed");
|
||||
if (cnt != 8)
|
||||
errx (1, "unexpected reply size %d (expected 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\r\n",
|
||||
host, ntohs(serverport));
|
||||
} else {
|
||||
r = snprintf(buf, sizeof(buf),
|
||||
"CONNECT %s:%d HTTP/1.0\r\n\r\n",
|
||||
host, ntohs(serverport));
|
||||
}
|
||||
if (r == -1 || r >= sizeof(buf))
|
||||
errx (1, "hostname too long");
|
||||
r = strlen(buf);
|
||||
|
||||
/* XXX atomicio */
|
||||
cnt = write (proxyfd, buf, r);
|
||||
if (cnt == -1)
|
||||
err (1, "write failed");
|
||||
if (cnt != r)
|
||||
errx (1, "short write, %d (expected %d)", cnt, r);
|
||||
|
||||
/* Read reply */
|
||||
for (r = 0; r < HTTP_MAXHDRS; r++) {
|
||||
proxy_read_line(proxyfd, buf, sizeof(buf));
|
||||
if (r == 0 && strncmp(buf, "HTTP/1.0 200 ", 12) != 0)
|
||||
errx (1, "Proxy error: \"%s\"", buf);
|
||||
/* Discard headers until we hit an empty line */
|
||||
if (*buf == '\0')
|
||||
break;
|
||||
}
|
||||
} else
|
||||
errx (1, "Unknown proxy protocol %d", socksv);
|
||||
|
||||
return proxyfd;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user