[patch] postauth processes to log via monitor

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

 



Hi,

there is a long standing problem with logging in chroots. Especially,
when you use %u in ChrootDirectory, it is nearly impossible to have
/dev/log in every possible chroot for all users.

It seems to be important mainly for sftp-internal session which are
simply configurable to be chrooted and where admins would like to log
sftp session commands.

I have put together a patch which introduces a new configuration option
LogViaMonitor. When this option is 'yes', then postauth unprivileged
processes log via their monitor process instead of via standard channels
(syslog, stderr).

I've removed closefrom() from close_child_fds() in order not to close
m_log_send_fd socket before sftp_server_main() is called. And I've put
it to a part of code where it's clear that there will be exec().

I'd appreciate any comment or suggestion.


Petr
-- 
Petr Lautrbach


diff --git a/log.c b/log.c
index 32e1d2e..d4caeb5 100644
--- a/log.c
+++ b/log.c
@@ -241,6 +241,11 @@ debug3(const char *fmt,...)
 void
 log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
 {
+	log_init_handler(av0, level, facility, on_stderr, 1);
+}
+
+void
+log_init_handler(char *av0, LogLevel level, SyslogFacility facility, int on_stderr, int reset_handler) {
 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
 	struct syslog_data sdata = SYSLOG_DATA_INIT;
 #endif
@@ -264,8 +269,10 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
 		exit(1);
 	}
 
-	log_handler = NULL;
-	log_handler_ctx = NULL;
+	if (reset_handler) {
+		log_handler = NULL;
+		log_handler_ctx = NULL;
+	}
 
 	log_on_stderr = on_stderr;
 	if (on_stderr)
diff --git a/log.h b/log.h
index ae7df25..30c3310 100644
--- a/log.h
+++ b/log.h
@@ -49,6 +49,7 @@ typedef enum {
 typedef void (log_handler_fn)(LogLevel, const char *, void *);
 
 void     log_init(char *, LogLevel, SyslogFacility, int);
+void     log_init_handler(char *, LogLevel, SyslogFacility, int, int);
 void     log_change_level(LogLevel);
 int      log_is_on_stderr(void);
 void     log_redirect_stderr_to(const char *);
diff --git a/monitor.c b/monitor.c
index dbe29f1..9f72979 100644
--- a/monitor.c
+++ b/monitor.c
@@ -363,6 +363,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
 	close(pmonitor->m_log_sendfd);
 	pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
 
+	pmonitor->m_state = "preauth";
+
 	authctxt = _authctxt;
 	memset(authctxt, 0, sizeof(*authctxt));
 
@@ -475,6 +477,8 @@ monitor_child_postauth(struct monitor *pmonitor)
 	signal(SIGXFSZ, SIG_IGN);
 #endif
 
+	pmonitor->m_state = "postauth";
+
 	if (compat20) {
 		mon_dispatch = mon_dispatch_postauth20;
 
@@ -543,7 +547,7 @@ monitor_read_log(struct monitor *pmonitor)
 	if (log_level_name(level) == NULL)
 		fatal("%s: invalid log level %u (corrupted message?)",
 		    __func__, level);
-	do_log2(level, "%s [preauth]", msg);
+	do_log2(level, "%s [%s]", msg, pmonitor->m_state);
 
 	buffer_free(&logmsg);
 	free(msg);
@@ -2051,13 +2055,14 @@ monitor_init(void)
 		mm_init_compression(mon->m_zlib);
 	}
 
+	mon->m_state = "";
 	return mon;
 }
 
 void
 monitor_reinit(struct monitor *mon)
 {
-	monitor_openfds(mon, 0);
+	monitor_openfds(mon, options.log_via_monitor);
 }
 
 #ifdef GSSAPI
diff --git a/monitor.h b/monitor.h
index 5bc41b5..78ed40d 100644
--- a/monitor.h
+++ b/monitor.h
@@ -77,6 +77,7 @@ struct monitor {
 	struct mm_master	*m_zlib;
 	struct Kex		**m_pkex;
 	pid_t			 m_pid;
+	char                    *m_state;
 };
 
 struct monitor *monitor_init(void);
diff --git a/servconf.c b/servconf.c
index b7f3294..c973ee4 100644
--- a/servconf.c
+++ b/servconf.c
@@ -99,6 +99,7 @@ initialize_server_options(ServerOptions *options)
 	options->tcp_keep_alive = -1;
 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
 	options->log_level = SYSLOG_LEVEL_NOT_SET;
+	options->log_via_monitor = -1;
 	options->rhosts_rsa_authentication = -1;
 	options->hostbased_authentication = -1;
 	options->hostbased_uses_name_from_packet_only = -1;
@@ -230,6 +231,8 @@ fill_default_server_options(ServerOptions *options)
 		options->log_facility = SYSLOG_FACILITY_AUTH;
 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
 		options->log_level = SYSLOG_LEVEL_INFO;
+	if (options->log_via_monitor == -1)
+		options->log_via_monitor = 0;
 	if (options->rhosts_rsa_authentication == -1)
 		options->rhosts_rsa_authentication = 0;
 	if (options->hostbased_authentication == -1)
@@ -334,7 +337,7 @@ typedef enum {
 	sUsePAM,
 	/* Standard Options */
 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
-	sPermitRootLogin, sLogFacility, sLogLevel,
+	sPermitRootLogin, sLogFacility, sLogLevel, sLogViaMonitor,
 	sRhostsRSAAuthentication, sRSAAuthentication,
 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
 	sKerberosGetAFSToken,
@@ -394,6 +397,7 @@ static struct {
 	{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
 	{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
 	{ "loglevel", sLogLevel, SSHCFG_GLOBAL },
+	{ "logviamonitor", sLogViaMonitor, SSHCFG_GLOBAL },
 	{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
 	{ "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
 	{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
@@ -1239,6 +1243,10 @@ process_server_config_line(ServerOptions *options, char *line,
 			*log_level_ptr = (LogLevel) value;
 		break;
 
+	case sLogViaMonitor:
+		intptr = &options->log_via_monitor;
+		goto parse_flag;
+
 	case sAllowTcpForwarding:
 		intptr = &options->allow_tcp_forwarding;
 		multistate_ptr = multistate_tcpfwd;
@@ -2090,6 +2098,7 @@ dump_config(ServerOptions *o)
 	/* string arguments requiring a lookup */
 	dump_cfg_string(sLogLevel, log_level_name(o->log_level));
 	dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
+	dump_cfg_fmtint(sLogViaMonitor, o->log_via_monitor);
 
 	/* string array arguments */
 	dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
diff --git a/servconf.h b/servconf.h
index 766db3a..f61365c 100644
--- a/servconf.h
+++ b/servconf.h
@@ -95,6 +95,7 @@ typedef struct {
 	struct ForwardOptions fwd_opts;	/* forwarding options */
 	SyslogFacility log_facility;	/* Facility for system logging. */
 	LogLevel log_level;	/* Level for system logging. */
+	int     log_via_monitor; /* Monitor childs will log via monitor instead of syslog/stderr */
 	int     rhosts_rsa_authentication;	/* If true, permit rhosts RSA
 						 * authentication. */
 	int     hostbased_authentication;	/* If true, permit ssh2 hostbased auth */
diff --git a/session.c b/session.c
index 3e96557..e870f1f 100644
--- a/session.c
+++ b/session.c
@@ -505,8 +505,8 @@ do_exec_no_pty(Session *s, const char *command)
 		is_child = 1;
 
 		/* Child.  Reinitialize the log since the pid has changed. */
-		log_init(__progname, options.log_level,
-		    options.log_facility, log_stderr);
+		log_init_handler(__progname, options.log_level,
+		    options.log_facility, log_stderr, !options.log_via_monitor);
 
 		/*
 		 * Create a new session and process group since the 4.4BSD
@@ -674,8 +674,8 @@ do_exec_pty(Session *s, const char *command)
 		close(ptymaster);
 
 		/* Child.  Reinitialize the log because the pid has changed. */
-		log_init(__progname, options.log_level,
-		    options.log_facility, log_stderr);
+		log_init_handler(__progname, options.log_level,
+		    options.log_facility, log_stderr, !options.log_via_monitor);
 		/* Close the master side of the pseudo tty. */
 		close(ptyfd);
 
@@ -1645,14 +1645,6 @@ child_close_fds(void)
 	 * descriptors left by system functions.  They will be closed later.
 	 */
 	endpwent();
-
-	/*
-	 * Close any extra open file descriptors so that we don't have them
-	 * hanging around in clients.  Note that we want to do this after
-	 * initgroups, because at least on Solaris 2.3 it leaves file
-	 * descriptors open.
-	 */
-	closefrom(STDERR_FILENO + 1);
 }
 
 /*
@@ -1798,8 +1790,6 @@ do_child(Session *s, const char *command)
 			exit(1);
 	}
 
-	closefrom(STDERR_FILENO + 1);
-
 	if (!options.use_login)
 		do_rc_files(s, shell);
 
@@ -1826,9 +1816,17 @@ do_child(Session *s, const char *command)
 #ifdef WITH_SELINUX
 		ssh_selinux_change_context("sftpd_t");
 #endif
-		exit(sftp_server_main(i, argv, s->pw));
+		exit(sftp_server_main(i, argv, s->pw, 0));
 	}
 
+	/*
+	 * Close any extra open file descriptors so that we don't have them
+	 * hanging around in clients.  Note that we want to do this after
+	 * initgroups, because at least on Solaris 2.3 it leaves file
+	 * descriptors open.
+	 */
+	closefrom(STDERR_FILENO + 1);
+
 	fflush(NULL);
 
 	if (options.use_login) {
diff --git a/sftp-server-main.c b/sftp-server-main.c
index 7e644ab..e162b7a 100644
--- a/sftp-server-main.c
+++ b/sftp-server-main.c
@@ -47,5 +47,5 @@ main(int argc, char **argv)
 		return 1;
 	}
 
-	return (sftp_server_main(argc, argv, user_pw));
+	return (sftp_server_main(argc, argv, user_pw, 0));
 }
diff --git a/sftp-server.c b/sftp-server.c
index 0177130..8fa7fc7 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -1440,7 +1440,7 @@ sftp_server_usage(void)
 }
 
 int
-sftp_server_main(int argc, char **argv, struct passwd *user_pw)
+sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handler)
 {
 	fd_set *rset, *wset;
 	int i, in, out, max, ch, skipargs = 0, log_stderr = 0;
@@ -1453,7 +1453,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
 	extern char *__progname;
 
 	__progname = ssh_get_progname(argv[0]);
-	log_init(__progname, log_level, log_facility, log_stderr);
+	log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler);
 
 	pw = pwcopy(user_pw);
 
@@ -1524,7 +1524,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
 		}
 	}
 
-	log_init(__progname, log_level, log_facility, log_stderr);
+	log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler);
 
 #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
 	/*
diff --git a/sftp.h b/sftp.h
index 2bde8bb..ddf1a39 100644
--- a/sftp.h
+++ b/sftp.h
@@ -97,5 +97,5 @@
 
 struct passwd;
 
-int	sftp_server_main(int, char **, struct passwd *);
+int	sftp_server_main(int, char **, struct passwd *, int);
 void	sftp_server_cleanup_exit(int) __attribute__((noreturn));
diff --git a/sshd.c b/sshd.c
index 481d001..c86ac41 100644
--- a/sshd.c
+++ b/sshd.c
@@ -751,6 +751,12 @@ privsep_postauth(Authctxt *authctxt)
 
 	close(pmonitor->m_sendfd);
 	pmonitor->m_sendfd = -1;
+	close(pmonitor->m_log_recvfd);
+	pmonitor->m_log_recvfd = -1;
+
+	/* Arrange for logging to be sent to the monitor */
+	if (options.log_via_monitor)
+		set_log_handler(mm_log_handler, pmonitor);
 
 	/* Demote the private keys to public keys. */
 	demote_sensitive_data();
diff --git a/sshd_config b/sshd_config
index e9045bc..cd95720 100644
--- a/sshd_config
+++ b/sshd_config
@@ -37,6 +37,7 @@
 # obsoletes QuietMode and FascistLogging
 #SyslogFacility AUTH
 #LogLevel INFO
+#LogViaMonitor no
 
 # Authentication:
 
diff --git a/sshd_config.5 b/sshd_config.5
index 6766b57..fc0aa0a 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -795,6 +795,16 @@ The default is INFO.
 DEBUG and DEBUG1 are equivalent.
 DEBUG2 and DEBUG3 each specify higher levels of debugging output.
 Logging with a DEBUG level violates the privacy of users and is not recommended.
+.It Cm LogViaMonitor
+Specifies whether postauth unprivileged processes should log via a monitor.
+The
+.Dq no
+means standard logging, while
+.Dq yes
+means that processes will log via its monitor process which is usefull when
+there's no standard method available (missing /dev/log in chroots).
+The default is
+.Dq no .
 .It Cm MACs
 Specifies the available MAC (message authentication code) algorithms.
 The MAC algorithm is used in protocol version 2
_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@xxxxxxxxxxx
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux