1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-10 09:49:05 +00:00

Make sure Unix socket path is null-terminated, per unix(7)

This commit is contained in:
dmiller
2022-10-14 00:58:22 +00:00
parent ca691d2789
commit 6a9acb1f1a
5 changed files with 99 additions and 38 deletions

View File

@@ -1008,8 +1008,7 @@ int ncat_connect(void)
bye("Failed to create name for temporary DGRAM source Unix domain socket (tempnam)."); bye("Failed to create name for temporary DGRAM source Unix domain socket (tempnam).");
#endif #endif
srcaddr.un.sun_family = AF_UNIX; NCAT_INIT_SUN(&srcaddr, tmp_name);
strncpy(srcaddr.un.sun_path, tmp_name, sizeof(srcaddr.un.sun_path));
free (tmp_name); free (tmp_name);
} }

View File

@@ -406,24 +406,21 @@ int ncat_listen()
watch set. */ watch set. */
static void handle_connection(int socket_accept, int type, fd_set *listen_fds) static void handle_connection(int socket_accept, int type, fd_set *listen_fds)
{ {
union sockaddr_u remoteaddr;
socklen_t ss_len;
struct fdinfo s = { 0 }; struct fdinfo s = { 0 };
int conn_count; int conn_count;
zmem(&s, sizeof(s)); zmem(&s, sizeof(s));
zmem(&remoteaddr, sizeof(remoteaddr.storage));
ss_len = sizeof(remoteaddr.storage); s.ss_len = sizeof(s.remoteaddr.storage);
errno = 0; errno = 0;
if (type == SOCK_STREAM) { if (type == SOCK_STREAM) {
s.fd = accept(socket_accept, &remoteaddr.sockaddr, &ss_len); s.fd = accept(socket_accept, &s.remoteaddr.sockaddr, &s.ss_len);
} }
else { else {
char buf[4] = {0}; char buf[4] = {0};
int nbytes = recvfrom(socket_accept, buf, sizeof(buf), MSG_PEEK, int nbytes = recvfrom(socket_accept, buf, sizeof(buf), MSG_PEEK,
&remoteaddr.sockaddr, &ss_len); &s.remoteaddr.sockaddr, &s.ss_len);
if (nbytes < 0) { if (nbytes < 0) {
loguser("%s.\n", socket_strerror(socket_errno())); loguser("%s.\n", socket_strerror(socket_errno()));
return; return;
@@ -432,24 +429,34 @@ static void handle_connection(int socket_accept, int type, fd_set *listen_fds)
* We're using connected udp. This has the down side of only * We're using connected udp. This has the down side of only
* being able to handle one udp client at a time * being able to handle one udp client at a time
*/ */
Connect(socket_accept, &remoteaddr.sockaddr, ss_len); Connect(socket_accept, &s.remoteaddr.sockaddr, s.ss_len);
s.fd = socket_accept; s.fd = socket_accept;
// Remove this socket from listening and put a new one up. /* If we expect new connections, we'll have to open a new listening
* socket to replace the one we just connected to a single client. */
if ((o.keepopen || o.broker)
#if HAVE_SYS_UN_H
/* unless it's a UNIX socket, since we get EADDRINUSE when we try to bind */
&& s.remoteaddr.storage.ss_family != AF_UNIX
#endif
) {
for (int i = 0; i < num_listenaddrs; i++) { for (int i = 0; i < num_listenaddrs; i++) {
if (listen_socket[i] == socket_accept) { if (listen_socket[i] == socket_accept) {
struct fdinfo *lfdi = get_fdinfo(&client_fdlist, socket_accept); struct fdinfo *lfdi = get_fdinfo(&client_fdlist, socket_accept);
union sockaddr_u localaddr = lfdi->remoteaddr; union sockaddr_u localaddr = lfdi->remoteaddr;
checked_fd_clr(socket_accept, &master_readfds);
checked_fd_clr(socket_accept, listen_fds);
rm_fd(&client_fdlist, socket_accept);
listen_socket[i] = new_listen_socket(type, (o.af == AF_INET || o.af == AF_INET6) ? o.proto : 0, &localaddr, listen_fds); listen_socket[i] = new_listen_socket(type, (o.af == AF_INET || o.af == AF_INET6) ? o.proto : 0, &localaddr, listen_fds);
if (listen_socket[i] < 0) { if (listen_socket[i] < 0) {
bye("do_listen(\"%s\"): %s\n", socktop(&listenaddrs[i], 0), socket_strerror(socket_errno())); bye("do_listen(\"%s\"): %s\n", socktop(&listenaddrs[i], 0), socket_strerror(socket_errno()));
return; return;
} }
break;
} }
} }
} }
/* Remove this socket from listening */
checked_fd_clr(socket_accept, &master_readfds);
checked_fd_clr(socket_accept, listen_fds);
rm_fd(&client_fdlist, socket_accept);
}
if (s.fd < 0) { if (s.fd < 0) {
if (o.debug) if (o.debug)
@@ -462,14 +469,18 @@ static void handle_connection(int socket_accept, int type, fd_set *listen_fds)
if (!o.keepopen && !o.broker) { if (!o.keepopen && !o.broker) {
int i; int i;
for (i = 0; i < num_listenaddrs; i++) { for (i = 0; i < num_listenaddrs; i++) {
/* If */
if (listen_socket[i] >= 0 && checked_fd_isset(listen_socket[i], listen_fds)) {
Close(listen_socket[i]); Close(listen_socket[i]);
checked_fd_clr(listen_socket[i], &master_readfds); checked_fd_clr(listen_socket[i], &master_readfds);
rm_fd(&client_fdlist, listen_socket[i]); rm_fd(&client_fdlist, listen_socket[i]);
listen_socket[i] = -1;
}
} }
} }
if (o.verbose) { if (o.verbose) {
loguser("Connection from %s", socktop(&remoteaddr, ss_len)); loguser("Connection from %s", socktop(&s.remoteaddr, s.ss_len));
if (o.chat) if (o.chat)
loguser_noprefix(" on file descriptor %d", s.fd); loguser_noprefix(" on file descriptor %d", s.fd);
loguser_noprefix(".\n"); loguser_noprefix(".\n");
@@ -483,15 +494,13 @@ static void handle_connection(int socket_accept, int type, fd_set *listen_fds)
Close(s.fd); Close(s.fd);
return; return;
} }
if (!allow_access(&remoteaddr)) { if (!allow_access(&s.remoteaddr)) {
if (o.verbose) if (o.verbose)
loguser("New connection denied: not allowed\n"); loguser("New connection denied: not allowed\n");
Close(s.fd); Close(s.fd);
return; return;
} }
s.remoteaddr = remoteaddr;
conn_inc++; conn_inc++;
unblock_socket(s.fd); unblock_socket(s.fd);
@@ -770,14 +779,14 @@ static void shutdown_sockets(int how)
} }
/* Announce the new connection and who is already connected. */ /* Announce the new connection and who is already connected. */
static int chat_announce_connect(int fd, const union sockaddr_u *su) static int chat_announce_connect(const struct fdinfo *fdi)
{ {
char *buf = NULL; char *buf = NULL;
size_t size = 0, offset = 0; size_t size = 0, offset = 0;
int i, count, ret; int i, count, ret;
strbuf_sprintf(&buf, &size, &offset, strbuf_sprintf(&buf, &size, &offset,
"<announce> %s is connected as <user%d>.\n", socktop(su, 0), fd); "<announce> %s is connected as <user%d>.\n", socktop(&fdi->remoteaddr, fdi->ss_len), fdi->fd);
strbuf_sprintf(&buf, &size, &offset, "<announce> already connected: "); strbuf_sprintf(&buf, &size, &offset, "<announce> already connected: ");
count = 0; count = 0;
@@ -785,7 +794,7 @@ static int chat_announce_connect(int fd, const union sockaddr_u *su)
union sockaddr_u tsu; union sockaddr_u tsu;
socklen_t len = sizeof(tsu.storage); socklen_t len = sizeof(tsu.storage);
if (i == fd || !checked_fd_isset(i, &master_broadcastfds)) if (i == fdi->fd || !checked_fd_isset(i, &master_broadcastfds))
continue; continue;
if (getpeername(i, &tsu.sockaddr, &len) == -1) if (getpeername(i, &tsu.sockaddr, &len) == -1)

View File

@@ -794,8 +794,7 @@ int main(int argc, char *argv[])
* If it's not valid, it will fail later! */ * If it's not valid, it will fail later! */
if (o.af == AF_UNIX) { if (o.af == AF_UNIX) {
if (o.proto == IPPROTO_UDP) { if (o.proto == IPPROTO_UDP) {
srcaddr.un.sun_family = AF_UNIX; NCAT_INIT_SUN(&srcaddr, source);
strncpy(srcaddr.un.sun_path, source, sizeof(srcaddr.un.sun_path));
srcaddrlen = SUN_LEN(&srcaddr.un); srcaddrlen = SUN_LEN(&srcaddr.un);
} }
else else
@@ -853,9 +852,7 @@ int main(int argc, char *argv[])
case 1: case 1:
#if HAVE_SYS_UN_H #if HAVE_SYS_UN_H
if (o.af == AF_UNIX) { if (o.af == AF_UNIX) {
memset(&targetaddrs->addr.storage, 0, sizeof(struct sockaddr_un)); NCAT_INIT_SUN(&targetaddrs->addr, argv[optind]);
targetaddrs->addr.un.sun_family = AF_UNIX;
strncpy(targetaddrs->addr.un.sun_path, argv[optind], sizeof(targetaddrs->addr.un.sun_path));
targetaddrs->addrlen = SUN_LEN(&targetaddrs->addr.un); targetaddrs->addrlen = SUN_LEN(&targetaddrs->addr.un);
o.sslservername = o.target = argv[optind]; o.sslservername = o.target = argv[optind];
break; break;

View File

@@ -65,6 +65,18 @@
#ifndef SOCKADDR_U_H_ #ifndef SOCKADDR_U_H_
#define SOCKADDR_U_H_ #define SOCKADDR_U_H_
#ifdef WIN32
# include <ws2def.h>
#endif
#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#if HAVE_SYS_UN_H
# include <sys/un.h>
#endif
#if HAVE_LINUX_VM_SOCKETS_H #if HAVE_LINUX_VM_SOCKETS_H
#include <linux/vm_sockets.h> #include <linux/vm_sockets.h>
#endif #endif
@@ -82,4 +94,37 @@ union sockaddr_u {
struct sockaddr sockaddr; struct sockaddr sockaddr;
}; };
static inline socklen_t get_socklen(const union sockaddr_u *s)
{
switch(s->storage.ss_family) {
#ifdef HAVE_SYS_UN_H
case AF_UNIX:
return SUN_LEN(&s->un);
break;
#endif
#ifdef HAVE_LINUX_VM_SOCKETS_H
case AF_VSOCK:
return sizeof(struct sockaddr_vm);
break;
#endif
#ifdef HAVE_SOCKADDR_SA_LEN
default:
return s->sockaddr.sa_len;
break;
#else
case AF_INET:
return sizeof(struct sockaddr_in);
break;
#ifdef AF_INET6
case AF_INET6:
return sizeof(struct sockaddr_in6);
break;
#endif
default:
return sizeof(union sockaddr_u);
break;
#endif
}
return 0;
}
#endif #endif

View File

@@ -70,8 +70,20 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#include "sockaddr_u.h"
#if HAVE_SYS_UN_H #if HAVE_SYS_UN_H
#include <sys/un.h> #include <sys/un.h>
#include <string.h>
#define NCAT_INIT_SUN(_Sock, _Source) do { \
memset(_Sock, 0, sizeof(union sockaddr_u)); \
(_Sock)->un.sun_family = AF_UNIX; \
if (strlen(_Source) > sizeof((_Sock)->un.sun_path) - 1) \
bye("Socket path length is too long. Max: %lu", sizeof((_Sock)->un.sun_path) - 1); \
strncpy((_Sock)->un.sun_path, _Source, sizeof((_Sock)->un.sun_path) - 1); \
} while (0);
#endif #endif
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
@@ -86,8 +98,6 @@ size_t smul(size_t, size_t);
void windows_init(); void windows_init();
#endif #endif
#include "sockaddr_u.h"
void loguser(const char *fmt, ...) void loguser(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2))); __attribute__ ((format (printf, 1, 2)));
void loguser_noprefix(const char *fmt, ...) void loguser_noprefix(const char *fmt, ...)
@@ -143,6 +153,7 @@ void ms_to_timeval(struct timeval *tv, long ms)
struct fdinfo { struct fdinfo {
int fd; int fd;
union sockaddr_u remoteaddr; union sockaddr_u remoteaddr;
socklen_t ss_len;
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
SSL *ssl; SSL *ssl;
#endif #endif