2091 lines
53 KiB
Diff
2091 lines
53 KiB
Diff
diff -ruN netcat-openbsd-1.195/Makefile netcat-openbsd-1.195_patch/Makefile
|
||
--- netcat-openbsd-1.195/Makefile 2018-10-21 13:34:47.000000000 +0300
|
||
+++ netcat-openbsd-1.195_patch/Makefile 2020-06-05 08:07:13.079766639 +0300
|
||
@@ -2,7 +2,19 @@
|
||
|
||
PROG= nc
|
||
SRCS= netcat.c atomicio.c socks.c
|
||
-LDADD+= -ltls -lssl -lcrypto
|
||
-DPADD+= ${LIBTLS} ${LIBSSL} ${LIBCRYPTO}
|
||
|
||
-.include <bsd.prog.mk>
|
||
+PKG_CONFIG ?= pkg-config
|
||
+LIBS= `$(PKG_CONFIG) --libs libbsd` -lresolv
|
||
+OBJS= $(SRCS:.c=.o)
|
||
+CFLAGS= -g -O2
|
||
+LDFLAGS= -Wl,--no-add-needed
|
||
+
|
||
+all: nc
|
||
+nc: $(OBJS)
|
||
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o nc
|
||
+
|
||
+$(OBJS): %.o: %.c
|
||
+ $(CC) $(CFLAGS) -c $< -o $@
|
||
+
|
||
+clean:
|
||
+ rm -f $(OBJS) nc
|
||
diff -ruN netcat-openbsd-1.195/nc.1 netcat-openbsd-1.195_patch/nc.1
|
||
--- netcat-openbsd-1.195/nc.1 2018-10-21 13:34:47.000000000 +0300
|
||
+++ netcat-openbsd-1.195_patch/nc.1 2020-06-05 08:07:13.079766639 +0300
|
||
@@ -33,20 +33,15 @@
|
||
.Nd arbitrary TCP and UDP connections and listens
|
||
.Sh SYNOPSIS
|
||
.Nm nc
|
||
-.Op Fl 46cDdFhklNnrStUuvz
|
||
-.Op Fl C Ar certfile
|
||
-.Op Fl e Ar name
|
||
-.Op Fl H Ar hash
|
||
+.Op Fl 46bCDdFhklNnrStUuvZz
|
||
.Op Fl I Ar length
|
||
.Op Fl i Ar interval
|
||
-.Op Fl K Ar keyfile
|
||
.Op Fl M Ar ttl
|
||
.Op Fl m Ar minttl
|
||
.Op Fl O Ar length
|
||
-.Op Fl o Ar staplefile
|
||
.Op Fl P Ar proxy_username
|
||
.Op Fl p Ar source_port
|
||
-.Op Fl R Ar CAfile
|
||
+.Op Fl q Ar seconds
|
||
.Op Fl s Ar source
|
||
.Op Fl T Ar keyword
|
||
.Op Fl V Ar rtable
|
||
@@ -54,7 +49,6 @@
|
||
.Op Fl w Ar timeout
|
||
.Op Fl X Ar proxy_protocol
|
||
.Op Fl x Ar proxy_address Ns Op : Ns Ar port
|
||
-.Op Fl Z Ar peercertfile
|
||
.Op Ar destination
|
||
.Op Ar port
|
||
.Sh DESCRIPTION
|
||
@@ -99,28 +93,17 @@
|
||
Use IPv4 addresses only.
|
||
.It Fl 6
|
||
Use IPv6 addresses only.
|
||
-.It Fl C Ar certfile
|
||
-Load the public key part of the TLS peer certificate from
|
||
-.Ar certfile ,
|
||
-in PEM format.
|
||
-Requires
|
||
-.Fl c .
|
||
-.It Fl c
|
||
-Use TLS to connect or listen.
|
||
-Cannot be used together with any of the options
|
||
-.Fl FuU .
|
||
+.It Fl b
|
||
+Allow broadcast.
|
||
+.It Fl C
|
||
+Send CRLF as line-ending. Each line feed (LF) character from the input
|
||
+data is translated into CR+LF before being written to the socket. Line
|
||
+feed characters that are already preceded with a carriage return (CR)
|
||
+are not translated. Received data is not affected.
|
||
.It Fl D
|
||
Enable debugging on the socket.
|
||
.It Fl d
|
||
Do not attempt to read from stdin.
|
||
-.It Fl e Ar name
|
||
-Only accept the TLS peer certificate if it contains the
|
||
-.Ar name .
|
||
-Requires
|
||
-.Fl c .
|
||
-If not specified,
|
||
-.Ar destination
|
||
-is used.
|
||
.It Fl F
|
||
Pass the first connected socket using
|
||
.Xr sendmsg 2
|
||
@@ -137,18 +120,7 @@
|
||
.Cm ProxyUseFdpass
|
||
option).
|
||
Cannot be used with
|
||
-.Fl c
|
||
-or
|
||
.Fl U .
|
||
-.It Fl H Ar hash
|
||
-Only accept the TLS peer certificate if its hash returned from
|
||
-.Xr tls_peer_cert_hash 3
|
||
-matches
|
||
-.Ar hash .
|
||
-Requires
|
||
-.Fl c
|
||
-and cannot be used with
|
||
-.Fl T Cm noverify .
|
||
.It Fl h
|
||
Print out the
|
||
.Nm
|
||
@@ -160,12 +132,6 @@
|
||
.Ar interval
|
||
seconds between lines of text sent and received.
|
||
Also causes a delay time between connections to multiple ports.
|
||
-.It Fl K Ar keyfile
|
||
-Load the TLS private key from
|
||
-.Ar keyfile ,
|
||
-in PEM format.
|
||
-Requires
|
||
-.Fl c .
|
||
.It Fl k
|
||
When a connection is completed, listen for another one.
|
||
Requires
|
||
@@ -177,8 +143,20 @@
|
||
.It Fl l
|
||
Listen for an incoming connection rather than initiating a
|
||
connection to a remote host.
|
||
-Cannot be used together with any of the options
|
||
-.Fl psxz .
|
||
+The
|
||
+.Ar destination
|
||
+and
|
||
+.Ar port
|
||
+to listen on can be specified either as non-optional arguments, or with
|
||
+options
|
||
+.Fl s
|
||
+and
|
||
+.Fl p
|
||
+respectively.
|
||
+Cannot be used together with
|
||
+.Fl x
|
||
+or
|
||
+.Fl z .
|
||
Additionally, any timeouts specified with the
|
||
.Fl w
|
||
option are ignored.
|
||
@@ -196,15 +174,6 @@
|
||
hostnames or ports.
|
||
.It Fl O Ar length
|
||
Specify the size of the TCP send buffer.
|
||
-.It Fl o Ar staplefile
|
||
-During the TLS handshake, load data to be stapled from
|
||
-.Ar staplefile ,
|
||
-which is expected to contain an OCSP response from an OCSP server in
|
||
-DER format.
|
||
-Requires
|
||
-.Fl c
|
||
-and
|
||
-.Fl C .
|
||
.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.
|
||
@@ -213,15 +182,15 @@
|
||
Specify the source port
|
||
.Nm
|
||
should use, subject to privilege restrictions and availability.
|
||
-Cannot be used together with
|
||
-.Fl l .
|
||
-.It Fl R Ar CAfile
|
||
-Load the root CA bundle for TLS certificate verification from
|
||
-.Ar CAfile ,
|
||
-in PEM format, instead of
|
||
-.Pa /etc/ssl/cert.pem .
|
||
-Requires
|
||
-.Fl c .
|
||
+.It Fl q Ar seconds
|
||
+after EOF on stdin, wait the specified number of
|
||
+.Ar seconds
|
||
+and then quit. If
|
||
+.Ar seconds
|
||
+is negative, wait forever (default). Specifying a non-negative
|
||
+.Ar seconds
|
||
+implies
|
||
+.Fl N .
|
||
.It Fl r
|
||
Choose source and/or destination ports randomly
|
||
instead of sequentially within a range or in the order that the system
|
||
@@ -237,43 +206,14 @@
|
||
datagram sockets, specifies the local temporary socket file
|
||
to create and use so that datagrams can be received.
|
||
Cannot be used together with
|
||
-.Fl l
|
||
-or
|
||
.Fl x .
|
||
.It Fl T Ar keyword
|
||
-Change the IPv4 TOS/IPv6 traffic class value or the TLS options.
|
||
-.Pp
|
||
-For TLS options,
|
||
-.Ar keyword
|
||
-may be one of:
|
||
-.Cm noverify ,
|
||
-which disables certificate verification;
|
||
-.Cm noname ,
|
||
-which disables certificate name checking;
|
||
-.Cm clientcert ,
|
||
-which requires a client certificate on incoming connections; or
|
||
-.Cm muststaple ,
|
||
-which requires the peer to provide a valid stapled OCSP response
|
||
-with the handshake.
|
||
-The following TLS options specify a value in the form of a
|
||
-.Ar key Ns = Ns Ar value
|
||
-pair:
|
||
-.Cm ciphers ,
|
||
-which allows the supported TLS ciphers to be specified (see
|
||
-.Xr tls_config_set_ciphers 3
|
||
-for further details);
|
||
-.Cm protocols ,
|
||
-which allows the supported TLS protocols to be specified (see
|
||
-.Xr tls_config_parse_protocols 3
|
||
-for further details).
|
||
-Specifying TLS options requires
|
||
-.Fl c .
|
||
-.Pp
|
||
-For the IPv4 TOS/IPv6 traffic class value,
|
||
+Change the IPv4 TOS/IPv6 traffic class value.
|
||
.Ar keyword
|
||
may be one of
|
||
.Cm critical ,
|
||
.Cm inetcontrol ,
|
||
+.Cm lowcost ,
|
||
.Cm lowdelay ,
|
||
.Cm netcontrol ,
|
||
.Cm throughput ,
|
||
@@ -292,13 +232,13 @@
|
||
Use
|
||
.Ux Ns -domain
|
||
sockets.
|
||
-Cannot be used together with any of the options
|
||
-.Fl cFx .
|
||
+Cannot be used together with
|
||
+.Fl F
|
||
+or
|
||
+.Fl x .
|
||
.It Fl u
|
||
Use UDP instead of TCP.
|
||
Cannot be used together with
|
||
-.Fl c
|
||
-or
|
||
.Fl x .
|
||
For
|
||
.Ux Ns -domain
|
||
@@ -361,12 +301,8 @@
|
||
in square brackets.
|
||
A proxy cannot be used with any of the options
|
||
.Fl lsuU .
|
||
-.It Fl Z Ar peercertfile
|
||
-Save the peer certificates to
|
||
-.Ar peercertfile ,
|
||
-in PEM format.
|
||
-Requires
|
||
-.Fl c .
|
||
+.It Fl Z
|
||
+DCCP mode.
|
||
.It Fl z
|
||
Only scan for listening daemons, without sending any data to them.
|
||
Cannot be used together with
|
||
@@ -429,6 +365,54 @@
|
||
The connection may be terminated using an
|
||
.Dv EOF
|
||
.Pq Sq ^D .
|
||
+.Pp
|
||
+There is no
|
||
+.Fl c
|
||
+or
|
||
+.Fl e
|
||
+option in this netcat, but you still can execute a command after connection
|
||
+being established by redirecting file descriptors. Be cautious here because
|
||
+opening a port and let anyone connected execute arbitrary command on your
|
||
+site is DANGEROUS. If you really need to do this, here is an example:
|
||
+.Pp
|
||
+On
|
||
+.Sq server
|
||
+side:
|
||
+.Pp
|
||
+.Dl $ rm -f /tmp/f; mkfifo /tmp/f
|
||
+.Dl $ cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f
|
||
+.Pp
|
||
+On
|
||
+.Sq client
|
||
+side:
|
||
+.Pp
|
||
+.Dl $ nc host.example.com 1234
|
||
+.Dl $ (shell prompt from host.example.com)
|
||
+.Pp
|
||
+By doing this, you create a fifo at /tmp/f and make nc listen at port 1234
|
||
+of address 127.0.0.1 on
|
||
+.Sq server
|
||
+side, when a
|
||
+.Sq client
|
||
+establishes a connection successfully to that port, /bin/sh gets executed
|
||
+on
|
||
+.Sq server
|
||
+side and the shell prompt is given to
|
||
+.Sq client
|
||
+side.
|
||
+.Pp
|
||
+When connection is terminated,
|
||
+.Nm
|
||
+quits as well. Use
|
||
+.Fl k
|
||
+if you want it keep listening, but if the command quits this option won't
|
||
+restart it or keep
|
||
+.Nm
|
||
+running. Also don't forget to remove the file descriptor once you don't need
|
||
+it anymore:
|
||
+.Pp
|
||
+.Dl $ rm -f /tmp/f
|
||
+.Pp
|
||
.Sh DATA TRANSFER
|
||
The example in the previous section can be expanded to build a
|
||
basic data transfer model.
|
||
@@ -470,7 +454,7 @@
|
||
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
|
||
+$ nc [\-C] localhost 25 \*(Lt\*(Lt EOF
|
||
HELO host.example.com
|
||
MAIL FROM:\*(Ltuser@host.example.com\*(Gt
|
||
RCPT TO:\*(Ltuser2@host.example.com\*(Gt
|
||
@@ -488,15 +472,35 @@
|
||
flag can be used to tell
|
||
.Nm
|
||
to report open ports,
|
||
-rather than initiate a connection.
|
||
+rather than initiate a connection. Usually it's useful to turn on verbose
|
||
+output to stderr by use this option in conjunction with
|
||
+.Fl v
|
||
+option.
|
||
+.Pp
|
||
For example:
|
||
.Bd -literal -offset indent
|
||
-$ nc -z host.example.com 20-30
|
||
+$ nc \-zv 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.
|
||
+The port range was specified to limit the search to ports 20 \- 30, and is
|
||
+scanned by increasing order (unless the
|
||
+.Fl r
|
||
+flag is set).
|
||
+.Pp
|
||
+You can also specify a list of ports to scan, for example:
|
||
+.Bd -literal -offset indent
|
||
+$ nc \-zv host.example.com http 20 22-23
|
||
+nc: connect to host.example.com 80 (tcp) failed: Connection refused
|
||
+nc: connect to host.example.com 20 (tcp) failed: Connection refused
|
||
+Connection to host.example.com port [tcp/ssh] succeeded!
|
||
+nc: connect to host.example.com 23 (tcp) failed: Connection refused
|
||
+.Ed
|
||
+.Pp
|
||
+The ports are scanned by the order you given (unless the
|
||
+.Fl r
|
||
+flag is set).
|
||
.Pp
|
||
Alternatively, it might be useful to know which server software
|
||
is running, and which versions.
|
||
@@ -520,16 +524,6 @@
|
||
.Pp
|
||
.Dl $ nc -p 31337 -w 5 host.example.com 42
|
||
.Pp
|
||
-Open a TCP connection to port 443 of www.example.com, and negotiate TLS with
|
||
-any supported TLS protocol version and "compat" ciphers:
|
||
-.Pp
|
||
-.Dl $ nc -cv -T protocols=all -T ciphers=compat www.example.com 443
|
||
-.Pp
|
||
-Open a TCP connection to port 443 of www.google.ca, and negotiate TLS.
|
||
-Check for a different name in the certificate for validation:
|
||
-.Pp
|
||
-.Dl $ nc -cv -e adsf.au.doubleclick.net www.google.ca 443
|
||
-.Pp
|
||
Open a UDP connection to port 53 of host.example.com:
|
||
.Pp
|
||
.Dl $ nc -u host.example.com 53
|
||
@@ -571,6 +565,9 @@
|
||
.br
|
||
Rewritten with IPv6 support by
|
||
.An Eric Jackson Aq Mt ericj@monkey.org .
|
||
+.br
|
||
+Modified for Debian port by Aron Xu
|
||
+.Aq aron@debian.org .
|
||
.Sh CAVEATS
|
||
UDP port scans using the
|
||
.Fl uz
|
||
diff -ruN netcat-openbsd-1.195/netcat.c netcat-openbsd-1.195_patch/netcat.c
|
||
--- netcat-openbsd-1.195/netcat.c 2018-10-21 13:34:47.000000000 +0300
|
||
+++ netcat-openbsd-1.195_patch/netcat.c 2020-06-05 08:07:13.083766725 +0300
|
||
@@ -32,6 +32,8 @@
|
||
* *Hobbit* <hobbit@avian.org>.
|
||
*/
|
||
|
||
+#define _GNU_SOURCE
|
||
+
|
||
#include <sys/types.h>
|
||
#include <sys/socket.h>
|
||
#include <sys/uio.h>
|
||
@@ -41,20 +43,73 @@
|
||
#include <netinet/tcp.h>
|
||
#include <netinet/ip.h>
|
||
#include <arpa/telnet.h>
|
||
+#include <arpa/inet.h>
|
||
+#ifdef __linux__
|
||
+# include <linux/in6.h>
|
||
+#endif
|
||
+#if defined(TCP_MD5SIG) && defined(TCP_MD5SIG_MAXKEYLEN)
|
||
+# include <bsd/readpassphrase.h>
|
||
+#endif
|
||
+
|
||
+#ifndef IPTOS_LOWDELAY
|
||
+# define IPTOS_LOWDELAY 0x10
|
||
+# define IPTOS_THROUGHPUT 0x08
|
||
+# define IPTOS_RELIABILITY 0x04
|
||
+# define IPTOS_LOWCOST 0x02
|
||
+# define IPTOS_MINCOST IPTOS_LOWCOST
|
||
+#endif /* IPTOS_LOWDELAY */
|
||
+
|
||
+# ifndef IPTOS_DSCP_AF11
|
||
+# define IPTOS_DSCP_AF11 0x28
|
||
+# define IPTOS_DSCP_AF12 0x30
|
||
+# define IPTOS_DSCP_AF13 0x38
|
||
+# define IPTOS_DSCP_AF21 0x48
|
||
+# define IPTOS_DSCP_AF22 0x50
|
||
+# define IPTOS_DSCP_AF23 0x58
|
||
+# define IPTOS_DSCP_AF31 0x68
|
||
+# define IPTOS_DSCP_AF32 0x70
|
||
+# define IPTOS_DSCP_AF33 0x78
|
||
+# define IPTOS_DSCP_AF41 0x88
|
||
+# define IPTOS_DSCP_AF42 0x90
|
||
+# define IPTOS_DSCP_AF43 0x98
|
||
+# define IPTOS_DSCP_EF 0xb8
|
||
+#endif /* IPTOS_DSCP_AF11 */
|
||
+
|
||
+#ifndef IPTOS_DSCP_CS0
|
||
+# define IPTOS_DSCP_CS0 0x00
|
||
+# define IPTOS_DSCP_CS1 0x20
|
||
+# define IPTOS_DSCP_CS2 0x40
|
||
+# define IPTOS_DSCP_CS3 0x60
|
||
+# define IPTOS_DSCP_CS4 0x80
|
||
+# define IPTOS_DSCP_CS5 0xa0
|
||
+# define IPTOS_DSCP_CS6 0xc0
|
||
+# define IPTOS_DSCP_CS7 0xe0
|
||
+#endif /* IPTOS_DSCP_CS0 */
|
||
+
|
||
+#ifndef IPTOS_DSCP_EF
|
||
+# define IPTOS_DSCP_EF 0xb8
|
||
+#endif /* IPTOS_DSCP_EF */
|
||
+
|
||
|
||
#include <err.h>
|
||
#include <errno.h>
|
||
+#include <fcntl.h>
|
||
#include <limits.h>
|
||
#include <netdb.h>
|
||
#include <poll.h>
|
||
#include <signal.h>
|
||
+#include <stddef.h>
|
||
#include <stdarg.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <time.h>
|
||
-#include <tls.h>
|
||
+#ifdef TLS
|
||
+# include <tls.h>
|
||
+#endif
|
||
#include <unistd.h>
|
||
+#include <bsd/stdlib.h>
|
||
+#include <bsd/string.h>
|
||
|
||
#include "atomicio.h"
|
||
|
||
@@ -66,14 +121,23 @@
|
||
#define POLL_NETIN 2
|
||
#define POLL_STDOUT 3
|
||
#define BUFSIZE 16384
|
||
-#define DEFAULT_CA_FILE "/etc/ssl/cert.pem"
|
||
+#ifdef TLS
|
||
+# define DEFAULT_CA_FILE "/etc/ssl/cert.pem"
|
||
+
|
||
+# define TLS_NOVERIFY (1 << 1)
|
||
+# define TLS_NONAME (1 << 2)
|
||
+# define TLS_CCERT (1 << 3)
|
||
+# define TLS_MUSTSTAPLE (1 << 4)
|
||
+#endif
|
||
+
|
||
+#define CONNECTION_SUCCESS 0
|
||
+#define CONNECTION_FAILED 1
|
||
+#define CONNECTION_TIMEOUT 2
|
||
|
||
-#define TLS_NOVERIFY (1 << 1)
|
||
-#define TLS_NONAME (1 << 2)
|
||
-#define TLS_CCERT (1 << 3)
|
||
-#define TLS_MUSTSTAPLE (1 << 4)
|
||
+#define UDP_SCAN_TIMEOUT 3 /* Seconds */
|
||
|
||
/* Command Line Options */
|
||
+int bflag; /* Allow Broadcast */
|
||
int dflag; /* detached, no stdin */
|
||
int Fflag; /* fdpass sock to stdout */
|
||
unsigned int iflag; /* Interval Flag */
|
||
@@ -83,10 +147,12 @@
|
||
int nflag; /* Don't do name look up */
|
||
char *Pflag; /* Proxy username */
|
||
char *pflag; /* Localport flag */
|
||
+int qflag = -1; /* Quit after some secs */
|
||
int rflag; /* Random ports flag */
|
||
char *sflag; /* Source Address */
|
||
int tflag; /* Telnet Emulation */
|
||
int uflag; /* UDP - Default to TCP */
|
||
+int dccpflag; /* DCCP - Default to TCP */
|
||
int vflag; /* Verbosity */
|
||
int xflag; /* Socks proxy */
|
||
int zflag; /* Port Scan Flag */
|
||
@@ -97,6 +163,7 @@
|
||
int Tflag = -1; /* IP Type of Service */
|
||
int rtableid = -1;
|
||
|
||
+# if defined(TLS)
|
||
int usetls; /* use TLS */
|
||
char *Cflag; /* Public cert file */
|
||
char *Kflag; /* Private key file */
|
||
@@ -109,7 +176,13 @@
|
||
char *tls_ciphers; /* TLS ciphers */
|
||
char *tls_protocols; /* TLS protocols */
|
||
FILE *Zflag; /* file to save peer cert */
|
||
-
|
||
+# else
|
||
+int Cflag = 0; /* CRLF line-ending */
|
||
+# endif
|
||
+
|
||
+# if defined(TCP_MD5SIG) && defined(TCP_MD5SIG_MAXKEYLEN)
|
||
+char Sflag_password[TCP_MD5SIG_MAXKEYLEN];
|
||
+# endif
|
||
int recvcount, recvlimit;
|
||
int timeout = -1;
|
||
int family = AF_UNSPEC;
|
||
@@ -120,13 +193,19 @@
|
||
|
||
void atelnet(int, unsigned char *, unsigned int);
|
||
int strtoport(char *portstr, int udp);
|
||
-void build_ports(char *);
|
||
+void build_ports(char **);
|
||
void help(void) __attribute__((noreturn));
|
||
int local_listen(const char *, const char *, struct addrinfo);
|
||
+# if defined(TLS)
|
||
void readwrite(int, struct tls *);
|
||
+# else
|
||
+void readwrite(int);
|
||
+# endif
|
||
void fdpass(int nfd) __attribute__((noreturn));
|
||
int remote_connect(const char *, const char *, struct addrinfo);
|
||
+# if defined(TLS)
|
||
int timeout_tls(int, struct tls *, int (*)(struct tls *));
|
||
+# endif
|
||
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 *);
|
||
@@ -134,33 +213,54 @@
|
||
int unix_bind(char *, int);
|
||
int unix_connect(char *);
|
||
int unix_listen(char *);
|
||
-void set_common_sockopts(int, int);
|
||
+void set_common_sockopts(int, const struct sockaddr *);
|
||
int process_tos_opt(char *, int *);
|
||
+# if defined(TLS)
|
||
int process_tls_opt(char *, int *);
|
||
void save_peer_cert(struct tls *_tls_ctx, FILE *_fp);
|
||
+# endif
|
||
void report_connect(const struct sockaddr *, socklen_t, char *);
|
||
+void report_listen(const struct sockaddr *, socklen_t, int);
|
||
+# if defined(TLS)
|
||
void report_tls(struct tls *tls_ctx, char * host);
|
||
+# endif
|
||
void usage(int);
|
||
+# if defined(TLS)
|
||
ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *);
|
||
ssize_t fillbuf(int, unsigned char *, size_t *, struct tls *);
|
||
void tls_setup_client(struct tls *, int, char *);
|
||
struct tls *tls_setup_server(struct tls *, int, char *);
|
||
+# else
|
||
+ssize_t drainbuf(int, unsigned char *, size_t *, int);
|
||
+ssize_t fillbuf(int, unsigned char *, size_t *);
|
||
+# endif
|
||
+
|
||
+char *proto_name(int uflag, int dccpflag);
|
||
+static int connect_with_timeout(int fd, const struct sockaddr *sa,
|
||
+ socklen_t salen, int ctimeout);
|
||
+
|
||
+static void quit();
|
||
|
||
int
|
||
main(int argc, char *argv[])
|
||
{
|
||
int ch, s = -1, ret, socksv;
|
||
- char *host, *uport;
|
||
+ char *host, **uport;
|
||
struct addrinfo hints;
|
||
struct servent *sv;
|
||
socklen_t len;
|
||
- struct sockaddr_storage cliaddr;
|
||
+ union {
|
||
+ struct sockaddr_storage storage;
|
||
+ struct sockaddr_un forunix;
|
||
+ } cliaddr;
|
||
char *proxy = NULL, *proxyport = NULL;
|
||
const char *errstr;
|
||
struct addrinfo proxyhints;
|
||
char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
|
||
+# if defined(TLS)
|
||
struct tls_config *tls_cfg = NULL;
|
||
struct tls *tls_ctx = NULL;
|
||
+# endif
|
||
uint32_t protocols;
|
||
|
||
ret = 1;
|
||
@@ -172,7 +272,11 @@
|
||
signal(SIGPIPE, SIG_IGN);
|
||
|
||
while ((ch = getopt(argc, argv,
|
||
- "46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:R:rSs:T:tUuV:vW:w:X:x:Z:z"))
|
||
+# if defined(TLS)
|
||
+ "46bC:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:q:R:rSs:T:tUuV:vW:w:X:x:Z:z"))
|
||
+# else
|
||
+ "46bCDdFhI:i:klM:m:NnO:P:p:q:rSs:T:tUuV:vW:w:X:x:Zz"))
|
||
+# endif
|
||
!= -1) {
|
||
switch (ch) {
|
||
case '4':
|
||
@@ -181,6 +285,13 @@
|
||
case '6':
|
||
family = AF_INET6;
|
||
break;
|
||
+ case 'b':
|
||
+# if defined(SO_BROADCAST)
|
||
+ bflag = 1;
|
||
+# else
|
||
+ errx(1, "no broadcast frame support available");
|
||
+# endif
|
||
+ break;
|
||
case 'U':
|
||
family = AF_UNIX;
|
||
break;
|
||
@@ -194,24 +305,34 @@
|
||
else
|
||
errx(1, "unsupported proxy protocol");
|
||
break;
|
||
+# if defined(TLS)
|
||
case 'C':
|
||
Cflag = optarg;
|
||
break;
|
||
case 'c':
|
||
usetls = 1;
|
||
break;
|
||
+# else
|
||
+ case 'C':
|
||
+ Cflag = 1;
|
||
+ break;
|
||
+# endif
|
||
case 'd':
|
||
dflag = 1;
|
||
break;
|
||
+# if defined(TLS)
|
||
case 'e':
|
||
tls_expectname = optarg;
|
||
break;
|
||
+# endif
|
||
case 'F':
|
||
Fflag = 1;
|
||
break;
|
||
+# if defined(TLS)
|
||
case 'H':
|
||
tls_expecthash = optarg;
|
||
break;
|
||
+# endif
|
||
case 'h':
|
||
help();
|
||
break;
|
||
@@ -220,9 +341,11 @@
|
||
if (errstr)
|
||
errx(1, "interval %s: %s", errstr, optarg);
|
||
break;
|
||
+# if defined(TLS)
|
||
case 'K':
|
||
Kflag = optarg;
|
||
break;
|
||
+# endif
|
||
case 'k':
|
||
kflag = 1;
|
||
break;
|
||
@@ -251,10 +374,19 @@
|
||
case 'p':
|
||
pflag = optarg;
|
||
break;
|
||
+ case 'q':
|
||
+ qflag = strtonum(optarg, INT_MIN, INT_MAX, &errstr);
|
||
+ if (errstr)
|
||
+ errx(1, "quit timer %s: %s", errstr, optarg);
|
||
+ if (qflag >= 0)
|
||
+ Nflag = 1;
|
||
+ break;
|
||
+# if defined(TLS)
|
||
case 'R':
|
||
tls_cachanged = 1;
|
||
Rflag = optarg;
|
||
break;
|
||
+# endif
|
||
case 'r':
|
||
rflag = 1;
|
||
break;
|
||
@@ -267,11 +399,22 @@
|
||
case 'u':
|
||
uflag = 1;
|
||
break;
|
||
+ case 'Z':
|
||
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
+ dccpflag = 1;
|
||
+# else
|
||
+ errx(1, "no DCCP support available");
|
||
+# endif
|
||
+ break;
|
||
case 'V':
|
||
+# if defined(RT_TABLEID_MAX)
|
||
rtableid = (int)strtonum(optarg, 0,
|
||
RT_TABLEID_MAX, &errstr);
|
||
if (errstr)
|
||
errx(1, "rtable %s: %s", errstr, optarg);
|
||
+# else
|
||
+ errx(1, "no alternate routing table support available");
|
||
+# endif
|
||
break;
|
||
case 'v':
|
||
vflag = 1;
|
||
@@ -292,12 +435,14 @@
|
||
if ((proxy = strdup(optarg)) == NULL)
|
||
err(1, NULL);
|
||
break;
|
||
+# if defined(TLS)
|
||
case 'Z':
|
||
if (strcmp(optarg, "-") == 0)
|
||
Zflag = stderr;
|
||
else if ((Zflag = fopen(optarg, "w")) == NULL)
|
||
err(1, "can't open %s", optarg);
|
||
break;
|
||
+# endif
|
||
case 'z':
|
||
zflag = 1;
|
||
break;
|
||
@@ -316,17 +461,28 @@
|
||
errx(1, "TCP send window %s: %s",
|
||
errstr, optarg);
|
||
break;
|
||
+# if defined(TLS)
|
||
case 'o':
|
||
oflag = optarg;
|
||
break;
|
||
+# endif
|
||
case 'S':
|
||
+# if defined(TCP_MD5SIG) && defined(TCP_MD5SIG_MAXKEYLEN)
|
||
+ if (readpassphrase("TCP MD5SIG password: ",
|
||
+ Sflag_password, TCP_MD5SIG_MAXKEYLEN, RPP_REQUIRE_TTY) == NULL)
|
||
+ errx(1, "Unable to read TCP MD5SIG password");
|
||
Sflag = 1;
|
||
+# else
|
||
+ errx(1, "no TCP MD5 signature support available");
|
||
+# endif
|
||
break;
|
||
case 'T':
|
||
errstr = NULL;
|
||
errno = 0;
|
||
+# if defined(TLS)
|
||
if (process_tls_opt(optarg, &TLSopt))
|
||
break;
|
||
+# endif
|
||
if (process_tos_opt(optarg, &Tflag))
|
||
break;
|
||
if (strlen(optarg) > 1 && optarg[0] == '0' &&
|
||
@@ -336,7 +492,11 @@
|
||
Tflag = (int)strtonum(optarg, 0, 255,
|
||
&errstr);
|
||
if (Tflag < 0 || Tflag > 255 || errstr || errno)
|
||
+# if defined(TLS)
|
||
errx(1, "illegal tos/tls value %s", optarg);
|
||
+# else
|
||
+ errx(1, "illegal tos value %s", optarg);
|
||
+# endif
|
||
break;
|
||
default:
|
||
usage(1);
|
||
@@ -345,25 +505,48 @@
|
||
argc -= optind;
|
||
argv += optind;
|
||
|
||
+# if defined(RT_TABLEID_MAX)
|
||
if (rtableid >= 0)
|
||
if (setrtable(rtableid) == -1)
|
||
err(1, "setrtable");
|
||
+# endif
|
||
|
||
/* 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]) {
|
||
+ if (argc == 0 && lflag) {
|
||
+ uport = &pflag;
|
||
+ host = sflag;
|
||
+ } else if (argc == 1 && !pflag && !sflag) {
|
||
+ if (family == AF_UNIX) {
|
||
+ host = argv[0];
|
||
+ uport = NULL;
|
||
+ } else if (lflag) {
|
||
+ host = NULL;
|
||
+ uport = argv;
|
||
+ }
|
||
+ } else if (argc >= 2) {
|
||
+ if (lflag && (pflag || sflag || argc > 2))
|
||
+ usage(1); /* conflict */
|
||
host = argv[0];
|
||
- uport = argv[1];
|
||
+ uport = &argv[1];
|
||
} else
|
||
usage(1);
|
||
|
||
+ if (family == AF_UNIX) {
|
||
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
+ if (dccpflag)
|
||
+ errx(1, "cannot use -Z and -U");
|
||
+# endif
|
||
+ if (uport && *uport)
|
||
+ errx(1, "cannot use port with -U");
|
||
+ if (!host)
|
||
+ errx(1, "missing socket pathname");
|
||
+ } else if (!uport || !*uport)
|
||
+ errx(1, "missing port number");
|
||
+
|
||
+ if (lflag && zflag)
|
||
+ errx(1, "cannot use -z and -l");
|
||
+
|
||
+# if defined(TLS)
|
||
if (usetls) {
|
||
if (Cflag && unveil(Cflag, "r") == -1)
|
||
err(1, "unveil");
|
||
@@ -386,42 +569,19 @@
|
||
err(1, "unveil");
|
||
}
|
||
}
|
||
+# endif
|
||
|
||
- if (family == AF_UNIX) {
|
||
- if (pledge("stdio rpath wpath cpath tmppath unix", NULL) == -1)
|
||
- err(1, "pledge");
|
||
- } else if (Fflag && Pflag) {
|
||
- if (pledge("stdio inet dns sendfd tty", NULL) == -1)
|
||
- err(1, "pledge");
|
||
- } else if (Fflag) {
|
||
- if (pledge("stdio inet dns sendfd", NULL) == -1)
|
||
- err(1, "pledge");
|
||
- } else if (Pflag && usetls) {
|
||
- if (pledge("stdio rpath inet dns tty", NULL) == -1)
|
||
- err(1, "pledge");
|
||
- } else if (Pflag) {
|
||
- if (pledge("stdio inet dns tty", NULL) == -1)
|
||
- err(1, "pledge");
|
||
- } else if (usetls) {
|
||
- if (pledge("stdio rpath inet dns", NULL) == -1)
|
||
- err(1, "pledge");
|
||
- } else if (pledge("stdio inet dns", NULL) == -1)
|
||
- err(1, "pledge");
|
||
-
|
||
- 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");
|
||
+# if defined(TLS)
|
||
if (uflag && usetls)
|
||
errx(1, "cannot use -c and -u");
|
||
if ((family == AF_UNIX) && usetls)
|
||
errx(1, "cannot use -c and -U");
|
||
+# endif
|
||
if ((family == AF_UNIX) && Fflag)
|
||
errx(1, "cannot use -F and -U");
|
||
+# if defined(TLS)
|
||
if (Fflag && usetls)
|
||
errx(1, "cannot use -c and -F");
|
||
if (TLSopt && !usetls)
|
||
@@ -440,6 +600,7 @@
|
||
errx(1, "you must specify -c to use -H");
|
||
if (tls_expectname && !usetls)
|
||
errx(1, "you must specify -c to use -e");
|
||
+# endif
|
||
|
||
/* Get name of temporary socket for unix datagram client */
|
||
if ((family == AF_UNIX) && uflag && !lflag) {
|
||
@@ -448,8 +609,8 @@
|
||
} 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");
|
||
+ if (mkstemp(unix_dg_tmp_socket_buf) == -1)
|
||
+ err(1, "mkstemp");
|
||
unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
|
||
}
|
||
}
|
||
@@ -458,8 +619,20 @@
|
||
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 (uflag) {
|
||
+ hints.ai_socktype = SOCK_DGRAM;
|
||
+ hints.ai_protocol = IPPROTO_UDP;
|
||
+ }
|
||
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
+ else if (dccpflag) {
|
||
+ hints.ai_socktype = SOCK_DCCP;
|
||
+ hints.ai_protocol = IPPROTO_DCCP;
|
||
+ }
|
||
+# endif
|
||
+ else {
|
||
+ hints.ai_socktype = SOCK_STREAM;
|
||
+ hints.ai_protocol = IPPROTO_TCP;
|
||
+ }
|
||
if (nflag)
|
||
hints.ai_flags |= AI_NUMERICHOST;
|
||
}
|
||
@@ -467,7 +640,10 @@
|
||
if (xflag) {
|
||
if (uflag)
|
||
errx(1, "no proxy support for UDP mode");
|
||
-
|
||
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
+ if (dccpflag)
|
||
+ errx(1, "no proxy support for DCCP mode");
|
||
+# endif
|
||
if (lflag)
|
||
errx(1, "no proxy support for listen");
|
||
|
||
@@ -506,6 +682,7 @@
|
||
proxyhints.ai_flags |= AI_NUMERICHOST;
|
||
}
|
||
|
||
+# if defined(TLS)
|
||
if (usetls) {
|
||
if ((tls_cfg = tls_config_new()) == NULL)
|
||
errx(1, "unable to allocate TLS config");
|
||
@@ -541,7 +718,8 @@
|
||
err(1, "pledge");
|
||
} else if (pledge("stdio inet dns", NULL) == -1)
|
||
err(1, "pledge");
|
||
- }
|
||
+ }
|
||
+# endif
|
||
if (lflag) {
|
||
ret = 0;
|
||
|
||
@@ -550,8 +728,12 @@
|
||
s = unix_bind(host, 0);
|
||
else
|
||
s = unix_listen(host);
|
||
- }
|
||
+ } else
|
||
+ s = local_listen(host, *uport, hints);
|
||
+ if (s < 0)
|
||
+ err(1, NULL);
|
||
|
||
+# if defined(TLS)
|
||
if (usetls) {
|
||
tls_config_verify_client_optional(tls_cfg);
|
||
if ((tls_ctx = tls_server()) == NULL)
|
||
@@ -560,22 +742,20 @@
|
||
errx(1, "tls configuration failed (%s)",
|
||
tls_error(tls_ctx));
|
||
}
|
||
+# endif
|
||
/* Allow only one connection at a time, but stay alive. */
|
||
for (;;) {
|
||
- if (family != AF_UNIX) {
|
||
- if (s != -1)
|
||
- close(s);
|
||
- s = local_listen(host, uport, hints);
|
||
- }
|
||
- if (s < 0)
|
||
- err(1, NULL);
|
||
if (uflag && kflag) {
|
||
/*
|
||
* For UDP and -k, don't connect the socket,
|
||
* let it receive datagrams from multiple
|
||
* socket pairs.
|
||
*/
|
||
+# if defined(TLS)
|
||
readwrite(s, NULL);
|
||
+# else
|
||
+ readwrite(s);
|
||
+# endif
|
||
} else if (uflag && !kflag) {
|
||
/*
|
||
* For UDP and not -k, we will use recvfrom()
|
||
@@ -584,24 +764,28 @@
|
||
*/
|
||
int rv;
|
||
char buf[2048];
|
||
- struct sockaddr_storage z;
|
||
|
||
- len = sizeof(z);
|
||
+ len = sizeof(cliaddr);
|
||
rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
|
||
- (struct sockaddr *)&z, &len);
|
||
+ (struct sockaddr *)&cliaddr, &len);
|
||
if (rv < 0)
|
||
err(1, "recvfrom");
|
||
|
||
- rv = connect(s, (struct sockaddr *)&z, len);
|
||
+ rv = connect(s, (struct sockaddr *)&cliaddr, len);
|
||
if (rv < 0)
|
||
err(1, "connect");
|
||
|
||
if (vflag)
|
||
- report_connect((struct sockaddr *)&z, len, NULL);
|
||
+ report_connect((struct sockaddr *)&cliaddr, len, NULL);
|
||
|
||
+# if defined(TLS)
|
||
readwrite(s, NULL);
|
||
} else {
|
||
struct tls *tls_cctx = NULL;
|
||
+# else
|
||
+ readwrite(s);
|
||
+ } else {
|
||
+# endif
|
||
int connfd;
|
||
|
||
len = sizeof(cliaddr);
|
||
@@ -614,6 +798,7 @@
|
||
if (vflag)
|
||
report_connect((struct sockaddr *)&cliaddr, len,
|
||
family == AF_UNIX ? host : NULL);
|
||
+# if defined(TLS)
|
||
if ((usetls) &&
|
||
(tls_cctx = tls_setup_server(tls_ctx, connfd, host)))
|
||
readwrite(connfd, tls_cctx);
|
||
@@ -623,21 +808,32 @@
|
||
timeout_tls(s, tls_cctx, tls_close);
|
||
close(connfd);
|
||
tls_free(tls_cctx);
|
||
+# else
|
||
+ readwrite(connfd);
|
||
+ close(connfd);
|
||
+# endif
|
||
}
|
||
if (family == AF_UNIX && uflag) {
|
||
if (connect(s, NULL, 0) < 0)
|
||
err(1, "connect");
|
||
}
|
||
|
||
- if (!kflag)
|
||
+ if (!kflag) {
|
||
+ if (s != -1)
|
||
+ close(s);
|
||
break;
|
||
+ }
|
||
}
|
||
} else if (family == AF_UNIX) {
|
||
ret = 0;
|
||
|
||
if ((s = unix_connect(host)) > 0) {
|
||
if (!zflag)
|
||
+# if defined(TLS)
|
||
readwrite(s, NULL);
|
||
+# else
|
||
+ readwrite(s);
|
||
+# endif
|
||
close(s);
|
||
} else
|
||
ret = 1;
|
||
@@ -656,6 +852,7 @@
|
||
for (s = -1, i = 0; portlist[i] != NULL; i++) {
|
||
if (s != -1)
|
||
close(s);
|
||
+# if defined(TLS)
|
||
tls_free(tls_ctx);
|
||
tls_ctx = NULL;
|
||
|
||
@@ -666,6 +863,7 @@
|
||
errx(1, "tls configuration failed (%s)",
|
||
tls_error(tls_ctx));
|
||
}
|
||
+# endif
|
||
if (xflag)
|
||
s = socks_connect(host, portlist[i], hints,
|
||
proxy, proxyport, proxyhints, socksv,
|
||
@@ -677,7 +875,7 @@
|
||
continue;
|
||
|
||
ret = 0;
|
||
- if (vflag || zflag) {
|
||
+ if (vflag) {
|
||
/* For UDP, make sure we are connected. */
|
||
if (uflag) {
|
||
if (udptest(s) == -1) {
|
||
@@ -686,23 +884,25 @@
|
||
}
|
||
}
|
||
|
||
+ char *proto = proto_name(uflag, dccpflag);
|
||
/* Don't look up port if -n. */
|
||
if (nflag)
|
||
sv = NULL;
|
||
else {
|
||
sv = getservbyport(
|
||
ntohs(atoi(portlist[i])),
|
||
- uflag ? "udp" : "tcp");
|
||
+ proto);
|
||
}
|
||
|
||
fprintf(stderr,
|
||
"Connection to %s %s port [%s/%s] "
|
||
"succeeded!\n", host, portlist[i],
|
||
- uflag ? "udp" : "tcp",
|
||
+ proto,
|
||
sv ? sv->s_name : "*");
|
||
}
|
||
if (Fflag)
|
||
fdpass(s);
|
||
+# if defined(TLS)
|
||
else {
|
||
if (usetls)
|
||
tls_setup_client(tls_ctx, s, host);
|
||
@@ -711,13 +911,19 @@
|
||
if (tls_ctx)
|
||
timeout_tls(s, tls_ctx, tls_close);
|
||
}
|
||
+# else
|
||
+ else if (!zflag)
|
||
+ readwrite(s);
|
||
+# endif
|
||
}
|
||
}
|
||
|
||
if (s != -1)
|
||
close(s);
|
||
+# if defined(TLS)
|
||
tls_free(tls_ctx);
|
||
tls_config_free(tls_cfg);
|
||
+# endif
|
||
|
||
return ret;
|
||
}
|
||
@@ -737,6 +943,8 @@
|
||
0)) < 0)
|
||
return -1;
|
||
|
||
+ unlink(path);
|
||
+
|
||
memset(&s_un, 0, sizeof(struct sockaddr_un));
|
||
s_un.sun_family = AF_UNIX;
|
||
|
||
@@ -757,6 +965,7 @@
|
||
return s;
|
||
}
|
||
|
||
+# if defined(TLS)
|
||
int
|
||
timeout_tls(int s, struct tls *tls_ctx, int (*func)(struct tls *))
|
||
{
|
||
@@ -843,6 +1052,7 @@
|
||
}
|
||
return NULL;
|
||
}
|
||
+# endif
|
||
|
||
/*
|
||
* unix_connect()
|
||
@@ -858,8 +1068,10 @@
|
||
if ((s = unix_bind(unix_dg_tmp_socket, SOCK_CLOEXEC)) < 0)
|
||
return -1;
|
||
} else {
|
||
- if ((s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0)
|
||
+ if ((s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) {
|
||
+ errx(1, "create unix socket failed");
|
||
return -1;
|
||
+ }
|
||
}
|
||
|
||
memset(&s_un, 0, sizeof(struct sockaddr_un));
|
||
@@ -869,10 +1081,12 @@
|
||
sizeof(s_un.sun_path)) {
|
||
close(s);
|
||
errno = ENAMETOOLONG;
|
||
+ warn("unix connect abandoned");
|
||
return -1;
|
||
}
|
||
if (connect(s, (struct sockaddr *)&s_un, sizeof(s_un)) < 0) {
|
||
save_errno = errno;
|
||
+ warn("unix connect failed");
|
||
close(s);
|
||
errno = save_errno;
|
||
return -1;
|
||
@@ -899,6 +1113,24 @@
|
||
return s;
|
||
}
|
||
|
||
+char *proto_name(int uflag, int dccpflag) {
|
||
+
|
||
+ char *proto = NULL;
|
||
+ if (uflag) {
|
||
+ proto = "udp";
|
||
+ }
|
||
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
+ else if (dccpflag) {
|
||
+ proto = "dccp";
|
||
+ }
|
||
+# endif
|
||
+ else {
|
||
+ proto = "tcp";
|
||
+ }
|
||
+
|
||
+ return proto;
|
||
+}
|
||
+
|
||
/*
|
||
* remote_connect()
|
||
* Returns a socket connected to a remote host. Properly binds to a local
|
||
@@ -923,12 +1155,27 @@
|
||
if (sflag || pflag) {
|
||
struct addrinfo ahints, *ares;
|
||
|
||
+# if defined (SO_BINDANY)
|
||
/* try SO_BINDANY, but don't insist */
|
||
setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
|
||
+# endif
|
||
memset(&ahints, 0, sizeof(struct addrinfo));
|
||
ahints.ai_family = res->ai_family;
|
||
- ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
|
||
- ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
|
||
+ if (uflag) {
|
||
+ ahints.ai_socktype = SOCK_DGRAM;
|
||
+ ahints.ai_protocol = IPPROTO_UDP;
|
||
+
|
||
+ }
|
||
+# if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
|
||
+ else if (dccpflag) {
|
||
+ hints.ai_socktype = SOCK_DCCP;
|
||
+ hints.ai_protocol = IPPROTO_DCCP;
|
||
+ }
|
||
+# endif
|
||
+ else {
|
||
+ ahints.ai_socktype = SOCK_STREAM;
|
||
+ ahints.ai_protocol = IPPROTO_TCP;
|
||
+ }
|
||
ahints.ai_flags = AI_PASSIVE;
|
||
if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
|
||
errx(1, "getaddrinfo: %s", gai_strerror(error));
|
||
@@ -939,13 +1186,17 @@
|
||
freeaddrinfo(ares);
|
||
}
|
||
|
||
- set_common_sockopts(s, res->ai_family);
|
||
+ set_common_sockopts(s, res->ai_addr);
|
||
+ char *proto = proto_name(uflag, dccpflag);
|
||
|
||
- if (timeout_connect(s, res->ai_addr, res->ai_addrlen) == 0)
|
||
+ if ((error = connect_with_timeout(s, res->ai_addr, res->ai_addrlen, timeout)) == CONNECTION_SUCCESS)
|
||
break;
|
||
- if (vflag)
|
||
+ if (vflag && error == CONNECTION_FAILED)
|
||
warn("connect to %s port %s (%s) failed", host, port,
|
||
- uflag ? "udp" : "tcp");
|
||
+ proto);
|
||
+ else if (vflag && error == CONNECTION_TIMEOUT)
|
||
+ warn("connect to %s port %s (%s) timed out", host, port,
|
||
+ proto);
|
||
|
||
save_errno = errno;
|
||
close(s);
|
||
@@ -986,6 +1237,69 @@
|
||
return ret;
|
||
}
|
||
|
||
+static int connect_with_timeout(int fd, const struct sockaddr *sa,
|
||
+ socklen_t salen, int ctimeout)
|
||
+{
|
||
+ int err;
|
||
+ struct timeval tv, *tvp = NULL;
|
||
+ fd_set connect_fdset;
|
||
+ socklen_t len;
|
||
+ int orig_flags;
|
||
+
|
||
+ orig_flags = fcntl(fd, F_GETFL, 0);
|
||
+ if (fcntl(fd, F_SETFL, orig_flags | O_NONBLOCK) < 0 ) {
|
||
+ warn("can't set O_NONBLOCK - timeout not available");
|
||
+ if (connect(fd, sa, salen) == 0)
|
||
+ return CONNECTION_SUCCESS;
|
||
+ else
|
||
+ return CONNECTION_FAILED;
|
||
+ }
|
||
+
|
||
+ /* set connect timeout */
|
||
+ if (ctimeout > 0) {
|
||
+ tv.tv_sec = (time_t)ctimeout/1000;
|
||
+ tv.tv_usec = 0;
|
||
+ tvp = &tv;
|
||
+ }
|
||
+
|
||
+ /* attempt the connection */
|
||
+ err = connect(fd, sa, salen);
|
||
+ if (err != 0 && errno == EINPROGRESS) {
|
||
+ /* connection is proceeding
|
||
+ * it is complete (or failed) when select returns */
|
||
+
|
||
+ /* initialize connect_fdset */
|
||
+ FD_ZERO(&connect_fdset);
|
||
+ FD_SET(fd, &connect_fdset);
|
||
+
|
||
+ /* call select */
|
||
+ do {
|
||
+ err = select(fd + 1, NULL, &connect_fdset,
|
||
+ NULL, tvp);
|
||
+ } while (err < 0 && errno == EINTR);
|
||
+
|
||
+ /* select error */
|
||
+ if (err < 0)
|
||
+ errx(1,"select error: %s", strerror(errno));
|
||
+ /* we have reached a timeout */
|
||
+ if (err == 0)
|
||
+ return CONNECTION_TIMEOUT;
|
||
+ /* select returned successfully, but we must test socket
|
||
+ * error for result */
|
||
+ len = sizeof(err);
|
||
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
|
||
+ errx(1, "getsockopt error: %s", strerror(errno));
|
||
+ /* setup errno according to the result returned by
|
||
+ * getsockopt */
|
||
+ if (err != 0)
|
||
+ errno = err;
|
||
+ }
|
||
+
|
||
+ /* return aborted if an error occured, and valid otherwise */
|
||
+ fcntl(fd, F_SETFL, orig_flags);
|
||
+ return (err != 0)? CONNECTION_FAILED : CONNECTION_SUCCESS;
|
||
+}
|
||
+
|
||
/*
|
||
* local_listen()
|
||
* Returns a socket listening on a local port, binds to specified source
|
||
@@ -1016,15 +1330,25 @@
|
||
res->ai_protocol)) < 0)
|
||
continue;
|
||
|
||
+ ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
|
||
+ if (ret == -1)
|
||
+ err(1, NULL);
|
||
+
|
||
+# if defined(SO_REUSEPORT)
|
||
ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
|
||
if (ret == -1)
|
||
err(1, NULL);
|
||
+# endif
|
||
|
||
- set_common_sockopts(s, res->ai_family);
|
||
+ set_common_sockopts(s, res->ai_addr);
|
||
|
||
if (bind(s, (struct sockaddr *)res->ai_addr,
|
||
- res->ai_addrlen) == 0)
|
||
+ res->ai_addrlen) == 0) {
|
||
+ if (vflag)
|
||
+ report_listen(res->ai_addr, res->ai_addrlen,
|
||
+ res->ai_family);
|
||
break;
|
||
+ }
|
||
|
||
save_errno = errno;
|
||
close(s);
|
||
@@ -1047,7 +1371,11 @@
|
||
* Loop that polls on the network file descriptor and stdin.
|
||
*/
|
||
void
|
||
+# if defined(TLS)
|
||
readwrite(int net_fd, struct tls *tls_ctx)
|
||
+# else
|
||
+readwrite(int net_fd)
|
||
+# endif
|
||
{
|
||
struct pollfd pfd[4];
|
||
int stdin_fd = STDIN_FILENO;
|
||
@@ -1082,21 +1410,27 @@
|
||
while (1) {
|
||
/* both inputs are gone, buffers are empty, we are done */
|
||
if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1 &&
|
||
- stdinbufpos == 0 && netinbufpos == 0)
|
||
- return;
|
||
+ stdinbufpos == 0 && netinbufpos == 0) {
|
||
+ if (qflag <= 0)
|
||
+ return;
|
||
+ goto delay_exit;
|
||
+ }
|
||
/* both outputs are gone, we can't continue */
|
||
- if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1)
|
||
- return;
|
||
+ if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) {
|
||
+ if (qflag <= 0)
|
||
+ return;
|
||
+ goto delay_exit;
|
||
+ }
|
||
/* listen and net in gone, queues empty, done */
|
||
if (lflag && pfd[POLL_NETIN].fd == -1 &&
|
||
- stdinbufpos == 0 && netinbufpos == 0)
|
||
- return;
|
||
-
|
||
- /* help says -i is for "wait between lines sent". We read and
|
||
- * write arbitrary amounts of data, and we don't want to start
|
||
- * scanning for newlines, so this is as good as it gets */
|
||
- if (iflag)
|
||
- sleep(iflag);
|
||
+ stdinbufpos == 0 && netinbufpos == 0) {
|
||
+ if (qflag <= 0)
|
||
+ return;
|
||
+delay_exit:
|
||
+ close(net_fd);
|
||
+ signal(SIGALRM, quit);
|
||
+ alarm(qflag);
|
||
+ }
|
||
|
||
/* poll */
|
||
num_fds = poll(pfd, 4, timeout);
|
||
@@ -1147,12 +1481,17 @@
|
||
/* try to read from stdin */
|
||
if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
|
||
ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
|
||
+# if defined(TLS)
|
||
&stdinbufpos, NULL);
|
||
if (ret == TLS_WANT_POLLIN)
|
||
pfd[POLL_STDIN].events = POLLIN;
|
||
else if (ret == TLS_WANT_POLLOUT)
|
||
pfd[POLL_STDIN].events = POLLOUT;
|
||
- else if (ret == 0 || ret == -1)
|
||
+ else
|
||
+# else
|
||
+ &stdinbufpos);
|
||
+# endif
|
||
+ if (ret == 0 || ret == -1)
|
||
pfd[POLL_STDIN].fd = -1;
|
||
/* read something - poll net out */
|
||
if (stdinbufpos > 0)
|
||
@@ -1164,12 +1503,17 @@
|
||
/* try to write to network */
|
||
if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
|
||
ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
|
||
+# if defined(TLS)
|
||
&stdinbufpos, tls_ctx);
|
||
if (ret == TLS_WANT_POLLIN)
|
||
pfd[POLL_NETOUT].events = POLLIN;
|
||
else if (ret == TLS_WANT_POLLOUT)
|
||
pfd[POLL_NETOUT].events = POLLOUT;
|
||
- else if (ret == -1)
|
||
+ else
|
||
+# else
|
||
+ &stdinbufpos, (iflag || Cflag) ? 1 : 0);
|
||
+# endif
|
||
+ if (ret == -1)
|
||
pfd[POLL_NETOUT].fd = -1;
|
||
/* buffer empty - remove self from polling */
|
||
if (stdinbufpos == 0)
|
||
@@ -1181,12 +1525,17 @@
|
||
/* try to read from network */
|
||
if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
|
||
ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
|
||
+# if defined(TLS)
|
||
&netinbufpos, tls_ctx);
|
||
if (ret == TLS_WANT_POLLIN)
|
||
pfd[POLL_NETIN].events = POLLIN;
|
||
else if (ret == TLS_WANT_POLLOUT)
|
||
pfd[POLL_NETIN].events = POLLOUT;
|
||
- else if (ret == -1)
|
||
+ else
|
||
+# else
|
||
+ &netinbufpos);
|
||
+# endif
|
||
+ if (ret == -1)
|
||
pfd[POLL_NETIN].fd = -1;
|
||
/* eof on net in - remove from pfd */
|
||
if (ret == 0) {
|
||
@@ -1213,12 +1562,17 @@
|
||
/* try to write to stdout */
|
||
if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
|
||
ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
|
||
+# if defined(TLS)
|
||
&netinbufpos, NULL);
|
||
if (ret == TLS_WANT_POLLIN)
|
||
pfd[POLL_STDOUT].events = POLLIN;
|
||
else if (ret == TLS_WANT_POLLOUT)
|
||
pfd[POLL_STDOUT].events = POLLOUT;
|
||
- else if (ret == -1)
|
||
+ else
|
||
+# else
|
||
+ &netinbufpos, 0);
|
||
+# endif
|
||
+ if (ret == -1)
|
||
pfd[POLL_STDOUT].fd = -1;
|
||
/* buffer empty - remove self from polling */
|
||
if (netinbufpos == 0)
|
||
@@ -1242,21 +1596,40 @@
|
||
}
|
||
|
||
ssize_t
|
||
-drainbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls)
|
||
+drainbuf(int fd, unsigned char *buf, size_t *bufpos, int oneline)
|
||
{
|
||
- ssize_t n;
|
||
+ ssize_t n, r;
|
||
ssize_t adjust;
|
||
+ unsigned char *lf = NULL;
|
||
|
||
- if (tls)
|
||
- n = tls_write(tls, buf, *bufpos);
|
||
- else {
|
||
- n = write(fd, buf, *bufpos);
|
||
- /* don't treat EAGAIN, EINTR as error */
|
||
- if (n == -1 && (errno == EAGAIN || errno == EINTR))
|
||
- n = TLS_WANT_POLLOUT;
|
||
- }
|
||
+ if (oneline)
|
||
+ lf = memchr(buf, '\n', *bufpos);
|
||
+ if (lf == NULL) {
|
||
+ n = *bufpos;
|
||
+ oneline = 0;
|
||
+ }
|
||
+ else if (Cflag && (lf == buf || buf[lf - buf - 1] != '\r')) {
|
||
+ n = lf - buf;
|
||
+ oneline = 2;
|
||
+ }
|
||
+ else
|
||
+ n = lf - buf + 1;
|
||
+ if (n > 0)
|
||
+ n = write(fd, buf, n);
|
||
+
|
||
+ /* don't treat EAGAIN, EINTR as error */
|
||
+ if (n == -1 && (errno == EAGAIN || errno == EINTR))
|
||
+ n = -2;
|
||
+ if (oneline == 2 && n >= 0)
|
||
+ n++;
|
||
if (n <= 0)
|
||
return n;
|
||
+
|
||
+ if (oneline == 2 && (r = atomicio(vwrite, fd, "\r\n", 2)) != 2)
|
||
+ err(1, "write failed (%zu/2)", r);
|
||
+ if (oneline > 0 && iflag)
|
||
+ sleep(iflag);
|
||
+
|
||
/* adjust buffer */
|
||
adjust = *bufpos - n;
|
||
if (adjust > 0)
|
||
@@ -1266,19 +1639,29 @@
|
||
}
|
||
|
||
ssize_t
|
||
+# if defined(TLS)
|
||
fillbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls)
|
||
+# else
|
||
+fillbuf(int fd, unsigned char *buf, size_t *bufpos)
|
||
+# endif
|
||
{
|
||
size_t num = BUFSIZE - *bufpos;
|
||
ssize_t n;
|
||
|
||
+# if defined(TLS)
|
||
if (tls)
|
||
n = tls_read(tls, buf + *bufpos, num);
|
||
else {
|
||
+# endif
|
||
n = read(fd, buf + *bufpos, num);
|
||
/* don't treat EAGAIN, EINTR as error */
|
||
if (n == -1 && (errno == EAGAIN || errno == EINTR))
|
||
+# if defined(TLS)
|
||
n = TLS_WANT_POLLIN;
|
||
}
|
||
+# else
|
||
+ n = -2;
|
||
+# endif
|
||
if (n <= 0)
|
||
return n;
|
||
*bufpos += n;
|
||
@@ -1402,51 +1785,61 @@
|
||
* that we should try to connect to.
|
||
*/
|
||
void
|
||
-build_ports(char *p)
|
||
+build_ports(char **p)
|
||
{
|
||
+ struct servent *sv;
|
||
char *n;
|
||
int hi, lo, cp;
|
||
int x = 0;
|
||
+ int i;
|
||
|
||
- if ((n = strchr(p, '-')) != NULL) {
|
||
- *n = '\0';
|
||
- n++;
|
||
-
|
||
- /* Make sure the ports are in order: lowest->highest. */
|
||
- hi = strtoport(n, uflag);
|
||
- lo = strtoport(p, uflag);
|
||
- if (lo > hi) {
|
||
- cp = hi;
|
||
- hi = lo;
|
||
- lo = cp;
|
||
- }
|
||
-
|
||
- /*
|
||
- * Initialize portlist with a random permutation. Based on
|
||
- * Knuth, as in ip_randomid() in sys/netinet/ip_id.c.
|
||
- */
|
||
- if (rflag) {
|
||
- for (x = 0; x <= hi - lo; x++) {
|
||
- cp = arc4random_uniform(x + 1);
|
||
- portlist[x] = portlist[cp];
|
||
- if (asprintf(&portlist[cp], "%d", x + lo) < 0)
|
||
- err(1, "asprintf");
|
||
+ char *proto = proto_name(uflag, dccpflag);
|
||
+ for (i = 0; p[i] != NULL; i++) {
|
||
+ sv = getservbyname(p[i], proto);
|
||
+ if (sv) {
|
||
+ if (asprintf(&portlist[x], "%d", ntohs(sv->s_port)) < 0)
|
||
+ err(1, "asprintf");
|
||
+ x++;
|
||
+ } else if ((n = strchr(p[i], '-')) != NULL) {
|
||
+ *n = '\0';
|
||
+ n++;
|
||
+
|
||
+ /* Make sure the ports are in order: lowest->highest. */
|
||
+ hi = strtoport(n, uflag);
|
||
+ lo = strtoport(p[i], uflag);
|
||
+ if (lo > hi) {
|
||
+ cp = hi;
|
||
+ hi = lo;
|
||
+ lo = cp;
|
||
}
|
||
- } else { /* Load ports sequentially. */
|
||
+
|
||
+ /* Load ports sequentially. */
|
||
for (cp = lo; cp <= hi; cp++) {
|
||
if (asprintf(&portlist[x], "%d", cp) < 0)
|
||
err(1, "asprintf");
|
||
x++;
|
||
}
|
||
+ } else {
|
||
+ hi = strtoport(p[i], uflag);
|
||
+ if (asprintf(&portlist[x], "%d", hi) < 0)
|
||
+ err(1, "asprintf");
|
||
+ x++;
|
||
}
|
||
- } else {
|
||
- char *tmp;
|
||
+ }
|
||
|
||
- hi = strtoport(p, uflag);
|
||
- if (asprintf(&tmp, "%d", hi) != -1)
|
||
- portlist[0] = tmp;
|
||
- else
|
||
- err(1, NULL);
|
||
+ /*
|
||
+ * Initialize portlist with a random permutation using
|
||
+ * Fisher–Yates shuffle.
|
||
+ */
|
||
+ if (rflag) {
|
||
+ for (i = x-1; i > 0; i--) {
|
||
+ cp = arc4random_uniform(i+1);
|
||
+ if (cp != i) {
|
||
+ n = portlist[i];
|
||
+ portlist[i] = portlist[cp];
|
||
+ portlist[cp] = n;
|
||
+ }
|
||
+ }
|
||
}
|
||
}
|
||
|
||
@@ -1458,27 +1851,51 @@
|
||
int
|
||
udptest(int s)
|
||
{
|
||
- int i, ret;
|
||
+ int i, t;
|
||
|
||
- for (i = 0; i <= 3; i++) {
|
||
- if (write(s, "X", 1) == 1)
|
||
- ret = 1;
|
||
- else
|
||
- ret = -1;
|
||
+ if ((write(s, "X", 1) != 1) ||
|
||
+ ((write(s, "X", 1) != 1) && (errno == ECONNREFUSED)))
|
||
+ return -1;
|
||
+
|
||
+ /* Give the remote host some time to reply. */
|
||
+ for (i = 0, t = (timeout == -1) ? UDP_SCAN_TIMEOUT : (timeout / 1000);
|
||
+ i < t; i++) {
|
||
+ sleep(1);
|
||
+ if ((write(s, "X", 1) != 1) && (errno == ECONNREFUSED))
|
||
+ return -1;
|
||
}
|
||
- return ret;
|
||
+ return 1;
|
||
}
|
||
|
||
void
|
||
-set_common_sockopts(int s, int af)
|
||
+set_common_sockopts(int s, const struct sockaddr* sa)
|
||
{
|
||
int x = 1;
|
||
+ int af = sa->sa_family;
|
||
|
||
+# if defined(SO_BROADCAST)
|
||
+ if (bflag) {
|
||
+ /* allow datagram sockets to send packets to a broadcast address
|
||
+ * (this option has no effect on stream-oriented sockets) */
|
||
+ if (setsockopt(s, SOL_SOCKET, SO_BROADCAST,
|
||
+ &x, sizeof(x)) == -1)
|
||
+ err(1, NULL);
|
||
+ }
|
||
+# endif
|
||
+# if defined(TCP_MD5SIG) && defined(TCP_MD5SIG_MAXKEYLEN)
|
||
if (Sflag) {
|
||
+ struct tcp_md5sig sig;
|
||
+ memset(&sig, 0, sizeof(sig));
|
||
+ memcpy(&sig.tcpm_addr, sa, sizeof(struct sockaddr_storage));
|
||
+ sig.tcpm_keylen = TCP_MD5SIG_MAXKEYLEN < strlen(Sflag_password)
|
||
+ ? TCP_MD5SIG_MAXKEYLEN
|
||
+ : strlen(Sflag_password);
|
||
+ strlcpy(sig.tcpm_key, Sflag_password, sig.tcpm_keylen);
|
||
if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
|
||
- &x, sizeof(x)) == -1)
|
||
+ &sig, sizeof(sig)) == -1)
|
||
err(1, NULL);
|
||
}
|
||
+# endif
|
||
if (Dflag) {
|
||
if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
|
||
&x, sizeof(x)) == -1)
|
||
@@ -1489,9 +1906,14 @@
|
||
IP_TOS, &Tflag, sizeof(Tflag)) == -1)
|
||
err(1, "set IP ToS");
|
||
|
||
+#if defined(IPV6_TCLASS)
|
||
else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
|
||
IPV6_TCLASS, &Tflag, sizeof(Tflag)) == -1)
|
||
err(1, "set IPv6 traffic class");
|
||
+#else
|
||
+ else if (af == AF_INET6)
|
||
+ errx(1, "can't set IPv6 traffic class (unavailable)");
|
||
+#endif
|
||
}
|
||
if (Iflag) {
|
||
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
|
||
@@ -1509,19 +1931,34 @@
|
||
IP_TTL, &ttl, sizeof(ttl)))
|
||
err(1, "set IP TTL");
|
||
|
||
+#if defined(IPV6_UNICAST_HOPS)
|
||
else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
|
||
IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)))
|
||
err(1, "set IPv6 unicast hops");
|
||
+#else
|
||
+ else if (af == AF_INET6)
|
||
+ errx(1, "can't set IPv6 unicast hops (unavailable)");
|
||
+#endif
|
||
}
|
||
|
||
if (minttl != -1) {
|
||
+#if defined(IP_MINTTL)
|
||
if (af == AF_INET && setsockopt(s, IPPROTO_IP,
|
||
IP_MINTTL, &minttl, sizeof(minttl)))
|
||
err(1, "set IP min TTL");
|
||
+#else
|
||
+ if (af == AF_INET)
|
||
+ errx(1, "can't set IP min TTL (unavailable)");
|
||
+#endif
|
||
|
||
+#if defined(IPV6_MINHOPCOUNT)
|
||
else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
|
||
IPV6_MINHOPCOUNT, &minttl, sizeof(minttl)))
|
||
err(1, "set IPv6 min hop count");
|
||
+#else
|
||
+ else if (af == AF_INET6)
|
||
+ errx(1, "can't set IPv6 min hop count (unavailable)");
|
||
+#endif
|
||
}
|
||
}
|
||
|
||
@@ -1556,6 +1993,7 @@
|
||
{ "cs7", IPTOS_DSCP_CS7 },
|
||
{ "ef", IPTOS_DSCP_EF },
|
||
{ "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
|
||
+ { "lowcost", IPTOS_LOWCOST },
|
||
{ "lowdelay", IPTOS_LOWDELAY },
|
||
{ "netcontrol", IPTOS_PREC_NETCONTROL },
|
||
{ "reliability", IPTOS_RELIABILITY },
|
||
@@ -1573,6 +2011,7 @@
|
||
return 0;
|
||
}
|
||
|
||
+# if defined(TLS)
|
||
int
|
||
process_tls_opt(char *s, int *flags)
|
||
{
|
||
@@ -1686,6 +2125,7 @@
|
||
|
||
}
|
||
}
|
||
+# endif
|
||
|
||
void
|
||
report_connect(const struct sockaddr *sa, socklen_t salen, char *path)
|
||
@@ -1719,23 +2159,40 @@
|
||
}
|
||
|
||
void
|
||
+report_listen(const struct sockaddr *sa, socklen_t salen, int family)
|
||
+{
|
||
+ char hostname[NI_MAXHOST];
|
||
+ char service[NI_MAXSERV];
|
||
+ int flags = NI_NUMERICSERV;
|
||
+
|
||
+ if (nflag)
|
||
+ flags |= NI_NUMERICHOST;
|
||
+ if (getnameinfo(sa, salen, hostname, sizeof(hostname),
|
||
+ service, sizeof(service), flags) == -1)
|
||
+ warn("Could not get address info for the listening socket");
|
||
+ else
|
||
+ fprintf(stderr, "Listening on [%s] (family %d, port %s)\n",
|
||
+ hostname, family, service);
|
||
+}
|
||
+
|
||
+void
|
||
help(void)
|
||
{
|
||
+# if defined(DEBIAN_VERSION)
|
||
+ fprintf(stderr, "OpenBSD netcat (Debian patchlevel " DEBIAN_VERSION ")\n");
|
||
+# endif
|
||
usage(0);
|
||
fprintf(stderr, "\tCommand Summary:\n\
|
||
\t-4 Use IPv4\n\
|
||
\t-6 Use IPv6\n\
|
||
- \t-C certfile Public key file\n\
|
||
- \t-c Use TLS\n\
|
||
+ \t-b Allow broadcast\n\
|
||
+ \t-C Send CRLF as line-ending\n\
|
||
\t-D Enable the debug socket option\n\
|
||
\t-d Detach from stdin\n\
|
||
- \t-e name\t Required name in peer certificate\n\
|
||
\t-F Pass socket fd\n\
|
||
- \t-H hash\t Hash string of peer certificate\n\
|
||
\t-h This help text\n\
|
||
\t-I length TCP receive buffer length\n\
|
||
\t-i interval Delay interval for lines sent, ports scanned\n\
|
||
- \t-K keyfile Private key file\n\
|
||
\t-k Keep inbound sockets open for multiple connects\n\
|
||
\t-l Listen mode, for inbound connects\n\
|
||
\t-M ttl Outgoing TTL / Hop Limit\n\
|
||
@@ -1743,14 +2200,13 @@
|
||
\t-N Shutdown the network socket after EOF on stdin\n\
|
||
\t-n Suppress name/port resolutions\n\
|
||
\t-O length TCP send buffer length\n\
|
||
- \t-o staplefile Staple file\n\
|
||
\t-P proxyuser\tUsername for proxy authentication\n\
|
||
\t-p port\t Specify local port for remote connects\n\
|
||
- \t-R CAfile CA bundle\n\
|
||
+ \t-q secs\t quit after EOF on stdin and delay of secs\n\
|
||
\t-r Randomize remote ports\n\
|
||
\t-S Enable the TCP MD5 signature option\n\
|
||
\t-s source Local source address\n\
|
||
- \t-T keyword TOS value or TLS options\n\
|
||
+ \t-T keyword TOS value\n\
|
||
\t-t Answer TELNET negotiation\n\
|
||
\t-U Use UNIX domain socket\n\
|
||
\t-u UDP mode\n\
|
||
@@ -1760,26 +2216,31 @@
|
||
\t-w timeout 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 Peer certificate file\n\
|
||
+ \t-Z DCCP mode\n\
|
||
\t-z Zero-I/O mode [used for scanning]\n\
|
||
Port numbers can be individual or ranges: lo-hi [inclusive]\n");
|
||
- exit(1);
|
||
+ exit(0);
|
||
}
|
||
|
||
void
|
||
usage(int ret)
|
||
{
|
||
fprintf(stderr,
|
||
- "usage: nc [-46cDdFhklNnrStUuvz] [-C certfile] [-e name] "
|
||
- "[-H hash] [-I length]\n"
|
||
- "\t [-i interval] [-K keyfile] [-M ttl] [-m minttl] [-O length]\n"
|
||
- "\t [-o staplefile] [-P proxy_username] [-p source_port] "
|
||
- "[-R CAfile]\n"
|
||
- "\t [-s source] [-T keyword] [-V rtable] [-W recvlimit] "
|
||
+ "usage: nc [-46CDdFhklNnrStUuvZz] [-I length] [-i interval] [-M ttl]\n"
|
||
+ "\t [-m minttl] [-O length] [-P proxy_username] [-p source_port]\n"
|
||
+ "\t [-q seconds] [-s source] [-T keyword] [-V rtable] [-W recvlimit] "
|
||
"[-w timeout]\n"
|
||
"\t [-X proxy_protocol] [-x proxy_address[:port]] "
|
||
- "[-Z peercertfile]\n"
|
||
"\t [destination] [port]\n");
|
||
if (ret)
|
||
exit(1);
|
||
}
|
||
+
|
||
+/*
|
||
+ * quit()
|
||
+ * handler for a "-q" timeout (exit 0 instead of 1)
|
||
+ */
|
||
+static void quit()
|
||
+{
|
||
+ exit(0);
|
||
+}
|
||
diff -ruN netcat-openbsd-1.195/socks.c netcat-openbsd-1.195_patch/socks.c
|
||
--- netcat-openbsd-1.195/socks.c 2018-10-21 13:34:47.000000000 +0300
|
||
+++ netcat-openbsd-1.195_patch/socks.c 2020-06-05 08:03:51.471461485 +0300
|
||
@@ -38,7 +38,7 @@
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include <resolv.h>
|
||
-#include <readpassphrase.h>
|
||
+#include <bsd/readpassphrase.h>
|
||
#include "atomicio.h"
|
||
|
||
#define SOCKS_PORT "1080"
|
||
@@ -217,11 +217,11 @@
|
||
buf[2] = SOCKS_NOAUTH;
|
||
cnt = atomicio(vwrite, proxyfd, buf, 3);
|
||
if (cnt != 3)
|
||
- err(1, "write failed (%zu/3)", cnt);
|
||
+ err(1, "write failed (%zu/3)", (size_t)cnt);
|
||
|
||
cnt = atomicio(read, proxyfd, buf, 2);
|
||
if (cnt != 2)
|
||
- err(1, "read failed (%zu/3)", cnt);
|
||
+ err(1, "read failed (%zu/3)", (size_t)cnt);
|
||
|
||
if (buf[1] == SOCKS_NOMETHOD)
|
||
errx(1, "authentication method negotiation failed");
|
||
@@ -270,11 +270,11 @@
|
||
|
||
cnt = atomicio(vwrite, proxyfd, buf, wlen);
|
||
if (cnt != wlen)
|
||
- err(1, "write failed (%zu/%zu)", cnt, wlen);
|
||
+ err(1, "write failed (%zu/%zu)", (size_t)cnt, (size_t)wlen);
|
||
|
||
cnt = atomicio(read, proxyfd, buf, 4);
|
||
if (cnt != 4)
|
||
- err(1, "read failed (%zu/4)", cnt);
|
||
+ err(1, "read failed (%zu/4)", (size_t)cnt);
|
||
if (buf[1] != 0) {
|
||
errx(1, "connection failed, SOCKSv5 error: %s",
|
||
socks5_strerror(buf[1]));
|
||
@@ -283,12 +283,12 @@
|
||
case SOCKS_IPV4:
|
||
cnt = atomicio(read, proxyfd, buf + 4, 6);
|
||
if (cnt != 6)
|
||
- err(1, "read failed (%zu/6)", cnt);
|
||
+ err(1, "read failed (%zu/6)", (size_t)cnt);
|
||
break;
|
||
case SOCKS_IPV6:
|
||
cnt = atomicio(read, proxyfd, buf + 4, 18);
|
||
if (cnt != 18)
|
||
- err(1, "read failed (%zu/18)", cnt);
|
||
+ err(1, "read failed (%zu/18)", (size_t)cnt);
|
||
break;
|
||
default:
|
||
errx(1, "connection failed, unsupported address type");
|
||
@@ -308,11 +308,11 @@
|
||
|
||
cnt = atomicio(vwrite, proxyfd, buf, wlen);
|
||
if (cnt != wlen)
|
||
- err(1, "write failed (%zu/%zu)", cnt, wlen);
|
||
+ err(1, "write failed (%zu/%zu)", (size_t)cnt, (size_t)wlen);
|
||
|
||
cnt = atomicio(read, proxyfd, buf, 8);
|
||
if (cnt != 8)
|
||
- err(1, "read failed (%zu/8)", cnt);
|
||
+ err(1, "read failed (%zu/8)", (size_t)cnt);
|
||
if (buf[1] != 90) {
|
||
errx(1, "connection failed, SOCKSv4 error: %s",
|
||
socks4_strerror(buf[1]));
|
||
@@ -326,21 +326,21 @@
|
||
|
||
/* Try to be sane about numeric IPv6 addresses */
|
||
if (strchr(host, ':') != NULL) {
|
||
- r = snprintf(buf, sizeof(buf),
|
||
+ r = snprintf((char*)buf, sizeof(buf),
|
||
"CONNECT [%s]:%d HTTP/1.0\r\n",
|
||
host, ntohs(serverport));
|
||
} else {
|
||
- r = snprintf(buf, sizeof(buf),
|
||
+ r = snprintf((char*)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);
|
||
+ r = strlen((char*)buf);
|
||
|
||
cnt = atomicio(vwrite, proxyfd, buf, r);
|
||
if (cnt != r)
|
||
- err(1, "write failed (%zu/%d)", cnt, r);
|
||
+ err(1, "write failed (%zu/%d)", (size_t)cnt, (int)r);
|
||
|
||
if (authretry > 1) {
|
||
char proxypass[256];
|
||
@@ -348,20 +348,20 @@
|
||
|
||
getproxypass(proxyuser, proxyhost,
|
||
proxypass, sizeof proxypass);
|
||
- r = snprintf(buf, sizeof(buf), "%s:%s",
|
||
+ r = snprintf((char*)buf, sizeof(buf), "%s:%s",
|
||
proxyuser, proxypass);
|
||
explicit_bzero(proxypass, sizeof proxypass);
|
||
if (r == -1 || (size_t)r >= sizeof(buf) ||
|
||
- b64_ntop(buf, strlen(buf), resp,
|
||
+ b64_ntop(buf, strlen((char*)buf), resp,
|
||
sizeof(resp)) == -1)
|
||
errx(1, "Proxy username/password too long");
|
||
- r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
|
||
+ r = snprintf((char*)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);
|
||
+ r = strlen((char*)buf);
|
||
if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r)
|
||
- err(1, "write failed (%zu/%d)", cnt, r);
|
||
+ err(1, "write failed (%zu/%d)", (size_t)cnt, r);
|
||
explicit_bzero(proxypass, sizeof proxypass);
|
||
explicit_bzero(buf, sizeof buf);
|
||
}
|
||
@@ -371,22 +371,22 @@
|
||
err(1, "write failed (%zu/2)", cnt);
|
||
|
||
/* Read status reply */
|
||
- proxy_read_line(proxyfd, buf, sizeof(buf));
|
||
+ proxy_read_line(proxyfd, (char*)buf, sizeof(buf));
|
||
if (proxyuser != NULL &&
|
||
- strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
|
||
+ strncmp((char*)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)
|
||
+ } else if (strncmp((char*)buf, "HTTP/1.0 200 ", 12) != 0 &&
|
||
+ strncmp((char*)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));
|
||
+ proxy_read_line(proxyfd, (char*)buf, sizeof(buf));
|
||
if (*buf == '\0')
|
||
break;
|
||
}
|