mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-01 03:22:48 -05:00
Log identifying information for the other end of connections.
When anyone connects to a PuTTY tool's listening socket - whether it's a user of a local->remote port forwarding, a connection-sharing downstream or a client of Pageant - we'd like to log as much information as we can find out about where the connection came from. To that end, I've implemented a function sk_peer_info() in the socket abstraction, which returns a freeform text string as best it can (or NULL, if it can't get anything at all) describing the thing at the other end of the connection. For TCP connections, this is done using getpeername() to get an IP address and port in the obvious way; for Unix-domain sockets, we attempt SO_PEERCRED (conditionalised on some moderately hairy autoconfery) to get the pid and owner of the peer. I haven't implemented anything for Windows named pipes, but I will if I hear of anything useful.
This commit is contained in:
@ -186,4 +186,9 @@ void *sk_getxdmdata(void *sock, int *lenp);
|
||||
*/
|
||||
extern Backend serial_backend;
|
||||
|
||||
/*
|
||||
* uxpeer.c, wrapping getsockopt(SO_PEERCRED).
|
||||
*/
|
||||
int so_peercred(int fd, int *pid, int *uid, int *gid);
|
||||
|
||||
#endif
|
||||
|
51
unix/uxnet.c
51
unix/uxnet.c
@ -16,6 +16,8 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/un.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#define DEFINE_PLUG_METHOD_MACROS
|
||||
#include "putty.h"
|
||||
@ -485,6 +487,7 @@ static int sk_tcp_write(Socket s, const char *data, int len);
|
||||
static int sk_tcp_write_oob(Socket s, const char *data, int len);
|
||||
static void sk_tcp_write_eof(Socket s);
|
||||
static void sk_tcp_set_frozen(Socket s, int is_frozen);
|
||||
static char *sk_tcp_peer_info(Socket s);
|
||||
static const char *sk_tcp_socket_error(Socket s);
|
||||
|
||||
static struct socket_function_table tcp_fn_table = {
|
||||
@ -495,7 +498,8 @@ static struct socket_function_table tcp_fn_table = {
|
||||
sk_tcp_write_eof,
|
||||
sk_tcp_flush,
|
||||
sk_tcp_set_frozen,
|
||||
sk_tcp_socket_error
|
||||
sk_tcp_socket_error,
|
||||
sk_tcp_peer_info,
|
||||
};
|
||||
|
||||
static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
|
||||
@ -1420,6 +1424,51 @@ static void sk_tcp_set_frozen(Socket sock, int is_frozen)
|
||||
uxsel_tell(s);
|
||||
}
|
||||
|
||||
static char *sk_tcp_peer_info(Socket sock)
|
||||
{
|
||||
Actual_Socket s = (Actual_Socket) sock;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (getpeername(s->s, (struct sockaddr *)&addr, &addrlen) < 0)
|
||||
return NULL;
|
||||
if (addr.ss_family == AF_INET) {
|
||||
return dupprintf
|
||||
("%s:%d",
|
||||
inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr),
|
||||
(int)ntohs(((struct sockaddr_in *)&addr)->sin_port));
|
||||
#ifndef NO_IPV6
|
||||
} else if (addr.ss_family == AF_INET6) {
|
||||
return dupprintf
|
||||
("[%s]:%d",
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr,
|
||||
buf, sizeof(buf)),
|
||||
(int)ntohs(((struct sockaddr_in6 *)&addr)->sin6_port));
|
||||
#endif
|
||||
} else if (addr.ss_family == AF_UNIX) {
|
||||
/*
|
||||
* For Unix sockets, the source address is unlikely to be
|
||||
* helpful. Instead, we try SO_PEERCRED and try to get the
|
||||
* source pid.
|
||||
*/
|
||||
int pid, uid, gid;
|
||||
if (so_peercred(s->s, &pid, &uid, &gid)) {
|
||||
char uidbuf[64], gidbuf[64];
|
||||
sprintf(uidbuf, "%d", uid);
|
||||
sprintf(gidbuf, "%d", gid);
|
||||
struct passwd *pw = getpwuid(uid);
|
||||
struct group *gr = getgrgid(gid);
|
||||
return dupprintf("pid %d (%s:%s)", pid,
|
||||
pw ? pw->pw_name : uidbuf,
|
||||
gr ? gr->gr_name : gidbuf);
|
||||
}
|
||||
return NULL;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void uxsel_tell(Actual_Socket s)
|
||||
{
|
||||
int rwx = 0;
|
||||
|
32
unix/uxpeer.c
Normal file
32
unix/uxpeer.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Unix: wrapper for getsockopt(SO_PEERCRED), conditionalised on
|
||||
* appropriate autoconfery.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "uxconfig.h" /* leading space prevents mkfiles.pl trying to follow */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SO_PEERCRED
|
||||
#define _GNU_SOURCE
|
||||
#include <features.h>
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
int so_peercred(int fd, int *pid, int *uid, int *gid)
|
||||
{
|
||||
#ifdef HAVE_SO_PEERCRED
|
||||
struct ucred cr;
|
||||
socklen_t crlen = sizeof(cr);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crlen) == 0) {
|
||||
*pid = cr.pid;
|
||||
*uid = cr.uid;
|
||||
*gid = cr.gid;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
@ -245,7 +245,8 @@ Socket platform_new_connection(SockAddr addr, const char *hostname,
|
||||
sk_localproxy_write_eof,
|
||||
sk_localproxy_flush,
|
||||
sk_localproxy_set_frozen,
|
||||
sk_localproxy_socket_error
|
||||
sk_localproxy_socket_error,
|
||||
NULL, /* peer_info */
|
||||
};
|
||||
|
||||
Local_Proxy_Socket ret;
|
||||
|
Reference in New Issue
Block a user