Marcus Meissner
f722726301
- Update openssh-6.5p1-audit4-kex_results.patch to ensure that we don't pass a NULL string to buffer_put_cstring. This happens when you have "Ciphers chacha20-poly1305@openssh.com" directive. OBS-URL: https://build.opensuse.org/request/show/227423 OBS-URL: https://build.opensuse.org/package/show/network/openssh?expand=0&rev=74
779 lines
24 KiB
Diff
779 lines
24 KiB
Diff
# 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 <stdarg.h>
|
|
#include <string.h>
|
|
+#include <unistd.h>
|
|
|
|
#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 <jchadima@redhat.com>
|
|
+ */
|
|
+
|
|
+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 : "<implicit>",
|
|
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 ? cipher : "");
|
|
+ buffer_put_cstring(&m, mac ? mac : "");
|
|
+ buffer_put_cstring(&m, compress ? 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 <tcpd.h>
|
|
#include <syslog.h>
|
|
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();
|