# key exhange auditing # based on: # https://bugzilla.mindrot.org/show_bug.cgi?id=1402 # https://bugzilla.mindrot.org/attachment.cgi?id=2013 # (replaces: https://bugzilla.mindrot.org/attachment.cgi?id=1976) # by jchadima@redhat.com diff --git a/openssh-6.5p1/Makefile.in b/openssh-6.5p1/Makefile.in --- a/openssh-6.5p1/Makefile.in +++ b/openssh-6.5p1/Makefile.in @@ -71,17 +71,18 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \ kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ ssh-ed25519.o digest.o \ - sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o + sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \ + auditstub.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect1.o sshconnect2.o mux.o \ roaming_common.o roaming_client.o SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ audit.o audit-bsm.o audit-linux.o platform.o \ sshpty.o sshlogin.o servconf.o serverloop.o \ diff --git a/openssh-6.5p1/audit-bsm.c b/openssh-6.5p1/audit-bsm.c --- a/openssh-6.5p1/audit-bsm.c +++ b/openssh-6.5p1/audit-bsm.c @@ -468,9 +468,21 @@ audit_event(ssh_audit_event_t event) case SSH_AUTH_FAIL_KBDINT: bsm_audit_bad_login("interactive password entry"); break; default: debug("%s: unhandled event %d", __func__, event); } } + +void +audit_unsupported_body(int what) +{ + /* not implemented */ +} + +void +audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, uid_t uid) +{ + /* not implemented */ +} #endif /* BSM */ diff --git a/openssh-6.5p1/audit-linux.c b/openssh-6.5p1/audit-linux.c --- a/openssh-6.5p1/audit-linux.c +++ b/openssh-6.5p1/audit-linux.c @@ -35,16 +35,18 @@ #include "log.h" #include "audit.h" #include "key.h" #include "hostfile.h" #include "auth.h" #include "servconf.h" #include "canohost.h" +#include "packet.h" +#include "cipher.h" #define AUDIT_LOG_SIZE 128 extern ServerOptions options; extern Authctxt *the_authctxt; extern u_int utmp_len; const char* audit_username(void); @@ -264,9 +266,65 @@ audit_event(ssh_audit_event_t event) get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); break; default: debug("%s: unhandled event %d", __func__, event); } } +void +audit_unsupported_body(int what) +{ +#ifdef AUDIT_CRYPTO_SESSION + char buf[AUDIT_LOG_SIZE]; + const static char *name[] = { "cipher", "mac", "comp" }; + char *s; + int audit_fd; + + snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", + name[what], get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), + get_local_port()); + free(s); + audit_fd = audit_open(); + if (audit_fd < 0) + /* no problem, the next instruction will be fatal() */ + return; + audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, + buf, NULL, get_remote_ipaddr(), NULL, 0); + audit_close(audit_fd); +#endif +} + +void +audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, + uid_t uid) +{ +#ifdef AUDIT_CRYPTO_SESSION + char buf[AUDIT_LOG_SIZE]; + int audit_fd, audit_ok; + const static char *direction[] = { "from-server", "from-client", "both" }; + Cipher *cipher = cipher_by_name(enc); + char *s; + + snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", + direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, + (intmax_t)pid, (intmax_t)uid, + get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), get_local_port()); + free(s); + audit_fd = audit_open(); + if (audit_fd < 0) { + if (errno == EINVAL || errno == EPROTONOSUPPORT || + errno == EAFNOSUPPORT) + return; /* No audit support in kernel */ + else + fatal("cannot open audit"); /* Must prevent login */ + } + audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, + buf, NULL, get_remote_ipaddr(), NULL, 1); + audit_close(audit_fd); + /* do not abort if the error is EPERM and sshd is run as non root user */ + if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) + fatal("cannot write into audit"); /* Must prevent login */ +#endif +} + #endif /* USE_LINUX_AUDIT */ diff --git a/openssh-6.5p1/audit.c b/openssh-6.5p1/audit.c --- a/openssh-6.5p1/audit.c +++ b/openssh-6.5p1/audit.c @@ -23,24 +23,27 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include +#include #ifdef SSH_AUDIT_EVENTS #include "audit.h" #include "log.h" #include "key.h" #include "hostfile.h" #include "auth.h" +#include "ssh-gss.h" +#include "monitor_wrap.h" #include "xmalloc.h" /* * Care must be taken when using this since it WILL NOT be initialized when * audit_connection_from() is called and MAY NOT be initialized when * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using. */ extern Authctxt *the_authctxt; @@ -123,16 +126,28 @@ audit_key(int host_user, int *rv, const crypto_name = "ssh-rsa1"; else crypto_name = key_ssh_name(key); if (audit_keyusage(host_user, crypto_name, key_size(key), fp, *rv) == 0) *rv = 0; free(fp); } +void +audit_unsupported(int what) +{ + PRIVSEP(audit_unsupported_body(what)); +} + +void +audit_kex(int ctos, char *enc, char *mac, char *comp) +{ + PRIVSEP(audit_kex_body(ctos, enc, mac, comp, getpid(), getuid())); +} + # ifndef CUSTOM_SSH_AUDIT_EVENTS /* * Null implementations of audit functions. * These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled. */ /* * Called after a connection has been accepted but before any authentication @@ -233,10 +248,31 @@ audit_end_command(int handle, const char */ int audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) { debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s, result %d", host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits, fp, rv); } + +/* + * This will be called when the protocol negotiation fails. + */ +void +audit_unsupported_body(int what) +{ + debug("audit unsupported protocol euid %d type %d", geteuid(), what); +} + +/* + * This will be called on succesfull protocol negotiation. + */ +void +audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, + uid_t uid) +{ + debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s from pid %ld uid %u", + (unsigned)geteuid(), ctos, enc, mac, compress, (long)pid, + (unsigned)uid); +} # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ #endif /* SSH_AUDIT_EVENTS */ diff --git a/openssh-6.5p1/audit.h b/openssh-6.5p1/audit.h --- a/openssh-6.5p1/audit.h +++ b/openssh-6.5p1/audit.h @@ -53,10 +53,14 @@ 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 *); int audit_run_command(const char *); void audit_end_command(int, const char *); ssh_audit_event_t audit_classify_auth(const char *); int audit_keyusage(int, const char *, unsigned, char *, int); void audit_key(int, int *, const Key *); +void audit_unsupported(int); +void audit_kex(int, char *, char *, char *); +void audit_unsupported_body(int); +void audit_kex_body(int, char *, char *, char *, pid_t, uid_t); #endif /* _SSH_AUDIT_H */ diff --git a/openssh-6.5p1/auditstub.c b/openssh-6.5p1/auditstub.c new file mode 100644 --- /dev/null +++ b/openssh-6.5p1/auditstub.c @@ -0,0 +1,39 @@ +/* $Id: auditstub.c,v 1.1 jfch Exp $ */ + +/* + * Copyright 2010 Red Hat, Inc. All rights reserved. + * Use is subject to license terms. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Red Hat author: Jan F. Chadima + */ + +void +audit_unsupported(int n) +{ +} + +void +audit_kex(int ctos, char *enc, char *mac, char *comp) +{ +} + diff --git a/openssh-6.5p1/cipher.c b/openssh-6.5p1/cipher.c --- a/openssh-6.5p1/cipher.c +++ b/openssh-6.5p1/cipher.c @@ -52,31 +52,17 @@ /* compatibility with old or broken OpenSSL versions */ #include "openbsd-compat/openssl-compat.h" extern const EVP_CIPHER *evp_ssh1_bf(void); extern const EVP_CIPHER *evp_ssh1_3des(void); extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); -struct Cipher { - char *name; - int number; /* for ssh1 only */ - u_int block_size; - u_int key_len; - u_int iv_len; /* defaults to block_size */ - u_int auth_len; - u_int discard_len; - u_int flags; -#define CFLAG_CBC (1<<0) -#define CFLAG_CHACHAPOLY (1<<1) - const EVP_CIPHER *(*evptype)(void); -}; - -static const struct Cipher ciphers[] = { +struct Cipher ciphers[] = { { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, diff --git a/openssh-6.5p1/cipher.h b/openssh-6.5p1/cipher.h --- a/openssh-6.5p1/cipher.h +++ b/openssh-6.5p1/cipher.h @@ -58,17 +58,30 @@ #define SSH_CIPHER_MAX 31 #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 typedef struct Cipher Cipher; typedef struct CipherContext CipherContext; -struct Cipher; +struct Cipher { + char *name; + int number; /* for ssh1 only */ + u_int block_size; + u_int key_len; + u_int iv_len; /* defaults to block_size */ + u_int auth_len; + u_int discard_len; + u_int flags; +#define CFLAG_CBC (1<<0) +#define CFLAG_CHACHAPOLY (1<<1) + const EVP_CIPHER *(*evptype)(void); +}; + struct CipherContext { int plaintext; int encrypt; EVP_CIPHER_CTX evp; struct chachapoly_ctx cp_ctx; /* XXX union with evp? */ const Cipher *cipher; }; diff --git a/openssh-6.5p1/kex.c b/openssh-6.5p1/kex.c --- a/openssh-6.5p1/kex.c +++ b/openssh-6.5p1/kex.c @@ -45,16 +45,17 @@ #include "kex.h" #include "log.h" #include "mac.h" #include "match.h" #include "dispatch.h" #include "monitor.h" #include "roaming.h" #include "digest.h" +#include "audit.h" #if OPENSSL_VERSION_NUMBER >= 0x00907000L # if defined(HAVE_EVP_SHA256) # define evp_ssh_sha256 EVP_sha256 # else extern const EVP_MD *evp_ssh_sha256(void); # endif #endif @@ -346,53 +347,65 @@ kex_kexinit_finish(Kex *kex) fatal("Unsupported key exchange %d", kex->kex_type); } } static void choose_enc(Enc *enc, char *client, char *server) { char *name = match_list(client, server, NULL); - if (name == NULL) + if (name == NULL) { +#ifdef SSH_AUDIT_EVENTS + audit_unsupported(0); +#endif fatal("no matching cipher found: client %s server %s", client, server); + } if ((enc->cipher = cipher_by_name(name)) == NULL) fatal("matching cipher is not supported: %s", name); enc->name = name; enc->enabled = 0; enc->iv = NULL; enc->iv_len = cipher_ivlen(enc->cipher); enc->key = NULL; enc->key_len = cipher_keylen(enc->cipher); enc->block_size = cipher_blocksize(enc->cipher); } static void choose_mac(Mac *mac, char *client, char *server) { char *name = match_list(client, server, NULL); - if (name == NULL) + if (name == NULL) { +#ifdef SSH_AUDIT_EVENTS + audit_unsupported(1); +#endif fatal("no matching mac found: client %s server %s", client, server); + } if (mac_setup(mac, name) < 0) fatal("unsupported mac %s", name); /* truncate the key */ if (datafellows & SSH_BUG_HMAC) mac->key_len = 16; mac->name = name; mac->key = NULL; mac->enabled = 0; } static void choose_comp(Comp *comp, char *client, char *server) { char *name = match_list(client, server, NULL); - if (name == NULL) + if (name == NULL) { +#ifdef SSH_AUDIT_EVENTS + audit_unsupported(2); +#endif fatal("no matching comp found: client %s server %s", client, server); + } if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; } else if (strcmp(name, "zlib") == 0) { comp->type = COMP_ZLIB; } else if (strcmp(name, "none") == 0) { comp->type = COMP_NONE; } else { fatal("unsupported comp %s", name); @@ -497,16 +510,19 @@ kex_choose_conf(Kex *kex) if (authlen == 0) choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); debug("kex: %s %s %s %s", ctos ? "client->server" : "server->client", newkeys->enc.name, authlen == 0 ? newkeys->mac.name : "", newkeys->comp.name); +#ifdef SSH_AUDIT_EVENTS + audit_kex(ctos, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name); +#endif } choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); need = dh_need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; need = MAX(need, newkeys->enc.key_len); diff --git a/openssh-6.5p1/monitor.c b/openssh-6.5p1/monitor.c --- a/openssh-6.5p1/monitor.c +++ b/openssh-6.5p1/monitor.c @@ -93,16 +93,17 @@ #include "monitor_wrap.h" #include "monitor_fdpass.h" #include "misc.h" #include "compat.h" #include "ssh2.h" #include "jpake.h" #include "roaming.h" #include "authfd.h" +#include "audit.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; #endif /* Imports */ extern ServerOptions options; extern u_int utmp_len; @@ -182,16 +183,18 @@ int mm_answer_gss_accept_ctx(int, Buffer int mm_answer_gss_userok(int, Buffer *); int mm_answer_gss_checkmic(int, Buffer *); #endif #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 *); +int mm_answer_audit_unsupported_body(int, Buffer *); +int mm_answer_audit_kex_body(int, Buffer *); #endif static int monitor_read_log(struct monitor *); static Authctxt *authctxt; static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ /* local state for key verify */ @@ -233,16 +236,18 @@ struct mon_table mon_dispatch_proto20[] {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, {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 SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, #endif #ifdef SKEY {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, @@ -270,16 +275,18 @@ struct mon_table mon_dispatch_postauth20 {MONITOR_REQ_SIGN, 0, mm_answer_sign}, {MONITOR_REQ_PTY, 0, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, #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}, + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, #endif {0, 0, NULL} }; struct mon_table mon_dispatch_proto15[] = { {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, @@ -301,28 +308,32 @@ struct mon_table mon_dispatch_proto15[] {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, {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 SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, #endif {0, 0, NULL} }; 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 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}, + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, #endif {0, 0, NULL} }; struct mon_table *mon_dispatch; /* Specifies if a certain message is allowed at the moment */ @@ -2411,8 +2422,52 @@ mm_answer_jpake_check_confirm(int sock, monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1); auth_method = "jpake-01@openssh.com"; return authenticated; } #endif /* JPAKE */ + +#ifdef SSH_AUDIT_EVENTS +int +mm_answer_audit_unsupported_body(int sock, Buffer *m) +{ + int what; + + what = buffer_get_int(m); + + audit_unsupported_body(what); + + buffer_clear(m); + + mm_request_send(sock, MONITOR_ANS_AUDIT_UNSUPPORTED, m); + return 0; +} + +int +mm_answer_audit_kex_body(int sock, Buffer *m) +{ + int ctos, len; + char *cipher, *mac, *compress; + pid_t pid; + uid_t uid; + + ctos = buffer_get_int(m); + cipher = buffer_get_string(m, &len); + mac = buffer_get_string(m, &len); + compress = buffer_get_string(m, &len); + pid = buffer_get_int64(m); + uid = buffer_get_int64(m); + + audit_kex_body(ctos, cipher, mac, compress, pid, uid); + + free(cipher); + free(mac); + free(compress); + buffer_clear(m); + + mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m); + return 0; +} + +#endif /* SSH_AUDIT_EVENTS */ diff --git a/openssh-6.5p1/monitor.h b/openssh-6.5p1/monitor.h --- a/openssh-6.5p1/monitor.h +++ b/openssh-6.5p1/monitor.h @@ -65,16 +65,18 @@ enum monitor_reqtype { MONITOR_REQ_PAM_START = 100, MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105, MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, MONITOR_ANS_AUDIT_COMMAND = 114, MONITOR_REQ_AUDIT_END_COMMAND = 115, + MONITOR_REQ_AUDIT_UNSUPPORTED = 116, MONITOR_ANS_AUDIT_UNSUPPORTED = 117, + MONITOR_REQ_AUDIT_KEX = 118, MONITOR_ANS_AUDIT_KEX = 119, }; struct mm_master; struct monitor { int m_recvfd; int m_sendfd; int m_log_recvfd; diff --git a/openssh-6.5p1/monitor_wrap.c b/openssh-6.5p1/monitor_wrap.c --- a/openssh-6.5p1/monitor_wrap.c +++ b/openssh-6.5p1/monitor_wrap.c @@ -1483,8 +1483,46 @@ mm_jpake_check_confirm(const BIGNUM *k, success = buffer_get_int(&m); buffer_free(&m); debug3("%s: success = %d", __func__, success); return success; } #endif /* JPAKE */ + +#ifdef SSH_AUDIT_EVENTS +void +mm_audit_unsupported_body(int what) +{ + Buffer m; + + buffer_init(&m); + buffer_put_int(&m, what); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED, + &m); + + buffer_free(&m); +} + +void +mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress, pid_t pid, + uid_t uid) +{ + Buffer m; + + buffer_init(&m); + buffer_put_int(&m, ctos); + buffer_put_cstring(&m, cipher); + buffer_put_cstring(&m, mac); + buffer_put_cstring(&m, compress); + buffer_put_int64(&m, pid); + buffer_put_int64(&m, uid); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX, + &m); + + buffer_free(&m); +} +#endif /* SSH_AUDIT_EVENTS */ diff --git a/openssh-6.5p1/monitor_wrap.h b/openssh-6.5p1/monitor_wrap.h --- a/openssh-6.5p1/monitor_wrap.h +++ b/openssh-6.5p1/monitor_wrap.h @@ -72,16 +72,18 @@ int mm_sshpam_respond(void *, u_int, cha void mm_sshpam_free_ctx(void *); #endif #ifdef SSH_AUDIT_EVENTS #include "audit.h" void mm_audit_event(ssh_audit_event_t); int mm_audit_run_command(const char *); void mm_audit_end_command(int, const char *); +void mm_audit_unsupported_body(int); +void mm_audit_kex_body(int, char *, char *, char *, pid_t, uid_t); #endif struct Session; void mm_terminate(void); int mm_pty_allocate(int *, int *, char *, size_t); void mm_session_pty_cleanup2(struct Session *); /* SSHv1 interfaces */ diff --git a/openssh-6.5p1/sshd.c b/openssh-6.5p1/sshd.c --- a/openssh-6.5p1/sshd.c +++ b/openssh-6.5p1/sshd.c @@ -114,16 +114,17 @@ #include "session.h" #include "monitor_mm.h" #include "monitor.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "roaming.h" +#include "audit.h" #include "ssh-sandbox.h" #include "version.h" #ifdef LIBWRAP #include #include int allow_severity; int deny_severity; @@ -2312,16 +2313,20 @@ do_ssh1_kex(void) packet_disconnect("Warning: client selects unsupported cipher."); /* Get check bytes from the packet. These must match those we sent earlier with the public key packet. */ for (i = 0; i < 8; i++) if (cookie[i] != packet_get_char()) packet_disconnect("IP Spoofing check bytes do not match."); +#ifdef SSH_AUDIT_EVENTS + audit_kex(2, cipher_name(cipher_type), "crc", "none"); +#endif + debug("Encryption type: %.200s", cipher_name(cipher_type)); /* Get the encrypted integer. */ if ((session_key_int = BN_new()) == NULL) fatal("do_ssh1_kex: BN_new failed"); packet_get_bignum(session_key_int); protocol_flags = packet_get_int();