1
0
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:
david
2012-11-12 20:44:40 +00:00
parent f01e3800fb
commit 6531a19892
10 changed files with 199 additions and 18 deletions

View File

@@ -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
View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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)

View File

@@ -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. */

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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