]> andersk Git - openssh.git/commitdiff
- (dtucker) [Makefile.in auth.c auth.h auth1.c auth2.c loginrec.c monitor.c
authordtucker <dtucker>
Wed, 2 Feb 2005 13:20:53 +0000 (13:20 +0000)
committerdtucker <dtucker>
Wed, 2 Feb 2005 13:20:53 +0000 (13:20 +0000)
   monitor.h monitor_wrap.c monitor_wrap.h session.c sshd.c] Bug #125:
   (first stage) Add audit instrumentation to sshd, currently disabled by
   default.  with suggestions from and djm@

13 files changed:
ChangeLog
Makefile.in
auth.c
auth.h
auth1.c
auth2.c
loginrec.c
monitor.c
monitor.h
monitor_wrap.c
monitor_wrap.h
session.c
sshd.c

index 1f676b5cfec41f297a295030c7ea8a6474323dd4..908b4493a26af87a7cb6d7240d6ed6fc37dd19f4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
    attempts (currently only for password, kbdint and C/R, only on Linux and
    HP-UX), based on code from login.c from util-linux. With ashok_kovai at
    hotmail.com, ok djm@
+ - (dtucker) [Makefile.in auth.c auth.h auth1.c auth2.c loginrec.c monitor.c
+   monitor.h monitor_wrap.c monitor_wrap.h session.c sshd.c] Bug #125:
+   (first stage) Add audit instrumentation to sshd, currently disabled by
+   default.  with suggestions from and djm@
 
 20050201
  - (dtucker) [log.c] Bug #973: force log_init() to open syslog, since on some
index d0f27afbe41be69a2320c68967e119e9bfd62ae1..b2e333363d9d99bbb8dea174013a7871b50d7404 100644 (file)
@@ -85,7 +85,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
        monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
        auth-krb5.o \
        auth2-gss.o gss-serv.o gss-serv-krb5.o \
-       loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o
+       loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o audit.o
 
 MANPAGES       = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
 MANPAGES_IN    = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
diff --git a/auth.c b/auth.c
index b6c00c12b25dc7551cc50a88d5b653b62610d9a2..bbf3a54a4a1f32e5f3e5ad18d61953cf4b07f424 100644 (file)
--- a/auth.c
+++ b/auth.c
@@ -51,6 +51,7 @@ RCSID("$OpenBSD: auth.c,v 1.57 2005/01/22 08:17:59 dtucker Exp $");
 #include "bufaux.h"
 #include "packet.h"
 #include "loginrec.h"
+#include "monitor_wrap.h"
 
 /* import */
 extern ServerOptions options;
@@ -251,6 +252,44 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
                record_failed_login(authctxt->user,
                    get_canonical_hostname(options.use_dns), "ssh");
 #endif
+#ifdef AUDIT_EVENTS
+       if (authenticated == 0 && !authctxt->postponed) {
+               ssh_audit_event_t event;
+
+               debug3("audit failed auth attempt, method %s euid %d",
+                   method, (int)geteuid());
+               /*
+                * Because the auth loop is used in both monitor and slave,
+                * we must be careful to send each event only once and with
+                * enough privs to write the event.
+                */
+               event = audit_classify_auth(method);
+               switch(event) {
+               case AUTH_FAIL_NONE:
+               case AUTH_FAIL_PASSWD:
+               case AUTH_FAIL_KBDINT:
+                       if (geteuid() == 0)
+                               audit_event(event);
+                       break;
+               case AUTH_FAIL_PUBKEY:
+               case AUTH_FAIL_HOSTBASED:
+               case AUTH_FAIL_GSSAPI:
+                       /*
+                        * This is required to handle the case where privsep
+                        * is enabled but it's root logging in, since
+                        * use_privsep won't be cleared until after a
+                        * successful login.
+                        */
+                       if (geteuid() == 0)
+                               audit_event(event);
+                       else
+                               PRIVSEP(audit_event(event));
+                       break;
+               default:
+                       error("unknown authentication audit event %d", event);
+               }
+       }
+#endif
 }
 
 /*
@@ -476,6 +515,9 @@ getpwnamallow(const char *user)
                record_failed_login(user,
                    get_canonical_hostname(options.use_dns), "ssh");
 #endif
+#ifdef AUDIT_EVENTS
+               audit_event(INVALID_USER);
+#endif /* AUDIT_EVENTS */
                return (NULL);
        }
        if (!allowed_user(pw))
diff --git a/auth.h b/auth.h
index 6c0089dc73fee65472f24e328294b335bb774b7a..8d1f934033ab2c9ca1eb966274502bb871848ca3 100644 (file)
--- a/auth.h
+++ b/auth.h
@@ -130,6 +130,7 @@ int auth_shadow_pwexpired(Authctxt *);
 #endif
 
 #include "auth-pam.h"
+#include "audit.h"
 void remove_kbdint_device(const char *);
 
 void disable_forwarding(void);
diff --git a/auth1.c b/auth1.c
index 2a9d18b9a23982b5fefc5082eefddd3ffb45d5a2..aeb5d8cb95e891ece76e329a0c8876a2fa2ede7d 100644 (file)
--- a/auth1.c
+++ b/auth1.c
@@ -247,8 +247,12 @@ do_authloop(Authctxt *authctxt)
 #else
                /* Special handling for root */
                if (authenticated && authctxt->pw->pw_uid == 0 &&
-                   !auth_root_allowed(get_authname(type)))
+                   !auth_root_allowed(get_authname(type))) {
                        authenticated = 0;
+# ifdef AUDIT_EVENTS
+                       PRIVSEP(audit_event(LOGIN_ROOT_DENIED));
+# endif
+               }
 #endif
 
 #ifdef USE_PAM
@@ -283,8 +287,12 @@ do_authloop(Authctxt *authctxt)
                if (authenticated)
                        return;
 
-               if (authctxt->failures++ > options.max_authtries)
+               if (authctxt->failures++ > options.max_authtries) {
+#ifdef AUDIT_EVENTS
+                       PRIVSEP(audit_event(LOGIN_EXCEED_MAXTRIES));
+#endif
                        packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+               }
 
                packet_start(SSH_SMSG_FAILURE);
                packet_send();
diff --git a/auth2.c b/auth2.c
index 60e261f7f452caa55fe3a2086ff91e5337a92607..2727e0ff56290643dd7ca39502f825bae19f2706 100644 (file)
--- a/auth2.c
+++ b/auth2.c
@@ -166,6 +166,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
 #ifdef USE_PAM
                        if (options.use_pam)
                                PRIVSEP(start_pam(authctxt));
+#endif
+#ifdef AUDIT_EVENTS
+                       PRIVSEP(audit_event(INVALID_USER));
 #endif
                }
                setproctitle("%s%s", authctxt->valid ? user : "unknown",
@@ -214,8 +217,12 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
 
        /* Special handling for root */
        if (authenticated && authctxt->pw->pw_uid == 0 &&
-           !auth_root_allowed(method))
+           !auth_root_allowed(method)) {
                authenticated = 0;
+#ifdef AUDIT_EVENTS
+               PRIVSEP(audit_event(LOGIN_ROOT_DENIED));
+#endif
+       }
 
 #ifdef USE_PAM
        if (options.use_pam && authenticated) {
@@ -255,8 +262,12 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
                /* now we can break out */
                authctxt->success = 1;
        } else {
-               if (authctxt->failures++ > options.max_authtries)
+               if (authctxt->failures++ > options.max_authtries) {
+#ifdef AUDIT_EVENTS
+                       PRIVSEP(audit_event(LOGIN_EXCEED_MAXTRIES));
+#endif
                        packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+               }
                methods = authmethods_get();
                packet_start(SSH2_MSG_USERAUTH_FAILURE);
                packet_put_cstring(methods);
index 491b7afb6f0f36f29a12d79f34779edc11bc52ee..f87492a6bbbb670a4e0e1bc3c073de98be1d4e23 100644 (file)
 #include "atomicio.h"
 #include "packet.h"
 #include "canohost.h"
+#include "auth.h"
 
 #ifdef HAVE_UTIL_H
 # include <util.h>
@@ -442,6 +443,12 @@ login_write(struct logininfo *li)
        if (li->type == LTYPE_LOGIN && 
           !sys_auth_record_login(li->username,li->hostname,li->line))
                logit("Writing login record failed for %s", li->username);
+#endif
+#ifdef AUDIT_EVENTS
+       if (li->type == LTYPE_LOGIN)
+               audit_session_open(li->line);
+       else if (li->type == LTYPE_LOGOUT)
+               audit_session_close(li->line);
 #endif
        return (0);
 }
index 00d4a785f63b1b8b3ce39f9cdd82928c6d70b57e..ce7784aa153cc6606cc51f71760bb15f45762a27 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -143,6 +143,11 @@ int mm_answer_gss_userok(int, Buffer *);
 int mm_answer_gss_checkmic(int, Buffer *);
 #endif
 
+#ifdef AUDIT_EVENTS
+int mm_answer_audit_event(int, Buffer *);
+int mm_answer_audit_command(int, Buffer *);
+#endif
+
 static Authctxt *authctxt;
 static BIGNUM *ssh1_challenge = NULL;  /* used for ssh1 rsa auth */
 
@@ -186,6 +191,9 @@ struct mon_table mon_dispatch_proto20[] = {
     {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
     {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
 #endif
+#ifdef AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, 0, mm_answer_audit_event},
+#endif
 #ifdef BSD_AUTH
     {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
     {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
@@ -211,6 +219,10 @@ struct mon_table mon_dispatch_postauth20[] = {
     {MONITOR_REQ_PTY, 0, mm_answer_pty},
     {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
     {MONITOR_REQ_TERM, 0, mm_answer_term},
+#ifdef AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
+#endif
     {0, 0, NULL}
 };
 
@@ -238,6 +250,9 @@ struct mon_table mon_dispatch_proto15[] = {
     {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
     {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
     {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
+#endif
+#ifdef AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, 0, mm_answer_audit_event},
 #endif
     {0, 0, NULL}
 };
@@ -246,6 +261,10 @@ struct mon_table mon_dispatch_postauth15[] = {
     {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
     {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
     {MONITOR_REQ_TERM, 0, mm_answer_term},
+#ifdef AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
+#endif
     {0, 0, NULL}
 };
 
@@ -609,6 +628,9 @@ mm_answer_pwnamallow(int sock, Buffer *m)
        if (options.use_pam)
                monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
 #endif
+#ifdef AUDIT_EVENTS
+       monitor_permit(mon_dispatch, MONITOR_REQ_AUDIT_EVENT, 1);
+#endif
 
        return (0);
 }
@@ -1491,6 +1513,49 @@ mm_answer_term(int sock, Buffer *req)
        exit(res);
 }
 
+#ifdef AUDIT_EVENTS
+/* Report that an audit event occurred */
+int
+mm_answer_audit_event(int socket, Buffer *m)
+{
+       ssh_audit_event_t event;
+
+       debug3("%s entering", __func__);
+
+       event = buffer_get_int(m);
+       buffer_free(m);
+       switch(event) {
+       case AUTH_FAIL_PUBKEY:
+       case AUTH_FAIL_HOSTBASED:
+       case AUTH_FAIL_GSSAPI:
+       case LOGIN_EXCEED_MAXTRIES:
+       case LOGIN_ROOT_DENIED:
+       case CONNECTION_CLOSE:
+               audit_event(event);
+               break;
+       default:
+               fatal("Audit event type %d not permitted", event);
+       }
+
+       return (0);
+}
+
+int
+mm_answer_audit_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_run_command(cmd);
+       xfree(cmd);
+       buffer_free(m);
+       return (0);
+}
+#endif /* AUDIT_EVENTS */
+
 void
 monitor_apply_keystate(struct monitor *pmonitor)
 {
index 621a4ad1816240319c3809258b3b91dc75784095..13ce3e1ca3e593d70aa9c1dc5e76ed6ac98652b1 100644 (file)
--- a/monitor.h
+++ b/monitor.h
@@ -59,6 +59,7 @@ enum monitor_reqtype {
        MONITOR_REQ_PAM_QUERY, MONITOR_ANS_PAM_QUERY,
        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_TERM
 };
 
index 23857639b869798d7a17756b75c465417670ad27..983b24072196e3aa7e00b7e0a5c7454925f88f63 100644 (file)
@@ -1103,6 +1103,36 @@ mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
        return (success);
 }
 
+#ifdef AUDIT_EVENTS
+void
+mm_audit_event(ssh_audit_event_t event)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_int(&m, event);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
+       buffer_free(&m);
+}
+
+void
+mm_audit_run_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_COMMAND, &m);
+       buffer_free(&m);
+}
+#endif /* AUDIT_EVENTS */
+
 #ifdef GSSAPI
 OM_uint32
 mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
index e5cf5718c492308d22d1f9e21fbc898c8555a9c4..7ed241aa88a2503ae358b703d9ea9cc0413b2e32 100644 (file)
@@ -74,6 +74,12 @@ int mm_sshpam_respond(void *, u_int, char **);
 void mm_sshpam_free_ctx(void *);
 #endif
 
+#ifdef AUDIT_EVENTS
+#include "audit.h"
+void mm_audit_event(ssh_audit_event_t);
+void mm_audit_run_command(const char *);
+#endif
+
 struct Session;
 void mm_terminate(void);
 int mm_pty_allocate(int *, int *, char *, int);
index 4d7ac9de754519777d15ca9f55ef9ca626ebf73c..b645144c5c1049af1991f357e956d15322d89b6d 100644 (file)
--- a/session.c
+++ b/session.c
@@ -665,6 +665,18 @@ do_exec(Session *s, const char *command)
                debug("Forced command '%.900s'", command);
        }
 
+#ifdef AUDIT_EVENTS
+       if (command != NULL)
+               PRIVSEP(audit_run_command(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));
+       }
+#endif
+
 #ifdef GSSAPI
        if (options.gss_authentication) {
                temporarily_use_uid(s->pw);
@@ -2321,6 +2333,10 @@ do_cleanup(Authctxt *authctxt)
        }
 #endif
 
+#ifdef AUDIT_EVENTS
+       PRIVSEP(audit_event(CONNECTION_CLOSE));
+#endif
+
        /* remove agent socket */
        auth_sock_cleanup_proc(authctxt->pw);
 
diff --git a/sshd.c b/sshd.c
index 23d6962c052208fe65fc260e9654bda8dc6ae816..e61870ea584010c6e4fccdc39b7109065bebd5d6 100644 (file)
--- a/sshd.c
+++ b/sshd.c
@@ -1628,6 +1628,9 @@ main(int ac, char **av)
        remote_port = get_remote_port();
        remote_ip = get_remote_ipaddr();
 
+#ifdef AUDIT_EVENTS
+       audit_connection_from(remote_ip, remote_port);
+#endif
 #ifdef LIBWRAP
        /* Check whether logins are denied from this host. */
        if (packet_connection_is_on_socket()) {
@@ -1697,6 +1700,10 @@ main(int ac, char **av)
        }
 
  authenticated:
+#ifdef AUDIT_EVENTS
+       audit_event(AUTH_SUCCESS);
+#endif
+
        /*
         * In privilege separation, we fork another child and prepare
         * file descriptor passing.
@@ -2010,5 +2017,10 @@ cleanup_exit(int i)
 {
        if (the_authctxt)
                do_cleanup(the_authctxt);
+#ifdef AUDIT_EVENTS
+       /* done after do_cleanup so it can cancel the PAM auth 'thread' */
+       if (!use_privsep || mm_is_monitor())
+               audit_event(CONNECTION_ABANDON);
+#endif
        _exit(i);
 }
This page took 0.586107 seconds and 5 git commands to generate.