417 lines
13 KiB
Diff
417 lines
13 KiB
Diff
diff -up openssh-5.8p1/audit-bsm.c.audit1 openssh-5.8p1/audit-bsm.c
|
|
--- openssh-5.8p1/audit-bsm.c.audit1 2011-01-17 11:15:29.000000000 +0100
|
|
+++ openssh-5.8p1/audit-bsm.c 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -305,6 +305,12 @@ audit_run_command(const char *command)
|
|
}
|
|
|
|
void
|
|
+audit_end_command(const char *command)
|
|
+{
|
|
+ /* not implemented */
|
|
+}
|
|
+
|
|
+void
|
|
audit_session_open(struct logininfo *li)
|
|
{
|
|
/* not implemented */
|
|
diff -up openssh-5.8p1/audit.c.audit1 openssh-5.8p1/audit.c
|
|
--- openssh-5.8p1/audit.c.audit1 2011-01-17 11:15:30.000000000 +0100
|
|
+++ openssh-5.8p1/audit.c 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -182,5 +182,18 @@ audit_run_command(const char *command)
|
|
debug("audit run command euid %d user %s command '%.200s'", geteuid(),
|
|
audit_username(), command);
|
|
}
|
|
+
|
|
+/*
|
|
+ * 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.
|
|
+ */
|
|
+void
|
|
+audit_end_command(const char *command)
|
|
+{
|
|
+ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(),
|
|
+ audit_username(), command);
|
|
+}
|
|
+
|
|
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
|
|
#endif /* SSH_AUDIT_EVENTS */
|
|
diff -up openssh-5.8p1/audit.h.audit1 openssh-5.8p1/audit.h
|
|
--- openssh-5.8p1/audit.h.audit1 2011-01-17 11:15:30.000000000 +0100
|
|
+++ openssh-5.8p1/audit.h 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -52,6 +52,7 @@ void audit_event(ssh_audit_event_t);
|
|
void audit_session_open(struct logininfo *);
|
|
void audit_session_close(struct logininfo *);
|
|
void audit_run_command(const char *);
|
|
+void audit_end_command(const char *);
|
|
ssh_audit_event_t audit_classify_auth(const char *);
|
|
|
|
#endif /* _SSH_AUDIT_H */
|
|
diff -up openssh-5.8p1/audit-linux.c.audit1 openssh-5.8p1/audit-linux.c
|
|
--- openssh-5.8p1/audit-linux.c.audit1 2011-01-17 11:15:30.000000000 +0100
|
|
+++ openssh-5.8p1/audit-linux.c 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -35,13 +35,20 @@
|
|
|
|
#include "log.h"
|
|
#include "audit.h"
|
|
+#include "key.h"
|
|
+#include "hostfile.h"
|
|
+#include "auth.h"
|
|
+#include "servconf.h"
|
|
#include "canohost.h"
|
|
|
|
+extern ServerOptions options;
|
|
+extern Authctxt *the_authctxt;
|
|
+extern u_int utmp_len;
|
|
const char* audit_username(void);
|
|
|
|
-int
|
|
-linux_audit_record_event(int uid, const char *username,
|
|
- const char *hostname, const char *ip, const char *ttyn, int success)
|
|
+static void
|
|
+linux_audit_user_logxxx(int uid, const char *username,
|
|
+ const char *hostname, const char *ip, const char *ttyn, int success, int event)
|
|
{
|
|
int audit_fd, rc, saved_errno;
|
|
|
|
@@ -49,11 +56,11 @@ linux_audit_record_event(int uid, const
|
|
if (audit_fd < 0) {
|
|
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
|
|
errno == EAFNOSUPPORT)
|
|
- return 1; /* No audit support in kernel */
|
|
+ return; /* No audit support in kernel */
|
|
else
|
|
- return 0; /* Must prevent login */
|
|
+ goto fatal_report; /* Must prevent login */
|
|
}
|
|
- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
|
|
+ rc = audit_log_acct_message(audit_fd, event,
|
|
NULL, "login", username ? username : "(unknown)",
|
|
username == NULL ? uid : -1, hostname, ip, ttyn, success);
|
|
saved_errno = errno;
|
|
@@ -65,35 +72,112 @@ linux_audit_record_event(int uid, const
|
|
if ((rc == -EPERM) && (geteuid() != 0))
|
|
rc = 0;
|
|
errno = saved_errno;
|
|
- return (rc >= 0);
|
|
+ if (rc < 0) {
|
|
+fatal_report:
|
|
+ fatal("linux_audit_write_entry failed: %s", strerror(errno));
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+linux_audit_user_auth(int uid, const char *username,
|
|
+ const char *hostname, const char *ip, const char *ttyn, int success, int event)
|
|
+{
|
|
+ int audit_fd, rc, saved_errno;
|
|
+ static const char *event_name[] = {
|
|
+ "maxtries exceeded",
|
|
+ "root denied",
|
|
+ "success",
|
|
+ "none",
|
|
+ "password",
|
|
+ "challenge-response",
|
|
+ "pubkey",
|
|
+ "hostbased",
|
|
+ "gssapi",
|
|
+ "invalid user",
|
|
+ "nologin",
|
|
+ "connection closed",
|
|
+ "connection abandoned",
|
|
+ "unknown"
|
|
+ };
|
|
+
|
|
+ audit_fd = audit_open();
|
|
+ if (audit_fd < 0) {
|
|
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
|
|
+ errno == EAFNOSUPPORT)
|
|
+ return; /* No audit support in kernel */
|
|
+ else
|
|
+ goto fatal_report; /* Must prevent login */
|
|
+ }
|
|
+
|
|
+ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN))
|
|
+ event = SSH_AUDIT_UNKNOWN;
|
|
+
|
|
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH,
|
|
+ NULL, event_name[event], username ? username : "(unknown)",
|
|
+ username == NULL ? uid : -1, hostname, ip, ttyn, success);
|
|
+ saved_errno = errno;
|
|
+ close(audit_fd);
|
|
+ /*
|
|
+ * Do not report error if the error is EPERM and sshd is run as non
|
|
+ * root user.
|
|
+ */
|
|
+ if ((rc == -EPERM) && (geteuid() != 0))
|
|
+ rc = 0;
|
|
+ errno = saved_errno;
|
|
+ if (rc < 0) {
|
|
+fatal_report:
|
|
+ fatal("linux_audit_write_entry failed: %s", strerror(errno));
|
|
+ }
|
|
}
|
|
|
|
+static int user_login_count = 0;
|
|
+
|
|
/* Below is the sshd audit API code */
|
|
|
|
void
|
|
audit_connection_from(const char *host, int port)
|
|
{
|
|
-}
|
|
/* not implemented */
|
|
+}
|
|
|
|
void
|
|
audit_run_command(const char *command)
|
|
{
|
|
- /* not implemented */
|
|
+ if (!user_login_count++)
|
|
+ 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_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);
|
|
+}
|
|
+
|
|
+void
|
|
+audit_end_command(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);
|
|
+ if (!--user_login_count)
|
|
+ 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_LOGOUT);
|
|
}
|
|
|
|
void
|
|
audit_session_open(struct logininfo *li)
|
|
{
|
|
- if (linux_audit_record_event(li->uid, NULL, li->hostname,
|
|
- NULL, li->line, 1) == 0)
|
|
- fatal("linux_audit_write_entry failed: %s", strerror(errno));
|
|
+ if (!user_login_count++)
|
|
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
|
|
+ NULL, li->line, 1, AUDIT_USER_LOGIN);
|
|
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
|
|
+ NULL, li->line, 1, AUDIT_USER_START);
|
|
}
|
|
|
|
void
|
|
audit_session_close(struct logininfo *li)
|
|
{
|
|
- /* not implemented */
|
|
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
|
|
+ NULL, li->line, 1, AUDIT_USER_END);
|
|
+ if (!--user_login_count)
|
|
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
|
|
+ NULL, li->line, 1, AUDIT_USER_LOGOUT);
|
|
}
|
|
|
|
void
|
|
@@ -101,21 +185,43 @@ audit_event(ssh_audit_event_t event)
|
|
{
|
|
switch(event) {
|
|
case SSH_AUTH_SUCCESS:
|
|
- case SSH_CONNECTION_CLOSE:
|
|
+ linux_audit_user_auth(-1, audit_username(), NULL,
|
|
+ get_remote_ipaddr(), "sshd", 1, event);
|
|
+ break;
|
|
+
|
|
case SSH_NOLOGIN:
|
|
- case SSH_LOGIN_EXCEED_MAXTRIES:
|
|
case SSH_LOGIN_ROOT_DENIED:
|
|
+ linux_audit_user_auth(-1, audit_username(), NULL,
|
|
+ get_remote_ipaddr(), "sshd", 0, event);
|
|
+ linux_audit_user_logxxx(-1, audit_username(), NULL,
|
|
+ get_remote_ipaddr(), "sshd", 0, AUDIT_USER_LOGIN);
|
|
break;
|
|
|
|
+ case SSH_LOGIN_EXCEED_MAXTRIES:
|
|
case SSH_AUTH_FAIL_NONE:
|
|
case SSH_AUTH_FAIL_PASSWD:
|
|
case SSH_AUTH_FAIL_KBDINT:
|
|
case SSH_AUTH_FAIL_PUBKEY:
|
|
case SSH_AUTH_FAIL_HOSTBASED:
|
|
case SSH_AUTH_FAIL_GSSAPI:
|
|
+ linux_audit_user_auth(-1, audit_username(), NULL,
|
|
+ get_remote_ipaddr(), "sshd", 0, event);
|
|
+ break;
|
|
+
|
|
+ case SSH_CONNECTION_CLOSE:
|
|
+ if (user_login_count) {
|
|
+ while (user_login_count--)
|
|
+ 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);
|
|
+ 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_LOGOUT);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case SSH_CONNECTION_ABANDON:
|
|
case SSH_INVALID_USER:
|
|
- linux_audit_record_event(-1, audit_username(), NULL,
|
|
- get_remote_ipaddr(), "sshd", 0);
|
|
+ linux_audit_user_logxxx(-1, audit_username(), NULL,
|
|
+ get_remote_ipaddr(), "sshd", 0, AUDIT_USER_LOGIN);
|
|
break;
|
|
|
|
default:
|
|
diff -up openssh-5.8p1/monitor.c.audit1 openssh-5.8p1/monitor.c
|
|
--- openssh-5.8p1/monitor.c.audit1 2010-09-10 03:23:34.000000000 +0200
|
|
+++ openssh-5.8p1/monitor.c 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -177,6 +177,7 @@ int mm_answer_gss_checkmic(int, Buffer *
|
|
#ifdef SSH_AUDIT_EVENTS
|
|
int mm_answer_audit_event(int, Buffer *);
|
|
int mm_answer_audit_command(int, Buffer *);
|
|
+int mm_answer_audit_end_command(int, Buffer *);
|
|
#endif
|
|
|
|
static Authctxt *authctxt;
|
|
@@ -261,6 +262,7 @@ struct mon_table mon_dispatch_postauth20
|
|
#ifdef SSH_AUDIT_EVENTS
|
|
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
|
|
{MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
|
|
+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
|
|
#endif
|
|
{0, 0, NULL}
|
|
};
|
|
@@ -303,6 +305,7 @@ struct mon_table mon_dispatch_postauth15
|
|
#ifdef SSH_AUDIT_EVENTS
|
|
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
|
|
{MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
|
|
+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
|
|
#endif
|
|
{0, 0, NULL}
|
|
};
|
|
@@ -1618,6 +1621,20 @@ mm_answer_audit_command(int socket, Buff
|
|
xfree(cmd);
|
|
return (0);
|
|
}
|
|
+
|
|
+int
|
|
+mm_answer_audit_end_command(int socket, Buffer *m)
|
|
+{
|
|
+ u_int len;
|
|
+ char *cmd;
|
|
+
|
|
+ debug3("%s entering", __func__);
|
|
+ cmd = buffer_get_string(m, &len);
|
|
+ /* sanity check command, if so how? */
|
|
+ audit_end_command(cmd);
|
|
+ xfree(cmd);
|
|
+ return (0);
|
|
+}
|
|
#endif /* SSH_AUDIT_EVENTS */
|
|
|
|
void
|
|
diff -up openssh-5.8p1/monitor.h.audit1 openssh-5.8p1/monitor.h
|
|
--- openssh-5.8p1/monitor.h.audit1 2008-11-05 06:20:46.000000000 +0100
|
|
+++ openssh-5.8p1/monitor.h 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -60,6 +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_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.audit1 openssh-5.8p1/monitor_wrap.c
|
|
--- openssh-5.8p1/monitor_wrap.c.audit1 2010-08-31 14:41:14.000000000 +0200
|
|
+++ openssh-5.8p1/monitor_wrap.c 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -1163,6 +1163,20 @@ mm_audit_run_command(const char *command
|
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
|
|
buffer_free(&m);
|
|
}
|
|
+
|
|
+void
|
|
+mm_audit_end_command(const char *command)
|
|
+{
|
|
+ Buffer m;
|
|
+
|
|
+ debug3("%s entering command %s", __func__, command);
|
|
+
|
|
+ buffer_init(&m);
|
|
+ buffer_put_cstring(&m, command);
|
|
+
|
|
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m);
|
|
+ buffer_free(&m);
|
|
+}
|
|
#endif /* SSH_AUDIT_EVENTS */
|
|
|
|
#ifdef GSSAPI
|
|
diff -up openssh-5.8p1/monitor_wrap.h.audit1 openssh-5.8p1/monitor_wrap.h
|
|
--- openssh-5.8p1/monitor_wrap.h.audit1 2009-03-05 14:58:22.000000000 +0100
|
|
+++ openssh-5.8p1/monitor_wrap.h 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -74,6 +74,7 @@ void mm_sshpam_free_ctx(void *);
|
|
#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 *);
|
|
#endif
|
|
|
|
struct Session;
|
|
diff -up openssh-5.8p1/session.c.audit1 openssh-5.8p1/session.c
|
|
--- openssh-5.8p1/session.c.audit1 2010-12-01 02:02:59.000000000 +0100
|
|
+++ openssh-5.8p1/session.c 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -809,14 +809,16 @@ do_exec(Session *s, const char *command)
|
|
}
|
|
|
|
#ifdef SSH_AUDIT_EVENTS
|
|
- if (command != NULL)
|
|
+ if (command != NULL) {
|
|
PRIVSEP(audit_run_command(command));
|
|
- else if (s->ttyfd == -1) {
|
|
+ s->command = xstrdup(command);
|
|
+ } 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);
|
|
}
|
|
#endif
|
|
if (s->ttyfd != -1)
|
|
@@ -2456,6 +2458,12 @@ session_close(Session *s)
|
|
debug("session_close: session %d pid %ld", s->self, (long)s->pid);
|
|
if (s->ttyfd != -1)
|
|
session_pty_cleanup(s);
|
|
+#ifdef SSH_AUDIT_EVENTS
|
|
+ if (s->command) {
|
|
+ PRIVSEP(audit_end_command(s->command));
|
|
+ xfree(s->command);
|
|
+ }
|
|
+#endif
|
|
if (s->term)
|
|
xfree(s->term);
|
|
if (s->display)
|
|
diff -up openssh-5.8p1/session.h.audit1 openssh-5.8p1/session.h
|
|
--- openssh-5.8p1/session.h.audit1 2008-05-19 07:34:50.000000000 +0200
|
|
+++ openssh-5.8p1/session.h 2011-02-24 13:49:49.000000000 +0100
|
|
@@ -60,6 +60,11 @@ struct Session {
|
|
char *name;
|
|
char *val;
|
|
} *env;
|
|
+
|
|
+ /* exec */
|
|
+#ifdef SSH_AUDIT_EVENTS
|
|
+ char *command;
|
|
+#endif
|
|
};
|
|
|
|
void do_authenticated(Authctxt *);
|
|
diff -up openssh-5.8p1/sshd.c.audit1 openssh-5.8p1/sshd.c
|
|
--- openssh-5.8p1/sshd.c.audit1 2011-02-24 13:50:29.000000000 +0100
|
|
+++ openssh-5.8p1/sshd.c 2011-02-24 13:50:47.000000000 +0100
|
|
@@ -2342,7 +2342,8 @@ cleanup_exit(int i)
|
|
do_cleanup(the_authctxt);
|
|
#ifdef SSH_AUDIT_EVENTS
|
|
/* done after do_cleanup so it can cancel the PAM auth 'thread' */
|
|
- if (!use_privsep || mm_is_monitor())
|
|
+ if ((the_authctxt == NULL || !the_authctxt->authenticated) &&
|
|
+ (!use_privsep || mm_is_monitor()))
|
|
audit_event(SSH_CONNECTION_ABANDON);
|
|
#endif
|
|
_exit(i);
|