Hi Hildegard, Hildegard Meier wrote: > > I think that works specifically because *no* new process is created > > when using internal-sftp as opposed to executing the sftp-server binary. > > For every sftp subsystem login (here with user "sftp_nagios"), I > see a new sftpd process created: .. > root 4192 0.0 0.1 72304 6512 ? Ss 11:01 0:00 /usr/sbin/sftpd -D -f /etc/sftpd/sftpd_config > root 4590 0.2 0.1 74736 6632 ? Ss 11:05 0:00 sftpd: sftp_nagios [priv] > sftp_na+ 4592 0.0 0.0 74736 3432 ? S 11:05 0:00 sftpd: sftp_nagios@notty > sftp_na+ 4593 0.0 0.0 74736 3108 ? Ss 11:05 0:00 sftpd: sftp_nagios@internal-sftp Thanks, yes, you're correct that there are new processes. I should have written different, refering to sshd vs. sftp-server: sshd creates one child process for each incoming TCP connection (4590) and after authentication it creates another child process (4592) which runs as the authenticated user to handle the session, and then the sftp subsystem channel is handled by yet another child process (4593). These processes all run (different parts of) sshd, they do not execute any other program, when using internal-sftp not even 4593. This is relevant because as mentioned there is then no point where sshd executes the sftp-server binary, so also no opportunity to use LD_PRELOAD only for SFTP. All of sftp-server is built into sshd, specifically to enable internal-sftp, with the great benefit that no sftp-server binary is needed inside the chroot. My thought was still wrong though. It could have been relevant for the syslog() socket because that is closed automatically on exec() and not on fork(), but sshd re-opens the syslog() socket right after fork() so the internal-sftp vs. sftp-server makes no difference for logging, only for LD_PRELOAD convenience. Hildegard Meier wrote: > Jochen Bern wrote: > > If a newly-started syslogd on server A does > > indeed REMOVE AND RECREATE the /dev/log sockets, > > If /dev dir under sftp user's chroot dir exists but there is no "log" > file in it, it gets created by syslog-ng. It is never removed afterwards. I had forgotten: AF_UNIX bind() to a filesystem address only succeeds if the socket inode does not already exist in the filesystem. So syslog-ng does what all AF_UNIX socket servers must: it unlinks the socket from the filesystem first, so that a new socket inode can be created by bind(). Jochen identified the problem. Jochen Bern wrote: > (The difference being that the socket itself would not have to store any > additional state about the open FDs pointing to it, which I doubt it has > any capacity for.) The inode itself doesn't store anything, the kernel just maps the filesystem inode to its socket object. Since the inode created by daemon B means nothing within the kernel on system A, connecting to that inode now also visible on system A doesn't reach daemon A. Jochen Bern wrote: > If that theory holds, then all we'd need to do is to force both > syslogd's to use *pre-existing* sockets instead ... That's unfortunately not possible. Hildegard Meier wrote: > I think both the LD_PRELOAD and overlay fs approach are too > complicated and hacky for me. Fair enough, and overlayfs is only possible with a Linux NFS server. There aren't very many other solutions: * A patch to change SFTP logging The attached patch adds an -E option to sftp-server (as exists for sshd) to log to a specific file. With -E /sftp.log on the internal-sftp command line in sshd_config on both servers they would then both log to a file in the user's home directory. Beware of write contention on that log file when the same user is connected to both servers. Ensure that the file exists before using this configuration. Make file ownership root:user and mode 620 if the user shouldn't be able to read it. The patch is small, but until an equivalent is accepted in OpenSSH, if ever, it requires maintaining a local package. Note that as proposed this patch only works with a regular file, not a syslog socket. Supporting a socket is of course possible but requires a larger patch re-implementing much of syslog(). I can write that if it would be accepted into OpenSSH. * Add -e to the internal-sftp command line and create a custom parser Because internal-sftp is still the sshd process this log message parser must be connected already to the initial sshd stderr and must handle anything that can be output on stderr by any sshd child process, not just SFTP messages, making this alternative less attractive. Kind regards //Peter
From 2764f03c48747b4a0054f88388c4e5df24d9304a Mon Sep 17 00:00:00 2001 From: Peter Stuge <peter@xxxxxxxx> Date: Thu, 30 Sep 2021 03:05:34 +0200 Subject: [PATCH] Add -E log_file option to sftp-server Like in sshd, this option uses stderr redirection to the given file. --- sftp-server.8 | 15 ++++++++++++++- sftp-server.c | 8 +++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/sftp-server.8 b/sftp-server.8 index 5311bf9..310a3ff 100644 --- a/sftp-server.8 +++ b/sftp-server.8 @@ -33,6 +33,7 @@ .Bk -words .Op Fl ehR .Op Fl d Ar start_directory +.Op Fl E Ar log_file .Op Fl f Ar log_facility .Op Fl l Ar log_level .Op Fl P Ar denied_requests @@ -78,6 +79,18 @@ option. Causes .Nm to print logging information to stderr instead of syslog for debugging. +.It Fl E Ar log_file +Log to +.Pa log_file +instead of using syslog. +The filename may contain the following tokens that are expanded at runtime: +%% is replaced by a literal '%', +%d is replaced by the home directory of the authenticated user, +and %u is replaced by the username of that user. +This option is useful in conjunction with the +.Xr sshd_config 5 +.Cm ChrootDirectory +option. .It Fl f Ar log_facility Specifies the facility code that is used when logging messages from .Nm . @@ -140,7 +153,7 @@ to be applied to newly-created files and directories, instead of the user's default mask. .El .Pp -On some systems, +Unless -e or -E is used, on some systems, .Nm must be able to access .Pa /dev/log diff --git a/sftp-server.c b/sftp-server.c index 18d1949..fa60214 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1723,7 +1723,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) pw = pwcopy(user_pw); while (!skipargs && (ch = getopt(argc, argv, - "d:f:l:P:p:Q:u:cehR")) != -1) { + "d:f:l:P:p:Q:u:cE:ehR")) != -1) { switch (ch) { case 'Q': if (strcasecmp(optarg, "requests") != 0) { @@ -1746,6 +1746,12 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) */ skipargs = 1; break; + case 'E': + cp = percent_expand(optarg, "d", user_pw->pw_dir, + "u", user_pw->pw_name, (char *)NULL); + log_redirect_stderr_to(cp); + free(cp); + /* FALLTHROUGH */ case 'e': log_stderr = 1; break; --
_______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev