Blob Blame History Raw
diff -up openssh-5.8p1/audit-bsm.c.audit1a openssh-5.8p1/audit-bsm.c
--- openssh-5.8p1/audit-bsm.c.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/audit-bsm.c	2011-03-02 09:37:14.000000000 +0100
@@ -298,19 +298,26 @@ audit_connection_from(const char *host, 
 #endif
 }
 
-void
+int
 audit_run_command(const char *command)
 {
 	/* not implemented */
+	return 0;
 }
 
 void
-audit_end_command(const char *command)
+audit_end_command(int handle, const char *command)
 {
 	/* not implemented */
 }
 
 void
+audit_count_session_open(void)
+{
+	/* not necessary */
+}
+
+void
 audit_session_open(struct logininfo *li)
 {
 	/* not implemented */
diff -up openssh-5.8p1/audit.c.audit1a openssh-5.8p1/audit.c
--- openssh-5.8p1/audit.c.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/audit.c	2011-03-02 09:37:14.000000000 +0100
@@ -140,6 +140,17 @@ audit_event(ssh_audit_event_t event)
 }
 
 /*
+ * Called when a child process has called, or will soon call,
+ * audit_session_open.
+ */
+void
+audit_count_session_open(void)
+{
+	debug("audit count session open euid %d user %s", geteuid(),
+	      audit_username());
+}
+
+/*
  * Called when a user session is started.  Argument is the tty allocated to
  * the session, or NULL if no tty was allocated.
  *
@@ -174,22 +185,25 @@ audit_session_close(struct logininfo *li
 /*
  * This will be called when a user runs a non-interactive command.  Note that
  * it may be called multiple times for a single connection since SSH2 allows
- * multiple sessions within a single connection.
+ * multiple sessions within a single connection.  Returns a "handle" for
+ * audit_end_command.
  */
-void
+int
 audit_run_command(const char *command)
 {
 	debug("audit run command euid %d user %s command '%.200s'", geteuid(),
 	    audit_username(), command);
+	return 0;
 }
 
 /*
  * This will be called when the non-interactive command finishes.  Note that
  * it may be called multiple times for a single connection since SSH2 allows
- * multiple sessions within a single connection.
+ * multiple sessions within a single connection.  "handle" should come from
+ * the corresponding audit_run_command.
  */
 void
-audit_end_command(const char *command)
+audit_end_command(int handle, const char *command)
 {
 	debug("audit end nopty exec  euid %d user %s command '%.200s'", geteuid(),
 	    audit_username(), command);
diff -up openssh-5.8p1/audit.h.audit1a openssh-5.8p1/audit.h
--- openssh-5.8p1/audit.h.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/audit.h	2011-03-02 09:37:14.000000000 +0100
@@ -49,10 +49,11 @@ typedef enum ssh_audit_event_type ssh_au
 
 void	audit_connection_from(const char *, int);
 void	audit_event(ssh_audit_event_t);
+void	audit_count_session_open(void);
 void	audit_session_open(struct logininfo *);
 void	audit_session_close(struct logininfo *);
-void	audit_run_command(const char *);
-void 	audit_end_command(const char *);
+int	audit_run_command(const char *);
+void 	audit_end_command(int, const char *);
 ssh_audit_event_t audit_classify_auth(const char *);
 
 #endif /* _SSH_AUDIT_H */
diff -up openssh-5.8p1/audit-linux.c.audit1a openssh-5.8p1/audit-linux.c
--- openssh-5.8p1/audit-linux.c.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/audit-linux.c	2011-03-02 09:37:14.000000000 +0100
@@ -140,7 +140,7 @@ audit_connection_from(const char *host, 
 	/* not implemented */
 }
 
-void
+int
 audit_run_command(const char *command)
 {
 	if (!user_login_count++) 
@@ -148,10 +148,11 @@ audit_run_command(const char *command)
 		    NULL, "ssh", 1, AUDIT_USER_LOGIN);
 	linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
 	    NULL, "ssh", 1, AUDIT_USER_START);
+	return 0;
 }
 
 void
-audit_end_command(const char *command)
+audit_end_command(int handle, const char *command)
 {
 	linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
 	    NULL, "ssh", 1, AUDIT_USER_END);
@@ -161,6 +162,12 @@ audit_end_command(const char *command)
 }
 
 void
+audit_count_session_open(void)
+{
+	user_login_count++;
+}
+
+void
 audit_session_open(struct logininfo *li)
 {
 	if (!user_login_count++) 
diff -up openssh-5.8p1/monitor.c.audit1a openssh-5.8p1/monitor.c
--- openssh-5.8p1/monitor.c.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/monitor.c	2011-03-02 09:37:14.000000000 +0100
@@ -1291,6 +1291,12 @@ mm_session_close(Session *s)
 		debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
 		session_pty_cleanup2(s);
 	}
+#ifdef SSH_AUDIT_EVENTS
+	if (s->command != NULL) {
+		debug3("%s: command %d", __func__, s->command_handle);
+		session_end_command2(s);
+	}
+#endif
 	session_unused(s->self);
 }
 
@@ -1613,25 +1619,44 @@ mm_answer_audit_command(int socket, Buff
 {
 	u_int len;
 	char *cmd;
+	Session *s;
 
 	debug3("%s entering", __func__);
 	cmd = buffer_get_string(m, &len);
+
 	/* sanity check command, if so how? */
-	audit_run_command(cmd);
-	xfree(cmd);
+	s = session_new();
+	if (s == NULL)
+		fatal("%s: error allocating a session", __func__);
+	s->command = cmd;
+	s->command_handle = audit_run_command(cmd);
+
+	buffer_clear(m);
+	buffer_put_int(m, s->self);
+
+	mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m);
+
 	return (0);
 }
 
 int
 mm_answer_audit_end_command(int socket, Buffer *m)
 {
+	int handle;
 	u_int len;
 	char *cmd;
+	Session *s;
 
 	debug3("%s entering", __func__);
+	handle = buffer_get_int(m);
 	cmd = buffer_get_string(m, &len);
-	/* sanity check command, if so how? */
-	audit_end_command(cmd);
+
+	s = session_by_id(handle);
+	if (s == NULL || s->ttyfd != -1 || s->command == NULL ||
+	    strcmp(s->command, cmd) != 0)
+		fatal("%s: invalid handle", __func__);
+	mm_session_close(s);
+
 	xfree(cmd);
 	return (0);
 }
diff -up openssh-5.8p1/monitor.h.audit1a openssh-5.8p1/monitor.h
--- openssh-5.8p1/monitor.h.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/monitor.h	2011-03-02 09:37:15.000000000 +0100
@@ -60,7 +60,7 @@ enum monitor_reqtype {
 	MONITOR_REQ_PAM_RESPOND, MONITOR_ANS_PAM_RESPOND,
 	MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX,
 	MONITOR_REQ_AUDIT_EVENT, MONITOR_REQ_AUDIT_COMMAND,
-	MONITOR_REQ_AUDIT_END_COMMAND,
+	MONITOR_ANS_AUDIT_COMMAND, MONITOR_REQ_AUDIT_END_COMMAND,
 	MONITOR_REQ_TERM,
 	MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
 	MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-5.8p1/monitor_wrap.c.audit1a openssh-5.8p1/monitor_wrap.c
--- openssh-5.8p1/monitor_wrap.c.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/monitor_wrap.c	2011-03-02 09:37:15.000000000 +0100
@@ -1150,10 +1150,11 @@ mm_audit_event(ssh_audit_event_t event)
 	buffer_free(&m);
 }
 
-void
+int
 mm_audit_run_command(const char *command)
 {
 	Buffer m;
+	int handle;
 
 	debug3("%s entering command %s", __func__, command);
 
@@ -1161,17 +1162,23 @@ mm_audit_run_command(const char *command
 	buffer_put_cstring(&m, command);
 
 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
+	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, &m);
+
+	handle = buffer_get_int(&m);
 	buffer_free(&m);
+
+	return (handle);
 }
 
 void
-mm_audit_end_command(const char *command)
+mm_audit_end_command(int handle, const char *command)
 {
 	Buffer m;
 
 	debug3("%s entering command %s", __func__, command);
 
 	buffer_init(&m);
+	buffer_put_int(&m, handle);
 	buffer_put_cstring(&m, command);
 
 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m);
diff -up openssh-5.8p1/monitor_wrap.h.audit1a openssh-5.8p1/monitor_wrap.h
--- openssh-5.8p1/monitor_wrap.h.audit1a	2011-03-02 09:41:17.000000000 +0100
+++ openssh-5.8p1/monitor_wrap.h	2011-03-02 09:44:35.000000000 +0100
@@ -73,8 +73,8 @@ void mm_sshpam_free_ctx(void *);
 #ifdef SSH_AUDIT_EVENTS
 #include "audit.h"
 void mm_audit_event(ssh_audit_event_t);
-void mm_audit_run_command(const char *);
-void mm_audit_end_command(const char *);
+int mm_audit_run_command(const char *);
+void mm_audit_end_command(int, const char *);
 #endif
 
 struct Session;
diff -up openssh-5.8p1/session.c.audit1a openssh-5.8p1/session.c
--- openssh-5.8p1/session.c.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/session.c	2011-03-02 09:37:15.000000000 +0100
@@ -738,6 +738,14 @@ do_exec_pty(Session *s, const char *comm
 	/* Parent.  Close the slave side of the pseudo tty. */
 	close(ttyfd);
 
+#ifndef HAVE_OSF_SIA
+	/* do_login in the child did not affect state in this process,
+	   compensate.  From an architectural standpoint, this is extremely
+	   ugly. */
+	if (!(options.use_login && command == NULL))
+		audit_count_session_open();
+#endif
+
 	/* Enter interactive session. */
 	s->ptymaster = ptymaster;
 	packet_set_interactive(1, 
@@ -809,17 +817,19 @@ do_exec(Session *s, const char *command)
 	}
 
 #ifdef SSH_AUDIT_EVENTS
-	if (command != NULL) {
-		PRIVSEP(audit_run_command(command));
+	if (s->command != NULL || s->command_handle != -1)
+		fatal("do_exec: command already set");
+	if (command != NULL)
 		s->command = xstrdup(command);
-	} else if (s->ttyfd == -1) {
+	else if (s->ttyfd == -1) {
 		char *shell = s->pw->pw_shell;
 
 		if (shell[0] == '\0')	/* empty shell means /bin/sh */
 			shell =_PATH_BSHELL;
-		PRIVSEP(audit_run_command(shell));
 		s->command = xstrdup(shell);
 	}
+	if (s->command != NULL)
+		s->command_handle = PRIVSEP(audit_run_command(s->command));
 #endif
 	if (s->ttyfd != -1)
 		ret = do_exec_pty(s, command);
@@ -1843,6 +1853,7 @@ session_unused(int id)
 	sessions[id].ttyfd = -1;
 	sessions[id].ptymaster = -1;
 	sessions[id].x11_chanids = NULL;
+	sessions[id].command_handle = -1;
 	sessions[id].next_unused = sessions_first_unused;
 	sessions_first_unused = id;
 }
@@ -1925,6 +1936,19 @@ session_open(Authctxt *authctxt, int cha
 }
 
 Session *
+session_by_id(int id)
+{
+	if (id >= 0 && id < sessions_nalloc) {
+		Session *s = &sessions[id];
+		if (s->used)
+			return s;
+	}
+	debug("session_by_id: unknown id %d", id);
+	session_dump();
+	return NULL;
+}
+
+Session *
 session_by_tty(char *tty)
 {
 	int i;
@@ -2450,6 +2474,30 @@ session_exit_message(Session *s, int sta
 		chan_write_failed(c);
 }
 
+#ifdef SSH_AUDIT_EVENTS
+void
+session_end_command2(Session *s)
+{
+	if (s->command != NULL) {
+		audit_end_command(s->command_handle, s->command);
+		xfree(s->command);
+		s->command = NULL;
+		s->command_handle = -1;
+	}
+}
+
+static void
+session_end_command(Session *s)
+{
+	if (s->command != NULL) {
+		PRIVSEP(audit_end_command(s->command_handle, s->command));
+		xfree(s->command);
+		s->command = NULL;
+		s->command_handle = -1;
+	}
+}
+#endif
+
 void
 session_close(Session *s)
 {
@@ -2459,10 +2507,8 @@ session_close(Session *s)
 	if (s->ttyfd != -1)
 		session_pty_cleanup(s);
 #ifdef SSH_AUDIT_EVENTS
-	if (s->command) {
-		PRIVSEP(audit_end_command(s->command));
-		xfree(s->command);
-	}
+	if (s->command)
+		session_end_command(s);
 #endif
 	if (s->term)
 		xfree(s->term);
@@ -2683,6 +2729,15 @@ do_authenticated2(Authctxt *authctxt)
 	server_loop2(authctxt);
 }
 
+static void
+do_cleanup_one_session(Session *s)
+{
+	session_pty_cleanup2(s);
+#ifdef SSH_AUDIT_EVENTS
+	session_end_command2(s);
+#endif
+}
+
 void
 do_cleanup(Authctxt *authctxt)
 {
@@ -2731,5 +2786,5 @@ do_cleanup(Authctxt *authctxt)
 	 * or if running in monitor.
 	 */
 	if (!use_privsep || mm_is_monitor())
-		session_destroy_all(session_pty_cleanup2);
+		session_destroy_all(do_cleanup_one_session);
 }
diff -up openssh-5.8p1/session.h.audit1a openssh-5.8p1/session.h
--- openssh-5.8p1/session.h.audit1a	2011-03-02 09:37:14.000000000 +0100
+++ openssh-5.8p1/session.h	2011-03-02 09:37:15.000000000 +0100
@@ -63,6 +63,7 @@ struct Session {
 
 	/* exec */
 #ifdef SSH_AUDIT_EVENTS
+	int	command_handle;
 	char	*command;
 #endif
 };
@@ -77,8 +78,10 @@ void	 session_close_by_pid(pid_t, int);
 void	 session_close_by_channel(int, void *);
 void	 session_destroy_all(void (*)(Session *));
 void	 session_pty_cleanup2(Session *);
+void	 session_end_command2(Session *);
 
 Session	*session_new(void);
+Session *session_by_id(int);
 Session	*session_by_tty(char *);
 void	 session_close(Session *);
 void	 do_setusercontext(struct passwd *);