Hi Hildegard, Hildegard Meier wrote: > I think, the sftpd process should just not write to the /dev/log > unix socket (because this leads to the problem here), but to the > local kernel directly, something like what you describe here. Exactly, but unfortunately the code that sets the socket path is in the system C library, without any interface to control the setting. > But how could I do this concrete with Ubuntu Linux? What you write > is rather abstract and I am not so expert that I understand what > you mean with LD_PRELOAD wrapper. Setting the LD_PRELOAD environment variable to a library filename when starting a program loads that library into memory before the system C library and the program itself. Symbols (ie. functions) loaded from the preloaded library are not replaced by later (system) libraries, making it possible to override and/or wrap libc functionality in this fairly brutish way, hence a bit unpleasant. Attached is source code for a simple such wrapper overriding openlog(), syslog() and closelog(). It might work only on the older system, or on both. You only need this hack on one server, the other can use /dev/log. The wrapper directs logging to /dev/log_<hostname> instead of /dev/log. Since libc has no interface to manipulate the socket path these functions override the normal functions with a very limited implementation. Adjust the template on line 49 if you want to change the destinateion. Although functionality is limited it could work well for sftp-server. One simplification is that this openlog() ignores all option flags except LOG_NDELAY and that syslog() always behaves as if openlog() was called with the LOG_PID option. Since this is exactly what OpenSSH log.c does all log messages should look the same as with the libc implementation. Note that log messages are silently lost on any error, e.g. syslog-ng not running. Also note that if log messages, the openlog() ident parameter or the username (when ident == NULL) are very long then messages are silently truncated to 2048 chars. OpenSSH sends max 500 chars. You didn't mention if your two sshd are configured to use the in-process sftp-server (Subsystem sftp internal-sftp in sshd_config) - if so then this is probably not really the best solution, since LD_PRELOAD would have to be set for the entire sshd process, which I don't recommend because this code is so simplistic compared to libc. Anyway, try it if you like. The comment near the top of the file shows how to compile. sshd can't be configured to set LD_PRELOAD so to use the compiled .so with sftp-server you have to create a simple script: --8<-- /usr/local/libexec/sftp-server-hostlog #!/bin/sh export LD_PRELOAD=/usr/local/libexec/hostlog.so exec /usr/lib/sftp-server "$*" -->8-- and then configure sshd to call that instead of sftp-server: --8<-- /etc/ssh/sshd_config Subsystem sftp /usr/local/libexec/sftp-server-hostlog -->8-- Adjust paths as needed, also in the compile command. For anyone else interested please go ahead but note that I haven't put huge effort into portability; it might work outside Linux but I haven't tested anywhere else so YMMV. Kind regards //Peter
/* Copyright (c) 2021 Peter Stuge */ /* SPDX-License-Identifier: MIT */ /* This very limited syslog() implementation sends messages to * /dev/log_<hostname> instead of /dev/log and fails silently on any error. * * build: cc -std=c89 -shared -fPIC -s -o hostlog.so hostlog.c * usage: LD_PRELOAD=./hostlog.so program_using_libc_syslog args ... */ #define _POSIX_C_SOURCE 200112L /* gethostname() */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <limits.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> #include <time.h> #ifndef LOG_NDELAY #define LOG_NDELAY 0x08 #endif #ifndef LOG_USER #define LOG_USER (1<<3) #endif static const char *opened_ident = NULL; static int opened_facility = LOG_USER; static int sockfd = -1; static void close_sockfd(void) { if (sockfd != -1) { close(sockfd); sockfd = -1; } } static int open_sockfd(void) { char hostname[HOST_NAME_MAX + 1]; struct sockaddr_un un; int fd; if (-1 == gethostname(hostname, sizeof hostname)) return -1; hostname[sizeof hostname - 1] = 0; un.sun_family = AF_UNIX; if (snprintf(un.sun_path, sizeof un.sun_path, "/dev/log_%s", hostname) >= sizeof un.sun_path) return -1; fd = socket(un.sun_family, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (-1 == fd) return -1; if (-1 == connect(fd, (const struct sockaddr *)&un, sizeof un)) { close(fd); return -1; } close_sockfd(); sockfd = fd; return sockfd; } void openlog(const char *ident, int option, int facility) { opened_ident = ident; opened_facility = facility; if (option & LOG_NDELAY) open_sockfd(); } void syslog(int priority, const char *format, ...) { time_t now; char timestr[64], msg[2049]; int len; va_list ap; if (-1 == sockfd && -1 == open_sockfd()) return; now = time(NULL); strftime(timestr, sizeof timestr, "%b %d %H:%M:%S", localtime(&now)); len = snprintf(msg, sizeof msg, "<%u>%s %s[%u]: ", opened_facility | priority, timestr, opened_ident ? opened_ident : getenv("USER"), getpid()); if (len < sizeof msg) { va_start(ap, format); len += vsnprintf(msg + len, sizeof msg - len, format, ap); va_end(ap); } if (len >= sizeof msg) len = sizeof msg - 1; sendto(sockfd, msg, len, MSG_NOSIGNAL, NULL, 0); } void closelog(void) { close_sockfd(); opened_ident = NULL; opened_facility = LOG_USER; }
_______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev