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).");
#endif
srcaddr.un.sun_family = AF_UNIX;
strncpy(srcaddr.un.sun_path, tmp_name, sizeof(srcaddr.un.sun_path));
NCAT_INIT_SUN(&srcaddr, tmp_name);
free (tmp_name);
}

View File

@@ -406,24 +406,21 @@ int ncat_listen()
watch set. */
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 };
int conn_count;
zmem(&s, sizeof(s));
zmem(&remoteaddr, sizeof(remoteaddr.storage));
ss_len = sizeof(remoteaddr.storage);
s.ss_len = sizeof(s.remoteaddr.storage);
errno = 0;
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 {
char buf[4] = {0};
int nbytes = recvfrom(socket_accept, buf, sizeof(buf), MSG_PEEK,
&remoteaddr.sockaddr, &ss_len);
&s.remoteaddr.sockaddr, &s.ss_len);
if (nbytes < 0) {
loguser("%s.\n", socket_strerror(socket_errno()));
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
* 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;
// 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++) {
if (listen_socket[i] == socket_accept) {
struct fdinfo *lfdi = get_fdinfo(&client_fdlist, socket_accept);
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);
if (listen_socket[i] < 0) {
bye("do_listen(\"%s\"): %s\n", socktop(&listenaddrs[i], 0), socket_strerror(socket_errno()));
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 (o.debug)
@@ -462,14 +469,18 @@ static void handle_connection(int socket_accept, int type, fd_set *listen_fds)
if (!o.keepopen && !o.broker) {
int 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]);
checked_fd_clr(listen_socket[i], &master_readfds);
rm_fd(&client_fdlist, listen_socket[i]);
listen_socket[i] = -1;
}
}
}
if (o.verbose) {
loguser("Connection from %s", socktop(&remoteaddr, ss_len));
loguser("Connection from %s", socktop(&s.remoteaddr, s.ss_len));
if (o.chat)
loguser_noprefix(" on file descriptor %d", s.fd);
loguser_noprefix(".\n");
@@ -483,15 +494,13 @@ static void handle_connection(int socket_accept, int type, fd_set *listen_fds)
Close(s.fd);
return;
}
if (!allow_access(&remoteaddr)) {
if (!allow_access(&s.remoteaddr)) {
if (o.verbose)
loguser("New connection denied: not allowed\n");
Close(s.fd);
return;
}
s.remoteaddr = remoteaddr;
conn_inc++;
unblock_socket(s.fd);
@@ -770,14 +779,14 @@ static void shutdown_sockets(int how)
}
/* 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;
size_t size = 0, offset = 0;
int i, count, ret;
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: ");
count = 0;
@@ -785,7 +794,7 @@ static int chat_announce_connect(int fd, const union sockaddr_u *su)
union sockaddr_u tsu;
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;
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 (o.af == AF_UNIX) {
if (o.proto == IPPROTO_UDP) {
srcaddr.un.sun_family = AF_UNIX;
strncpy(srcaddr.un.sun_path, source, sizeof(srcaddr.un.sun_path));
NCAT_INIT_SUN(&srcaddr, source);
srcaddrlen = SUN_LEN(&srcaddr.un);
}
else
@@ -853,9 +852,7 @@ int main(int argc, char *argv[])
case 1:
#if HAVE_SYS_UN_H
if (o.af == AF_UNIX) {
memset(&targetaddrs->addr.storage, 0, sizeof(struct sockaddr_un));
targetaddrs->addr.un.sun_family = AF_UNIX;
strncpy(targetaddrs->addr.un.sun_path, argv[optind], sizeof(targetaddrs->addr.un.sun_path));
NCAT_INIT_SUN(&targetaddrs->addr, argv[optind]);
targetaddrs->addrlen = SUN_LEN(&targetaddrs->addr.un);
o.sslservername = o.target = argv[optind];
break;

View File

@@ -65,6 +65,18 @@
#ifndef 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
#include <linux/vm_sockets.h>
#endif
@@ -82,4 +94,37 @@ union sockaddr_u {
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

View File

@@ -70,8 +70,20 @@
#include <netinet/in.h>
#endif
#include "sockaddr_u.h"
#if HAVE_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
#ifdef HAVE_OPENSSL
@@ -86,8 +98,6 @@ size_t smul(size_t, size_t);
void windows_init();
#endif
#include "sockaddr_u.h"
void loguser(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
void loguser_noprefix(const char *fmt, ...)
@@ -143,6 +153,7 @@ void ms_to_timeval(struct timeval *tv, long ms)
struct fdinfo {
int fd;
union sockaddr_u remoteaddr;
socklen_t ss_len;
#ifdef HAVE_OPENSSL
SSL *ssl;
#endif