mirror of
https://github.com/nmap/nmap.git
synced 2026-01-06 06:29:03 +00:00
Implementation of UNIX-domain sockets for Ncat
Implementation of UNIX sockets for Ncat using also UNIX-domain sockets functionality from Nsock library. Added new argument "-U".
This commit is contained in:
@@ -119,6 +119,9 @@
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||
#undef HAVE_SYS_UN_H
|
||||
|
||||
/* Define to 1 if you have the `vprintf' function. */
|
||||
#undef HAVE_VPRINTF
|
||||
|
||||
|
||||
2
ncat/configure
vendored
2
ncat/configure
vendored
@@ -3770,7 +3770,7 @@ fi
|
||||
done
|
||||
|
||||
|
||||
for ac_header in fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/param.h sys/socket.h sys/time.h sys/timeb.h unistd.h
|
||||
for ac_header in fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/param.h sys/socket.h sys/time.h sys/timeb.h unistd.h sys/un.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
|
||||
@@ -39,7 +39,7 @@ AC_PATH_TOOL([STRIP], [strip], [/bin/true])
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS([fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/param.h sys/socket.h sys/time.h sys/timeb.h unistd.h])
|
||||
AC_CHECK_HEADERS([fcntl.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/param.h sys/socket.h sys/time.h sys/timeb.h unistd.h sys/un.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_HEADER_STAT
|
||||
|
||||
@@ -5,6 +5,7 @@ Options taking a time assume seconds. Append 'ms' for milliseconds,
|
||||
's' for seconds, 'm' for minutes, or 'h' for hours (e.g. 500ms).
|
||||
-4 Use IPv4 only
|
||||
-6 Use IPv6 only
|
||||
-U, --unixsock Use Unix domain sockets only
|
||||
-C, --crlf Use CRLF for EOL sequence
|
||||
-c, --sh-exec <command> Executes the given command via /bin/sh
|
||||
-e, --exec <command> Executes the given command
|
||||
|
||||
@@ -213,6 +213,7 @@ static void set_ssl_ctx_options(SSL_CTX *ctx)
|
||||
static void connect_report(nsock_iod nsi)
|
||||
{
|
||||
union sockaddr_u peer;
|
||||
zmem(&peer, sizeof(peer.storage));
|
||||
|
||||
nsi_getlastcommunicationinfo(nsi, NULL, NULL, NULL,
|
||||
&peer.sockaddr, sizeof(peer.storage));
|
||||
@@ -244,10 +245,20 @@ static void connect_report(nsock_iod nsi)
|
||||
assert(ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf)) != NULL);
|
||||
loguser("SHA-1 fingerprint: %s\n", digest_buf);
|
||||
} else {
|
||||
loguser("Connected to %s:%hu.\n", inet_socktop(&peer), nsi_peerport(nsi));
|
||||
#if HAVE_SYS_UN_H
|
||||
if (peer.sockaddr.sa_family == AF_UNIX)
|
||||
loguser("Connected to %s.\n", peer.un.sun_path);
|
||||
else
|
||||
#endif
|
||||
loguser("Connected to %s:%hu.\n", inet_socktop(&peer), nsi_peerport(nsi));
|
||||
}
|
||||
#else
|
||||
loguser("Connected to %s:%hu.\n", inet_socktop(&peer), nsi_peerport(nsi));
|
||||
#if HAVE_SYS_UN_H
|
||||
if (peer.sockaddr.sa_family == AF_UNIX)
|
||||
loguser("Connected to %s.\n", peer.un.sun_path);
|
||||
else
|
||||
#endif
|
||||
loguser("Connected to %s:%hu.\n", inet_socktop(&peer), nsi_peerport(nsi));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -523,6 +534,30 @@ int ncat_connect(void)
|
||||
if (nsi_set_hostname(cs.sock_nsi, o.target) == -1)
|
||||
bye("Failed to set hostname on iod.");
|
||||
|
||||
#if HAVE_SYS_UN_H
|
||||
/* For DGRAM UNIX socket we have to use source socket */
|
||||
if (o.af == AF_UNIX && o.udp)
|
||||
{
|
||||
if (srcaddr.storage.ss_family == AF_UNIX) {
|
||||
nsi_set_localaddr(cs.sock_nsi, &srcaddr.storage, SUN_LEN((struct sockaddr_un *)&srcaddr.storage));
|
||||
} else {
|
||||
char *tmp_name = NULL;
|
||||
/* If no source socket was specified, we have to create temporary one. */
|
||||
if ((tmp_name = tempnam(NULL, "ncat.")) == NULL)
|
||||
bye("Failed to create name for temporary DGRAM source Unix domain socket (tempnam).");
|
||||
|
||||
srcaddr.un.sun_family = AF_UNIX;
|
||||
strncpy(srcaddr.un.sun_path, tmp_name, sizeof(srcaddr.un.sun_path));
|
||||
free (tmp_name);
|
||||
|
||||
nsi_set_localaddr(cs.sock_nsi, &srcaddr.storage, SUN_LEN((struct sockaddr_un *)&srcaddr.storage));
|
||||
}
|
||||
|
||||
if (o.verbose)
|
||||
loguser("[%s] used as source DGRAM Unix domain socket.\n", srcaddr.un.sun_path);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (srcaddr.storage.ss_family != AF_UNSPEC)
|
||||
nsi_set_localaddr(cs.sock_nsi, &srcaddr.storage, sizeof(srcaddr.storage));
|
||||
|
||||
@@ -538,6 +573,19 @@ int ncat_connect(void)
|
||||
free(ipopts); /* Nsock has its own copy */
|
||||
}
|
||||
|
||||
#if HAVE_SYS_UN_H
|
||||
if (o.af == AF_UNIX) {
|
||||
if (o.udp) {
|
||||
nsock_connect_unixsock_datagram(mypool, cs.sock_nsi, connect_handler, NULL,
|
||||
&targetss.sockaddr,
|
||||
SUN_LEN((struct sockaddr_un *)&targetss.sockaddr));
|
||||
} else {
|
||||
nsock_connect_unixsock_stream(mypool, cs.sock_nsi, connect_handler, o.conntimeout,
|
||||
NULL, &targetss.sockaddr,
|
||||
SUN_LEN((struct sockaddr_un *)&targetss.sockaddr));
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (o.udp) {
|
||||
nsock_connect_udp(mypool, cs.sock_nsi, connect_handler,
|
||||
NULL, &targetss.sockaddr, targetsslen,
|
||||
@@ -659,6 +707,11 @@ int ncat_connect(void)
|
||||
nsi_get_read_count(cs.sock_nsi), time);
|
||||
}
|
||||
|
||||
#if HAVE_SYS_UN_H
|
||||
if (o.af == AF_UNIX && o.udp)
|
||||
unlink(srcaddr.un.sun_path);
|
||||
#endif
|
||||
|
||||
nsp_delete(mypool);
|
||||
|
||||
return rc == NSOCK_LOOP_ERROR ? 1 : 0;
|
||||
|
||||
@@ -110,6 +110,10 @@
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -354,8 +358,10 @@ static void handle_connection(int socket_accept)
|
||||
int conn_count;
|
||||
|
||||
zmem(&s, sizeof(s));
|
||||
zmem(&remoteaddr, sizeof(remoteaddr.storage));
|
||||
|
||||
ss_len = sizeof(remoteaddr.storage);
|
||||
|
||||
errno = 0;
|
||||
s.fd = accept(socket_accept, &remoteaddr.sockaddr, &ss_len);
|
||||
|
||||
@@ -368,6 +374,11 @@ static void handle_connection(int socket_accept)
|
||||
}
|
||||
|
||||
if (o.verbose) {
|
||||
#if HAVE_SYS_UN_H
|
||||
if (remoteaddr.sockaddr.sa_family == AF_UNIX)
|
||||
loguser("Connection from a client on Unix domain socket.\n");
|
||||
else
|
||||
#endif
|
||||
if (o.chat)
|
||||
loguser("Connection from %s on file descriptor %d.\n", inet_socktop(&remoteaddr), s.fd);
|
||||
else
|
||||
@@ -383,8 +394,14 @@ static void handle_connection(int socket_accept)
|
||||
}
|
||||
}
|
||||
|
||||
if (o.verbose)
|
||||
loguser("Connection from %s:%hu.\n", inet_socktop(&remoteaddr), inet_port(&remoteaddr));
|
||||
if (o.verbose) {
|
||||
#if HAVE_SYS_UN_H
|
||||
if (remoteaddr.sockaddr.sa_family == AF_UNIX)
|
||||
loguser("Connection from %s.\n", remoteaddr.un.sun_path);
|
||||
else
|
||||
#endif
|
||||
loguser("Connection from %s:%hu.\n", inet_socktop(&remoteaddr), inet_port(&remoteaddr));
|
||||
}
|
||||
|
||||
/* Check conditions that might cause us to deny the connection. */
|
||||
conn_count = get_conn_count();
|
||||
@@ -776,6 +793,14 @@ static int ncat_listen_dgram(int proto)
|
||||
|
||||
int ncat_listen()
|
||||
{
|
||||
#if HAVE_SYS_UN_H
|
||||
if (o.af == AF_UNIX)
|
||||
if (o.udp)
|
||||
return ncat_listen_dgram(0);
|
||||
else
|
||||
return ncat_listen_stream(0);
|
||||
else
|
||||
#endif
|
||||
if (o.httpserver)
|
||||
return ncat_http_server();
|
||||
else if (o.udp)
|
||||
|
||||
@@ -229,6 +229,9 @@ int main(int argc, char *argv[])
|
||||
struct option long_options[] = {
|
||||
{"4", no_argument, NULL, '4'},
|
||||
{"6", no_argument, NULL, '6'},
|
||||
#if HAVE_SYS_UN_H
|
||||
{"unixsock", no_argument, NULL, 'U'},
|
||||
#endif
|
||||
{"crlf", no_argument, NULL, 'C'},
|
||||
{"g", required_argument, NULL, 'g'},
|
||||
{"G", required_argument, NULL, 'G'},
|
||||
@@ -286,7 +289,7 @@ int main(int argc, char *argv[])
|
||||
while (1) {
|
||||
/* handle command line arguments */
|
||||
int option_index;
|
||||
int c = getopt_long(argc, argv, "46Cc:e:g:G:i:km:hp:d:lo:x:ts:uvw:n",
|
||||
int c = getopt_long(argc, argv, "46UCc:e:g:G:i:km:hp:d:lo:x:ts:uvw:n",
|
||||
long_options, &option_index);
|
||||
|
||||
/* That's the end of the options. */
|
||||
@@ -304,6 +307,11 @@ int main(int argc, char *argv[])
|
||||
bye("-6 chosen when IPv6 wasn't compiled in.");
|
||||
#endif
|
||||
break;
|
||||
#if HAVE_SYS_UN_H
|
||||
case 'U':
|
||||
o.af = AF_UNIX;
|
||||
break;
|
||||
#endif
|
||||
case 'C':
|
||||
o.crlf = 1;
|
||||
break;
|
||||
@@ -469,6 +477,9 @@ int main(int argc, char *argv[])
|
||||
"'s' for seconds, 'm' for minutes, or 'h' for hours (e.g. 500ms).\n"
|
||||
" -4 Use IPv4 only\n"
|
||||
" -6 Use IPv6 only\n"
|
||||
#if HAVE_SYS_UN_H
|
||||
" -U, --unixsock Use Unix domain sockets only\n"
|
||||
#endif
|
||||
" -C, --crlf Use CRLF for EOL sequence\n"
|
||||
" -c, --sh-exec <command> Executes the given command via /bin/sh\n"
|
||||
" -e, --exec <command> Executes the given command\n"
|
||||
@@ -536,7 +547,25 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
nbase_set_log(loguser, NULL);
|
||||
|
||||
/* Will be AF_INET or AF_INET6 when valid */
|
||||
#if HAVE_SYS_UN_H
|
||||
/* Using Unix domain sockets, so do the checks now */
|
||||
if (o.af == AF_UNIX) {
|
||||
if (proxyaddr || o.proxytype)
|
||||
bye("Proxy option not supported when using Unix domain sockets.");
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (o.ssl)
|
||||
bye("SSL option not supported when using Unix domain sockets.");
|
||||
#endif
|
||||
if (o.broker)
|
||||
bye("Connection brokering not supported when using Unix domain sockets.");
|
||||
if (srcport != -1)
|
||||
bye("Specifying source port when using Unix domain sockets doesn't make sense.");
|
||||
if (o.numsrcrtes > 0)
|
||||
bye("Loose source routing not allowed when using Unix domain sockets.");
|
||||
}
|
||||
#endif /* HAVE_SYS_UN_H */
|
||||
|
||||
/* Will be AF_INET or AF_INET6 or AF_UNIX when valid */
|
||||
memset(&targetss.storage, 0, sizeof(targetss.storage));
|
||||
targetss.storage.ss_family = AF_UNSPEC;
|
||||
httpconnect.storage = socksconnect.storage = srcaddr.storage = targetss.storage;
|
||||
@@ -583,12 +612,26 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Resolve the given source address */
|
||||
if (source) {
|
||||
int rc;
|
||||
int rc = 0;
|
||||
|
||||
if (o.listen)
|
||||
bye("-l and -s are incompatible. Specify the address and port to bind to like you would a host to connect to.");
|
||||
|
||||
rc = resolve(source, 0, &srcaddr.storage, &srcaddrlen, o.af);
|
||||
#if HAVE_SYS_UN_H
|
||||
/* if using UNIX sockets just copy the path.
|
||||
* If it's not valid, it will fail later! */
|
||||
if (o.af == AF_UNIX) {
|
||||
if (o.udp) {
|
||||
srcaddr.un.sun_family = AF_UNIX;
|
||||
strncpy(srcaddr.un.sun_path, source, sizeof(srcaddr.un.sun_path));
|
||||
srcaddrlen = SUN_LEN(&srcaddr.un);
|
||||
}
|
||||
else
|
||||
if (o.verbose)
|
||||
loguser("Specifying source socket for other than DATAGRAM Unix domain sockets have no effect.\n");
|
||||
} else
|
||||
#endif
|
||||
rc = resolve(source, 0, &srcaddr.storage, &srcaddrlen, o.af);
|
||||
if (rc != 0)
|
||||
bye("Could not resolve source address \"%s\": %s.", source, gai_strerror(rc));
|
||||
}
|
||||
@@ -599,10 +642,28 @@ int main(int argc, char *argv[])
|
||||
host_list_free(deny_host_list);
|
||||
|
||||
if (optind == argc) {
|
||||
#if HAVE_SYS_UN_H
|
||||
if (o.af == AF_UNIX) {
|
||||
if (!o.listen)
|
||||
bye("You have to specify path to a socket to connect to.");
|
||||
else
|
||||
bye("You have to specify path to a socket to listen on.");
|
||||
}
|
||||
#endif
|
||||
/* Listen defaults to any address and DEFAULT_NCAT_PORT */
|
||||
if (!o.listen)
|
||||
bye("You must specify a host to connect to.");
|
||||
} else {
|
||||
#if HAVE_SYS_UN_H
|
||||
if (o.af == AF_UNIX) {
|
||||
memset(&targetss.storage, 0, sizeof(struct sockaddr_un));
|
||||
targetss.un.sun_family = AF_UNIX;
|
||||
strncpy(targetss.un.sun_path, argv[optind], sizeof(targetss.un.sun_path));
|
||||
targetsslen = SUN_LEN(&targetss.un);
|
||||
o.target = argv[optind];
|
||||
optind++;
|
||||
} else
|
||||
#endif
|
||||
/* Resolve hostname if we're given one */
|
||||
if (strspn(argv[optind], "0123456789") != strlen(argv[optind])) {
|
||||
int rc;
|
||||
@@ -620,6 +681,12 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Whatever's left is the port number; there should be at most one. */
|
||||
#if HAVE_SYS_UN_H
|
||||
/* We do not use ports with Unix domain sockets. */
|
||||
if (o.af == AF_UNIX && optind > argc)
|
||||
bye("Using Unix domain sockets and specifying port doesn't make sense.");
|
||||
#endif
|
||||
|
||||
if (optind + 1 < argc || (o.listen && srcport != -1 && optind + 1 == argc)) {
|
||||
loguser("Got more than one port specification:");
|
||||
if (o.listen && srcport != -1)
|
||||
@@ -644,6 +711,11 @@ int main(int argc, char *argv[])
|
||||
#ifdef HAVE_IPV6
|
||||
else if (targetss.storage.ss_family == AF_INET6)
|
||||
targetss.in6.sin6_port = htons(o.portno);
|
||||
#endif
|
||||
#if HAVE_SYS_UN_H
|
||||
/* If we use Unix domain sockets, we have to count with them. */
|
||||
else if (targetss.storage.ss_family == AF_UNIX)
|
||||
; /* Do nothing. */
|
||||
#endif
|
||||
else if (targetss.storage.ss_family == AF_UNSPEC)
|
||||
; /* Leave unspecified. */
|
||||
|
||||
@@ -91,11 +91,16 @@
|
||||
|
||||
/* $Id:$ */
|
||||
|
||||
#include "ncat_config.h"
|
||||
|
||||
#ifndef SOCKADDR_U_H_
|
||||
#define SOCKADDR_U_H_
|
||||
|
||||
union sockaddr_u {
|
||||
struct sockaddr_storage storage;
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
struct sockaddr_un un;
|
||||
#endif
|
||||
struct sockaddr_in in;
|
||||
struct sockaddr_in6 in6;
|
||||
struct sockaddr sockaddr;
|
||||
|
||||
34
ncat/util.c
34
ncat/util.c
@@ -406,21 +406,39 @@ int do_listen(int type, int proto, const union sockaddr_u *srcaddr_u)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
sa_len = srcaddr_u->sockaddr.sa_len;
|
||||
#else
|
||||
sa_len = sizeof(*srcaddr_u);
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
if (srcaddr_u->storage.ss_family == AF_UNIX)
|
||||
sa_len = SUN_LEN(&srcaddr_u->un);
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
sa_len = srcaddr_u->sockaddr.sa_len;
|
||||
#else
|
||||
sa_len = sizeof(*srcaddr_u);
|
||||
#endif
|
||||
|
||||
if (bind(sock, &srcaddr_u->sockaddr, sa_len) < 0) {
|
||||
bye("bind to %s:%hu: %s.", inet_socktop(srcaddr_u),
|
||||
inet_port(srcaddr_u), socket_strerror(socket_errno()));
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
if (srcaddr_u->storage.ss_family == AF_UNIX)
|
||||
bye("bind to %s: %s.", srcaddr_u->un.sun_path,
|
||||
socket_strerror(socket_errno()));
|
||||
else
|
||||
#endif
|
||||
bye("bind to %s:%hu: %s.", inet_socktop(srcaddr_u),
|
||||
inet_port(srcaddr_u), socket_strerror(socket_errno()));
|
||||
}
|
||||
|
||||
if (type == SOCK_STREAM)
|
||||
Listen(sock, BACKLOG);
|
||||
|
||||
if (o.verbose)
|
||||
loguser("Listening on %s:%hu\n", inet_socktop(srcaddr_u), inet_port(srcaddr_u));
|
||||
if (o.verbose) {
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
if (srcaddr_u->storage.ss_family == AF_UNIX)
|
||||
loguser("Listening on %s\n", srcaddr_u->un.sun_path);
|
||||
else
|
||||
#endif
|
||||
loguser("Listening on %s:%hu\n", inet_socktop(srcaddr_u), inet_port(srcaddr_u));
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
@@ -101,6 +101,10 @@
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user