]> git.ipfire.org Git - ipfire-3.x.git/blame - openssh/patches/openssh-6.7p1-audit.patch
python3-systemd: New package.
[ipfire-3.x.git] / openssh / patches / openssh-6.7p1-audit.patch
CommitLineData
17d728c8
SS
1diff -up openssh-6.8p1/Makefile.in.audit openssh-6.8p1/Makefile.in
2--- openssh-6.8p1/Makefile.in.audit 2015-03-20 13:41:15.065883826 +0100
3+++ openssh-6.8p1/Makefile.in 2015-03-20 13:41:15.100883769 +0100
4@@ -98,7 +98,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
5 sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \
6 kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
7 kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
8- kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o
9+ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o auditstub.o
10
11 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
12 sshconnect.o sshconnect1.o sshconnect2.o mux.o \
13diff -up openssh-6.8p1/audit-bsm.c.audit openssh-6.8p1/audit-bsm.c
14--- openssh-6.8p1/audit-bsm.c.audit 2015-03-17 06:49:20.000000000 +0100
15+++ openssh-6.8p1/audit-bsm.c 2015-03-20 13:41:15.092883782 +0100
16@@ -375,10 +375,23 @@ audit_connection_from(const char *host,
17 #endif
18 }
19
20-void
21+int
22 audit_run_command(const char *command)
23 {
24 /* not implemented */
25+ return 0;
26+}
27+
28+void
29+audit_end_command(int handle, const char *command)
30+{
31+ /* not implemented */
32+}
33+
34+void
35+audit_count_session_open(void)
36+{
37+ /* not necessary */
38 }
39
40 void
41@@ -393,6 +406,12 @@ audit_session_close(struct logininfo *li)
42 /* not implemented */
43 }
44
45+int
46+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv)
47+{
48+ /* not implemented */
49+}
50+
51 void
52 audit_event(ssh_audit_event_t event)
53 {
54@@ -454,4 +473,40 @@ audit_event(ssh_audit_event_t event)
55 debug("%s: unhandled event %d", __func__, event);
56 }
57 }
58+
59+void
60+audit_unsupported_body(int what)
61+{
62+ /* not implemented */
63+}
64+
65+void
66+audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, uid_t uid)
67+{
68+ /* not implemented */
69+}
70+
71+void
72+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
73+{
74+ /* not implemented */
75+}
76+
77+void
78+audit_destroy_sensitive_data(const char *fp)
79+{
80+ /* not implemented */
81+}
82+
83+void
84+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
85+{
86+ /* not implemented */
87+}
88+
89+void
90+audit_generate_ephemeral_server_key(const char *fp)
91+{
92+ /* not implemented */
93+}
94 #endif /* BSM */
95diff -up openssh-6.8p1/audit-linux.c.audit openssh-6.8p1/audit-linux.c
96--- openssh-6.8p1/audit-linux.c.audit 2015-03-17 06:49:20.000000000 +0100
97+++ openssh-6.8p1/audit-linux.c 2015-03-20 13:41:15.093883780 +0100
98@@ -35,13 +35,25 @@
99
100 #include "log.h"
101 #include "audit.h"
102+#include "key.h"
103+#include "hostfile.h"
104+#include "auth.h"
105+#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */
106+#include "servconf.h"
107 #include "canohost.h"
108+#include "packet.h"
109+#include "cipher.h"
110
111+#define AUDIT_LOG_SIZE 256
112+
113+extern ServerOptions options;
114+extern Authctxt *the_authctxt;
115+extern u_int utmp_len;
116 const char* audit_username(void);
117
118-int
119-linux_audit_record_event(int uid, const char *username,
120- const char *hostname, const char *ip, const char *ttyn, int success)
121+static void
122+linux_audit_user_logxxx(int uid, const char *username,
123+ const char *hostname, const char *ip, const char *ttyn, int success, int event)
124 {
125 int audit_fd, rc, saved_errno;
126
127@@ -49,11 +61,11 @@ linux_audit_record_event(int uid, const char *username,
128 if (audit_fd < 0) {
129 if (errno == EINVAL || errno == EPROTONOSUPPORT ||
130 errno == EAFNOSUPPORT)
131- return 1; /* No audit support in kernel */
132+ return; /* No audit support in kernel */
133 else
134- return 0; /* Must prevent login */
135+ goto fatal_report; /* Must prevent login */
136 }
137- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
138+ rc = audit_log_acct_message(audit_fd, event,
139 NULL, "login", username ? username : "(unknown)",
140 username == NULL ? uid : -1, hostname, ip, ttyn, success);
141 saved_errno = errno;
142@@ -65,35 +77,154 @@ linux_audit_record_event(int uid, const char *username,
143 if ((rc == -EPERM) && (geteuid() != 0))
144 rc = 0;
145 errno = saved_errno;
146- return (rc >= 0);
147+ if (rc < 0) {
148+fatal_report:
149+ fatal("linux_audit_write_entry failed: %s", strerror(errno));
150+ }
151 }
152
153+static void
154+linux_audit_user_auth(int uid, const char *username,
155+ const char *hostname, const char *ip, const char *ttyn, int success, int event)
156+{
157+ int audit_fd, rc, saved_errno;
158+ static const char *event_name[] = {
159+ "maxtries exceeded",
160+ "root denied",
161+ "success",
162+ "none",
163+ "password",
164+ "challenge-response",
165+ "pubkey",
166+ "hostbased",
167+ "gssapi",
168+ "invalid user",
169+ "nologin",
170+ "connection closed",
171+ "connection abandoned",
172+ "unknown"
173+ };
174+
175+ audit_fd = audit_open();
176+ if (audit_fd < 0) {
177+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
178+ errno == EAFNOSUPPORT)
179+ return; /* No audit support in kernel */
180+ else
181+ goto fatal_report; /* Must prevent login */
182+ }
183+
184+ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN))
185+ event = SSH_AUDIT_UNKNOWN;
186+
187+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH,
188+ NULL, event_name[event], username ? username : "(unknown)",
189+ username == NULL ? uid : -1, hostname, ip, ttyn, success);
190+ saved_errno = errno;
191+ close(audit_fd);
192+ /*
193+ * Do not report error if the error is EPERM and sshd is run as non
194+ * root user.
195+ */
196+ if ((rc == -EPERM) && (geteuid() != 0))
197+ rc = 0;
198+ errno = saved_errno;
199+ if (rc < 0) {
200+fatal_report:
201+ fatal("linux_audit_write_entry failed: %s", strerror(errno));
202+ }
203+}
204+
205+int
206+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv)
207+{
208+ char buf[AUDIT_LOG_SIZE];
209+ int audit_fd, rc, saved_errno;
210+
211+ audit_fd = audit_open();
212+ if (audit_fd < 0) {
213+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
214+ errno == EAFNOSUPPORT)
215+ return 1; /* No audit support in kernel */
216+ else
217+ return 0; /* Must prevent login */
218+ }
219+ snprintf(buf, sizeof(buf), "%s_auth rport=%d", host_user ? "pubkey" : "hostbased", get_remote_port());
220+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
221+ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv);
222+ if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
223+ goto out;
224+ /* is the fingerprint_prefix() still needed?
225+ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s%s rport=%d",
226+ type, bits, sshkey_fingerprint_prefix(), fp, get_remote_port());
227+ */
228+ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s rport=%d",
229+ type, bits, fp, get_remote_port());
230+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
231+ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv);
232+out:
233+ saved_errno = errno;
234+ audit_close(audit_fd);
235+ errno = saved_errno;
236+ /* do not report error if the error is EPERM and sshd is run as non root user */
237+ return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0));
238+}
239+
240+static int user_login_count = 0;
241+
242 /* Below is the sshd audit API code */
243
244 void
245 audit_connection_from(const char *host, int port)
246 {
247-}
248 /* not implemented */
249+}
250
251-void
252+int
253 audit_run_command(const char *command)
254 {
255- /* not implemented */
256+ if (!user_login_count++)
257+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
258+ NULL, "ssh", 1, AUDIT_USER_LOGIN);
259+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
260+ NULL, "ssh", 1, AUDIT_USER_START);
261+ return 0;
262+}
263+
264+void
265+audit_end_command(int handle, const char *command)
266+{
267+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
268+ NULL, "ssh", 1, AUDIT_USER_END);
269+ if (user_login_count && !--user_login_count)
270+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
271+ NULL, "ssh", 1, AUDIT_USER_LOGOUT);
272+}
273+
274+void
275+audit_count_session_open(void)
276+{
277+ user_login_count++;
278 }
279
280 void
281 audit_session_open(struct logininfo *li)
282 {
283- if (linux_audit_record_event(li->uid, NULL, li->hostname,
284- NULL, li->line, 1) == 0)
285- fatal("linux_audit_write_entry failed: %s", strerror(errno));
286+ if (!user_login_count++)
287+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
288+ NULL, li->line, 1, AUDIT_USER_LOGIN);
289+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
290+ NULL, li->line, 1, AUDIT_USER_START);
291 }
292
293 void
294 audit_session_close(struct logininfo *li)
295 {
296- /* not implemented */
297+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
298+ NULL, li->line, 1, AUDIT_USER_END);
299+ if (user_login_count && !--user_login_count)
300+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
301+ NULL, li->line, 1, AUDIT_USER_LOGOUT);
302 }
303
304 void
305@@ -101,21 +232,43 @@ audit_event(ssh_audit_event_t event)
306 {
307 switch(event) {
308 case SSH_AUTH_SUCCESS:
309- case SSH_CONNECTION_CLOSE:
310+ linux_audit_user_auth(-1, audit_username(), NULL,
311+ get_remote_ipaddr(), "ssh", 1, event);
312+ break;
313+
314 case SSH_NOLOGIN:
315- case SSH_LOGIN_EXCEED_MAXTRIES:
316 case SSH_LOGIN_ROOT_DENIED:
317+ linux_audit_user_auth(-1, audit_username(), NULL,
318+ get_remote_ipaddr(), "ssh", 0, event);
319+ linux_audit_user_logxxx(-1, audit_username(), NULL,
320+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN);
321 break;
322
323+ case SSH_LOGIN_EXCEED_MAXTRIES:
324 case SSH_AUTH_FAIL_NONE:
325 case SSH_AUTH_FAIL_PASSWD:
326 case SSH_AUTH_FAIL_KBDINT:
327 case SSH_AUTH_FAIL_PUBKEY:
328 case SSH_AUTH_FAIL_HOSTBASED:
329 case SSH_AUTH_FAIL_GSSAPI:
330+ linux_audit_user_auth(-1, audit_username(), NULL,
331+ get_remote_ipaddr(), "ssh", 0, event);
332+ break;
333+
334+ case SSH_CONNECTION_CLOSE:
335+ if (user_login_count) {
336+ while (user_login_count--)
337+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
338+ NULL, "ssh", 1, AUDIT_USER_END);
339+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
340+ NULL, "ssh", 1, AUDIT_USER_LOGOUT);
341+ }
342+ break;
343+
344+ case SSH_CONNECTION_ABANDON:
345 case SSH_INVALID_USER:
346- linux_audit_record_event(-1, audit_username(), NULL,
347- get_remote_ipaddr(), "sshd", 0);
348+ linux_audit_user_logxxx(-1, audit_username(), NULL,
349+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN);
350 break;
351
352 default:
353@@ -123,4 +276,135 @@ audit_event(ssh_audit_event_t event)
354 }
355 }
356
357+void
358+audit_unsupported_body(int what)
359+{
360+#ifdef AUDIT_CRYPTO_SESSION
361+ char buf[AUDIT_LOG_SIZE];
362+ const static char *name[] = { "cipher", "mac", "comp" };
363+ char *s;
364+ int audit_fd;
365+
366+ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ",
367+ name[what], get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())),
368+ get_local_port());
369+ free(s);
370+ audit_fd = audit_open();
371+ if (audit_fd < 0)
372+ /* no problem, the next instruction will be fatal() */
373+ return;
374+ audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION,
375+ buf, NULL, get_remote_ipaddr(), NULL, 0);
376+ audit_close(audit_fd);
377+#endif
378+}
379+
380+const static char *direction[] = { "from-server", "from-client", "both" };
381+
382+void
383+audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid,
384+ uid_t uid)
385+{
386+#ifdef AUDIT_CRYPTO_SESSION
387+ char buf[AUDIT_LOG_SIZE];
388+ int audit_fd, audit_ok;
389+ const Cipher *cipher = cipher_by_name(enc);
390+ char *s;
391+
392+ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s pfs=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",
393+ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, pfs,
394+ (intmax_t)pid, (intmax_t)uid,
395+ get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), get_local_port());
396+ free(s);
397+ audit_fd = audit_open();
398+ if (audit_fd < 0) {
399+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
400+ errno == EAFNOSUPPORT)
401+ return; /* No audit support in kernel */
402+ else
403+ fatal("cannot open audit"); /* Must prevent login */
404+ }
405+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION,
406+ buf, NULL, get_remote_ipaddr(), NULL, 1);
407+ audit_close(audit_fd);
408+ /* do not abort if the error is EPERM and sshd is run as non root user */
409+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
410+ fatal("cannot write into audit"); /* Must prevent login */
411+#endif
412+}
413+
414+void
415+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
416+{
417+ char buf[AUDIT_LOG_SIZE];
418+ int audit_fd, audit_ok;
419+ char *s;
420+
421+ snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",
422+ direction[ctos], (intmax_t)pid, (intmax_t)uid,
423+ get_remote_port(),
424+ (s = get_local_ipaddr(packet_get_connection_in())),
425+ get_local_port());
426+ free(s);
427+ audit_fd = audit_open();
428+ if (audit_fd < 0) {
429+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
430+ errno != EAFNOSUPPORT)
431+ error("cannot open audit");
432+ return;
433+ }
434+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
435+ buf, NULL, get_remote_ipaddr(), NULL, 1);
436+ audit_close(audit_fd);
437+ /* do not abort if the error is EPERM and sshd is run as non root user */
438+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
439+ error("cannot write into audit");
440+}
441+
442+void
443+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
444+{
445+ char buf[AUDIT_LOG_SIZE];
446+ int audit_fd, audit_ok;
447+
448+ snprintf(buf, sizeof(buf), "op=destroy kind=server fp=%s direction=? spid=%jd suid=%jd ",
449+ fp, (intmax_t)pid, (intmax_t)uid);
450+ audit_fd = audit_open();
451+ if (audit_fd < 0) {
452+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
453+ errno != EAFNOSUPPORT)
454+ error("cannot open audit");
455+ return;
456+ }
457+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
458+ buf, NULL,
459+ listening_for_clients() ? get_remote_ipaddr() : NULL,
460+ NULL, 1);
461+ audit_close(audit_fd);
462+ /* do not abort if the error is EPERM and sshd is run as non root user */
463+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
464+ error("cannot write into audit");
465+}
466+
467+void
468+audit_generate_ephemeral_server_key(const char *fp)
469+{
470+ char buf[AUDIT_LOG_SIZE];
471+ int audit_fd, audit_ok;
472+
473+ snprintf(buf, sizeof(buf), "op=create kind=server fp=%s direction=? ", fp);
474+ audit_fd = audit_open();
475+ if (audit_fd < 0) {
476+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
477+ errno != EAFNOSUPPORT)
478+ error("cannot open audit");
479+ return;
480+ }
481+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
482+ buf, NULL, 0, NULL, 1);
483+ audit_close(audit_fd);
484+ /* do not abort if the error is EPERM and sshd is run as non root user */
485+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
486+ error("cannot write into audit");
487+}
488 #endif /* USE_LINUX_AUDIT */
489diff -up openssh-6.8p1/audit.c.audit openssh-6.8p1/audit.c
490--- openssh-6.8p1/audit.c.audit 2015-03-17 06:49:20.000000000 +0100
491+++ openssh-6.8p1/audit.c 2015-03-20 13:41:15.093883780 +0100
492@@ -28,6 +28,7 @@
493
494 #include <stdarg.h>
495 #include <string.h>
496+#include <unistd.h>
497
498 #ifdef SSH_AUDIT_EVENTS
499
500@@ -36,6 +37,11 @@
501 #include "key.h"
502 #include "hostfile.h"
503 #include "auth.h"
504+#include "ssh-gss.h"
505+#include "monitor_wrap.h"
506+#include "xmalloc.h"
507+#include "misc.h"
508+#include "servconf.h"
509
510 /*
511 * Care must be taken when using this since it WILL NOT be initialized when
512@@ -43,6 +49,7 @@
513 * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using.
514 */
515 extern Authctxt *the_authctxt;
516+extern ServerOptions options;
517
518 /* Maybe add the audit class to struct Authmethod? */
519 ssh_audit_event_t
520@@ -71,13 +78,10 @@ audit_classify_auth(const char *method)
521 const char *
522 audit_username(void)
523 {
524- static const char unknownuser[] = "(unknown user)";
525- static const char invaliduser[] = "(invalid user)";
526+ static const char unknownuser[] = "(unknown)";
527
528- if (the_authctxt == NULL || the_authctxt->user == NULL)
529+ if (the_authctxt == NULL || the_authctxt->user == NULL || !the_authctxt->valid)
530 return (unknownuser);
531- if (!the_authctxt->valid)
532- return (invaliduser);
533 return (the_authctxt->user);
534 }
535
536@@ -111,6 +115,40 @@ audit_event_lookup(ssh_audit_event_t ev)
537 return(event_lookup[i].name);
538 }
539
540+void
541+audit_key(int host_user, int *rv, const Key *key)
542+{
543+ char *fp;
544+ const char *crypto_name;
545+
546+ fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX);
547+ if (key->type == KEY_RSA1)
548+ crypto_name = "ssh-rsa1";
549+ else
550+ crypto_name = key_ssh_name(key);
551+ if (audit_keyusage(host_user, crypto_name, key_size(key), fp, *rv) == 0)
552+ *rv = 0;
553+ free(fp);
554+}
555+
556+void
557+audit_unsupported(int what)
558+{
559+ PRIVSEP(audit_unsupported_body(what));
560+}
561+
562+void
563+audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs)
564+{
565+ PRIVSEP(audit_kex_body(ctos, enc, mac, comp, pfs, getpid(), getuid()));
566+}
567+
568+void
569+audit_session_key_free(int ctos)
570+{
571+ PRIVSEP(audit_session_key_free_body(ctos, getpid(), getuid()));
572+}
573+
574 # ifndef CUSTOM_SSH_AUDIT_EVENTS
575 /*
576 * Null implementations of audit functions.
577@@ -140,6 +178,17 @@ audit_event(ssh_audit_event_t event)
578 }
579
580 /*
581+ * Called when a child process has called, or will soon call,
582+ * audit_session_open.
583+ */
584+void
585+audit_count_session_open(void)
586+{
587+ debug("audit count session open euid %d user %s", geteuid(),
588+ audit_username());
589+}
590+
591+/*
592 * Called when a user session is started. Argument is the tty allocated to
593 * the session, or NULL if no tty was allocated.
594 *
595@@ -174,13 +223,91 @@ audit_session_close(struct logininfo *li)
596 /*
597 * This will be called when a user runs a non-interactive command. Note that
598 * it may be called multiple times for a single connection since SSH2 allows
599- * multiple sessions within a single connection.
600+ * multiple sessions within a single connection. Returns a "handle" for
601+ * audit_end_command.
602 */
603-void
604+int
605 audit_run_command(const char *command)
606 {
607 debug("audit run command euid %d user %s command '%.200s'", geteuid(),
608 audit_username(), command);
609+ return 0;
610+}
611+
612+/*
613+ * This will be called when the non-interactive command finishes. Note that
614+ * it may be called multiple times for a single connection since SSH2 allows
615+ * multiple sessions within a single connection. "handle" should come from
616+ * the corresponding audit_run_command.
617+ */
618+void
619+audit_end_command(int handle, const char *command)
620+{
621+ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(),
622+ audit_username(), command);
623+}
624+
625+/*
626+ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key.
627+ *
628+ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key.
629+ */
630+int
631+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv)
632+{
633+ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s%s, result %d",
634+ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits,
635+ sshkey_fingerprint_prefix(), fp, rv);
636+}
637+
638+/*
639+ * This will be called when the protocol negotiation fails.
640+ */
641+void
642+audit_unsupported_body(int what)
643+{
644+ debug("audit unsupported protocol euid %d type %d", geteuid(), what);
645+}
646+
647+/*
648+ * This will be called on succesfull protocol negotiation.
649+ */
650+void
651+audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid,
652+ uid_t uid)
653+{
654+ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u",
655+ (unsigned)geteuid(), ctos, enc, mac, compress, pfs, (long)pid,
656+ (unsigned)uid);
657+}
658+
659+/*
660+ * This will be called on succesfull session key discard
661+ */
662+void
663+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
664+{
665+ debug("audit session key discard euid %u direction %d from pid %ld uid %u",
666+ (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid);
667+}
668+
669+/*
670+ * This will be called on destroy private part of the server key
671+ */
672+void
673+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
674+{
675+ debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u",
676+ geteuid(), fp, (long)pid, (unsigned)uid);
677+}
678+
679+/*
680+ * This will be called on generation of the ephemeral server key
681+ */
682+void
683+audit_generate_ephemeral_server_key(const char *)
684+{
685+ debug("audit create ephemeral server key euid %d fingerprint %s", geteuid(), fp);
686 }
687 # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
688 #endif /* SSH_AUDIT_EVENTS */
689diff -up openssh-6.8p1/audit.h.audit openssh-6.8p1/audit.h
690--- openssh-6.8p1/audit.h.audit 2015-03-17 06:49:20.000000000 +0100
691+++ openssh-6.8p1/audit.h 2015-03-20 13:41:15.093883780 +0100
692@@ -28,6 +28,7 @@
693 # define _SSH_AUDIT_H
694
695 #include "loginrec.h"
696+#include "key.h"
697
698 enum ssh_audit_event_type {
699 SSH_LOGIN_EXCEED_MAXTRIES,
700@@ -47,11 +48,25 @@ enum ssh_audit_event_type {
701 };
702 typedef enum ssh_audit_event_type ssh_audit_event_t;
703
704+int listening_for_clients(void);
705+
706 void audit_connection_from(const char *, int);
707 void audit_event(ssh_audit_event_t);
708+void audit_count_session_open(void);
709 void audit_session_open(struct logininfo *);
710 void audit_session_close(struct logininfo *);
711-void audit_run_command(const char *);
712+int audit_run_command(const char *);
713+void audit_end_command(int, const char *);
714 ssh_audit_event_t audit_classify_auth(const char *);
715+int audit_keyusage(int, const char *, unsigned, char *, int);
716+void audit_key(int, int *, const Key *);
717+void audit_unsupported(int);
718+void audit_kex(int, char *, char *, char *, char *);
719+void audit_unsupported_body(int);
720+void audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t);
721+void audit_session_key_free(int ctos);
722+void audit_session_key_free_body(int ctos, pid_t, uid_t);
723+void audit_destroy_sensitive_data(const char *, pid_t, uid_t);
724+void audit_generate_ephemeral_server_key(const char *);
725
726 #endif /* _SSH_AUDIT_H */
727diff -up openssh-6.8p1/auditstub.c.audit openssh-6.8p1/auditstub.c
728--- openssh-6.8p1/auditstub.c.audit 2015-03-20 13:41:15.093883780 +0100
729+++ openssh-6.8p1/auditstub.c 2015-03-20 13:41:15.093883780 +0100
730@@ -0,0 +1,50 @@
731+/* $Id: auditstub.c,v 1.1 jfch Exp $ */
732+
733+/*
734+ * Copyright 2010 Red Hat, Inc. All rights reserved.
735+ * Use is subject to license terms.
736+ *
737+ * Redistribution and use in source and binary forms, with or without
738+ * modification, are permitted provided that the following conditions
739+ * are met:
740+ * 1. Redistributions of source code must retain the above copyright
741+ * notice, this list of conditions and the following disclaimer.
742+ * 2. Redistributions in binary form must reproduce the above copyright
743+ * notice, this list of conditions and the following disclaimer in the
744+ * documentation and/or other materials provided with the distribution.
745+ *
746+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
747+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
748+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
749+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
750+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
751+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
752+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
753+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
754+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
755+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
756+ *
757+ * Red Hat author: Jan F. Chadima <jchadima@redhat.com>
758+ */
759+
760+#include <sys/types.h>
761+
762+void
763+audit_unsupported(int n)
764+{
765+}
766+
767+void
768+audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs)
769+{
770+}
771+
772+void
773+audit_session_key_free(int ctos)
774+{
775+}
776+
777+void
778+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
779+{
780+}
781diff -up openssh-6.8p1/auth-rsa.c.audit openssh-6.8p1/auth-rsa.c
782--- openssh-6.8p1/auth-rsa.c.audit 2015-03-17 06:49:20.000000000 +0100
783+++ openssh-6.8p1/auth-rsa.c 2015-03-20 13:41:15.094883779 +0100
784@@ -95,7 +95,10 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
785 {
786 u_char buf[32], mdbuf[16];
787 struct ssh_digest_ctx *md;
788- int len;
789+ int len, rv;
790+#ifdef SSH_AUDIT_EVENTS
791+ char *fp;
792+#endif
793
794 /* don't allow short keys */
795 if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
796@@ -119,12 +122,18 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
797 ssh_digest_free(md);
798
799 /* Verify that the response is the original challenge. */
800- if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
801- /* Wrong answer. */
802- return (0);
803+ rv = timingsafe_bcmp(response, mdbuf, 16) == 0;
804+
805+#ifdef SSH_AUDIT_EVENTS
806+ fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX);
807+ if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa) * 8, fp, rv) == 0) {
808+ debug("unsuccessful audit");
809+ rv = 0;
810 }
811- /* Correct answer. */
812- return (1);
813+ free(fp);
814+#endif
815+
816+ return rv;
817 }
818
819 /*
820diff -up openssh-6.8p1/auth.c.audit openssh-6.8p1/auth.c
821--- openssh-6.8p1/auth.c.audit 2015-03-17 06:49:20.000000000 +0100
822+++ openssh-6.8p1/auth.c 2015-03-20 13:41:15.094883779 +0100
823@@ -644,9 +644,6 @@ getpwnamallow(const char *user)
824 record_failed_login(user,
825 get_canonical_hostname(options.use_dns), "ssh");
826 #endif
827-#ifdef SSH_AUDIT_EVENTS
828- audit_event(SSH_INVALID_USER);
829-#endif /* SSH_AUDIT_EVENTS */
830 return (NULL);
831 }
832 if (!allowed_user(pw))
833diff -up openssh-6.8p1/auth.h.audit openssh-6.8p1/auth.h
834--- openssh-6.8p1/auth.h.audit 2015-03-20 13:41:15.002883927 +0100
835+++ openssh-6.8p1/auth.h 2015-03-20 13:41:15.094883779 +0100
836@@ -195,6 +195,7 @@ void abandon_challenge_response(Authctxt
837
838 char *expand_authorized_keys(const char *, struct passwd *pw);
839 char *authorized_principals_file(struct passwd *);
840+int user_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
841
842 FILE *auth_openkeyfile(const char *, struct passwd *, int);
843 FILE *auth_openprincipals(const char *, struct passwd *, int);
844@@ -213,6 +214,7 @@ int get_hostkey_index(Key *, int, struc
845 int ssh1_session_key(BIGNUM *);
846 int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *,
847 const u_char *, size_t, u_int);
848+int hostbased_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
849
850 /* debug messages during authentication */
851 void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
852diff -up openssh-6.8p1/auth2-hostbased.c.audit openssh-6.8p1/auth2-hostbased.c
853--- openssh-6.8p1/auth2-hostbased.c.audit 2015-03-20 13:41:15.002883927 +0100
854+++ openssh-6.8p1/auth2-hostbased.c 2015-03-20 13:41:15.093883780 +0100
855@@ -147,7 +147,7 @@ userauth_hostbased(Authctxt *authctxt)
856 /* test for allowed key and correct signature */
857 authenticated = 0;
858 if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
859- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
860+ PRIVSEP(hostbased_key_verify(key, sig, slen, buffer_ptr(&b),
861 buffer_len(&b))) == 1)
862 authenticated = 1;
863
864@@ -164,6 +164,18 @@ done:
865 return authenticated;
866 }
867
868+int
869+hostbased_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen)
870+{
871+ int rv;
872+
873+ rv = key_verify(key, sig, slen, data, datalen);
874+#ifdef SSH_AUDIT_EVENTS
875+ audit_key(0, &rv, key);
876+#endif
877+ return rv;
878+}
879+
880 /* return 1 if given hostkey is allowed */
881 int
882 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
883diff -up openssh-6.8p1/auth2-pubkey.c.audit openssh-6.8p1/auth2-pubkey.c
884--- openssh-6.8p1/auth2-pubkey.c.audit 2015-03-20 13:41:15.013883910 +0100
885+++ openssh-6.8p1/auth2-pubkey.c 2015-03-20 13:41:15.094883779 +0100
886@@ -172,7 +172,7 @@ userauth_pubkey(Authctxt *authctxt)
887 /* test for correct signature */
888 authenticated = 0;
889 if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
890- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
891+ PRIVSEP(user_key_verify(key, sig, slen, buffer_ptr(&b),
892 buffer_len(&b))) == 1) {
893 authenticated = 1;
894 /* Record the successful key to prevent reuse */
895@@ -250,6 +250,18 @@ pubkey_auth_info(Authctxt *authctxt, con
896 free(extra);
897 }
898
899+int
900+user_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen)
901+{
902+ int rv;
903+
904+ rv = key_verify(key, sig, slen, data, datalen);
905+#ifdef SSH_AUDIT_EVENTS
906+ audit_key(1, &rv, key);
907+#endif
908+ return rv;
909+}
910+
911 static int
912 match_principals_option(const char *principal_list, struct sshkey_cert *cert)
913 {
914diff -up openssh-6.8p1/auth2.c.audit openssh-6.8p1/auth2.c
915--- openssh-6.8p1/auth2.c.audit 2015-03-20 13:41:15.044883860 +0100
916+++ openssh-6.8p1/auth2.c 2015-03-20 13:41:15.093883780 +0100
917@@ -249,9 +249,6 @@ input_userauth_request(int type, u_int32
918 } else {
919 logit("input_userauth_request: invalid user %s", user);
920 authctxt->pw = fakepw();
921-#ifdef SSH_AUDIT_EVENTS
922- PRIVSEP(audit_event(SSH_INVALID_USER));
923-#endif
924 }
925 #ifdef USE_PAM
926 if (options.use_pam)
927diff -up openssh-6.8p1/cipher.c.audit openssh-6.8p1/cipher.c
928--- openssh-6.8p1/cipher.c.audit 2015-03-17 06:49:20.000000000 +0100
929+++ openssh-6.8p1/cipher.c 2015-03-20 13:41:15.101883767 +0100
930@@ -57,26 +59,6 @@ extern const EVP_CIPHER *evp_ssh1_3des(v
931 extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
932 #endif
933
934-struct sshcipher {
935- char *name;
936- int number; /* for ssh1 only */
937- u_int block_size;
938- u_int key_len;
939- u_int iv_len; /* defaults to block_size */
940- u_int auth_len;
941- u_int discard_len;
942- u_int flags;
943-#define CFLAG_CBC (1<<0)
944-#define CFLAG_CHACHAPOLY (1<<1)
945-#define CFLAG_AESCTR (1<<2)
946-#define CFLAG_NONE (1<<3)
947-#ifdef WITH_OPENSSL
948- const EVP_CIPHER *(*evptype)(void);
949-#else
950- void *ignored;
951-#endif
952-};
953-
954 static const struct sshcipher ciphers[] = {
955 #ifdef WITH_SSH1
956 { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
957diff -up openssh-6.8p1/cipher.h.audit openssh-6.8p1/cipher.h
958--- openssh-6.8p1/cipher.h.audit 2015-03-17 06:49:20.000000000 +0100
959+++ openssh-6.8p1/cipher.h 2015-03-20 13:41:15.094883779 +0100
960@@ -62,7 +62,26 @@
961 #define CIPHER_ENCRYPT 1
962 #define CIPHER_DECRYPT 0
963
964-struct sshcipher;
965+struct sshcipher {
966+ char *name;
967+ int number; /* for ssh1 only */
968+ u_int block_size;
969+ u_int key_len;
970+ u_int iv_len; /* defaults to block_size */
971+ u_int auth_len;
972+ u_int discard_len;
973+ u_int flags;
974+#define CFLAG_CBC (1<<0)
975+#define CFLAG_CHACHAPOLY (1<<1)
976+#define CFLAG_AESCTR (1<<2)
977+#define CFLAG_NONE (1<<3)
978+#ifdef WITH_OPENSSL
979+ const EVP_CIPHER *(*evptype)(void);
980+#else
981+ void *ignored;
982+#endif
983+};
984+
985 struct sshcipher_ctx {
986 int plaintext;
987 int encrypt;
988diff -up openssh-6.8p1/kex.c.audit openssh-6.8p1/kex.c
989--- openssh-6.8p1/kex.c.audit 2015-03-20 13:41:15.046883856 +0100
990+++ openssh-6.8p1/kex.c 2015-03-20 13:41:15.101883767 +0100
991@@ -54,6 +55,7 @@
992 #include "ssherr.h"
993 #include "sshbuf.h"
994 #include "digest.h"
995+#include "audit.h"
996
997 #ifdef GSSAPI
998 #include "ssh-gss.h"
999@@ -484,8 +508,12 @@ choose_enc(struct sshenc *enc, char *cli
1000 {
1001 char *name = match_list(client, server, NULL);
1002
1003- if (name == NULL)
1004+ if (name == NULL) {
1005+#ifdef SSH_AUDIT_EVENTS
1006+ audit_unsupported(0);
1007+#endif
1008 return SSH_ERR_NO_CIPHER_ALG_MATCH;
1009+ }
1010 if ((enc->cipher = cipher_by_name(name)) == NULL)
1011 return SSH_ERR_INTERNAL_ERROR;
1012 enc->name = name;
1013@@ -503,8 +531,12 @@ choose_mac(struct ssh *ssh, struct sshma
1014 {
1015 char *name = match_list(client, server, NULL);
1016
1017- if (name == NULL)
1018+ if (name == NULL) {
1019+#ifdef SSH_AUDIT_EVENTS
1020+ audit_unsupported(1);
1021+#endif
1022 return SSH_ERR_NO_MAC_ALG_MATCH;
1023+ }
1024 if (mac_setup(mac, name) < 0)
1025 return SSH_ERR_INTERNAL_ERROR;
1026 /* truncate the key */
1027@@ -521,8 +553,12 @@ choose_comp(struct sshcomp *comp, char *
1028 {
1029 char *name = match_list(client, server, NULL);
1030
1031- if (name == NULL)
1032+ if (name == NULL) {
1033+#ifdef SSH_AUDIT_EVENTS
1034+ audit_unsupported(2);
1035+#endif
1036 return SSH_ERR_NO_COMPRESS_ALG_MATCH;
1037+ }
1038 if (strcmp(name, "zlib@openssh.com") == 0) {
1039 comp->type = COMP_DELAYED;
1040 } else if (strcmp(name, "zlib") == 0) {
1041@@ -672,6 +708,10 @@ kex_choose_conf(struct ssh *ssh)
1042 dh_need = MAX(dh_need, newkeys->enc.block_size);
1043 dh_need = MAX(dh_need, newkeys->enc.iv_len);
1044 dh_need = MAX(dh_need, newkeys->mac.key_len);
1045+ debug("kex: %s need=%d dh_need=%d", kex->name, need, dh_need);
1046+#ifdef SSH_AUDIT_EVENTS
1047+ audit_kex(mode, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name, kex->name);
1048+#endif
1049 }
1050 /* XXX need runden? */
1051 kex->we_need = need;
1052@@ -847,3 +887,34 @@ dump_digest(char *msg, u_char *digest, i
1053 sshbuf_dump_data(digest, len, stderr);
1054 }
1055 #endif
1056+
1057+static void
1058+enc_destroy(struct sshenc *enc)
1059+{
1060+ if (enc == NULL)
1061+ return;
1062+
1063+ if (enc->key) {
1064+ memset(enc->key, 0, enc->key_len);
1065+ free(enc->key);
1066+ }
1067+
1068+ if (enc->iv) {
1069+ memset(enc->iv, 0, enc->block_size);
1070+ free(enc->iv);
1071+ }
1072+
1073+ memset(enc, 0, sizeof(*enc));
1074+}
1075+
1076+void
1077+newkeys_destroy(struct newkeys *newkeys)
1078+{
1079+ if (newkeys == NULL)
1080+ return;
1081+
1082+ enc_destroy(&newkeys->enc);
1083+ mac_destroy(&newkeys->mac);
1084+ memset(&newkeys->comp, 0, sizeof(newkeys->comp));
1085+}
1086+
1087diff -up openssh-6.8p1/kex.h.audit openssh-6.8p1/kex.h
1088--- openssh-6.8p1/kex.h.audit 2015-03-20 13:41:15.046883856 +0100
1089+++ openssh-6.8p1/kex.h 2015-03-20 13:41:15.095883777 +0100
1090@@ -199,6 +199,8 @@ int kexgss_client(struct ssh *);
1091 int kexgss_server(struct ssh *);
1092 #endif
1093
1094+void newkeys_destroy(struct newkeys *newkeys);
1095+
1096 int kex_dh_hash(const char *, const char *,
1097 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
1098 const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
1099diff -up openssh-6.8p1/key.h.audit openssh-6.8p1/key.h
1100--- openssh-6.8p1/key.h.audit 2015-03-17 06:49:20.000000000 +0100
1101+++ openssh-6.8p1/key.h 2015-03-20 13:41:15.095883777 +0100
1102@@ -50,6 +50,7 @@ typedef struct sshkey Key;
1103 #define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid
1104 #define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid
1105 #define key_is_cert sshkey_is_cert
1106+#define key_is_private sshkey_is_private
1107 #define key_type_plain sshkey_type_plain
1108 #define key_cert_is_legacy sshkey_cert_is_legacy
1109 #define key_curve_name_to_nid sshkey_curve_name_to_nid
1110diff -up openssh-6.8p1/mac.c.audit openssh-6.8p1/mac.c
1111--- openssh-6.8p1/mac.c.audit 2015-03-17 06:49:20.000000000 +0100
1112+++ openssh-6.8p1/mac.c 2015-03-20 13:41:15.102883766 +0100
1113@@ -226,6 +246,20 @@ mac_clear(struct sshmac *mac)
1114 mac->umac_ctx = NULL;
1115 }
1116
1117+void
1118+mac_destroy(struct sshmac *mac)
1119+{
1120+ if (mac == NULL)
1121+ return;
1122+
1123+ if (mac->key) {
1124+ memset(mac->key, 0, mac->key_len);
1125+ free(mac->key);
1126+ }
1127+
1128+ memset(mac, 0, sizeof(*mac));
1129+}
1130+
1131 /* XXX copied from ciphers_valid */
1132 #define MAC_SEP ","
1133 int
1134diff -up openssh-6.8p1/mac.h.audit openssh-6.8p1/mac.h
1135--- openssh-6.8p1/mac.h.audit 2015-03-17 06:49:20.000000000 +0100
1136+++ openssh-6.8p1/mac.h 2015-03-20 13:41:15.095883777 +0100
1137@@ -47,5 +47,6 @@ int mac_init(struct sshmac *);
1138 int mac_compute(struct sshmac *, u_int32_t, const u_char *, int,
1139 u_char *, size_t);
1140 void mac_clear(struct sshmac *);
1141+void mac_destroy(struct sshmac *);
1142
1143 #endif /* SSHMAC_H */
1144diff -up openssh-6.8p1/monitor.c.audit openssh-6.8p1/monitor.c
1145--- openssh-6.8p1/monitor.c.audit 2015-03-20 13:41:15.072883814 +0100
1146+++ openssh-6.8p1/monitor.c 2015-03-20 13:41:15.107883758 +0100
1147@@ -102,6 +102,7 @@
1148 #include "ssh2.h"
1149 #include "roaming.h"
1150 #include "authfd.h"
1151+#include "audit.h"
1152 #include "match.h"
1153 #include "ssherr.h"
1154
1155@@ -117,6 +118,8 @@ extern Buffer auth_debug;
1156 extern int auth_debug_init;
1157 extern Buffer loginmsg;
1158
1159+extern void destroy_sensitive_data(int);
1160+
1161 /* State exported from the child */
1162 static struct sshbuf *child_state;
1163
1164@@ -167,6 +170,11 @@ int mm_answer_gss_updatecreds(int, Buffe
1165 #ifdef SSH_AUDIT_EVENTS
1166 int mm_answer_audit_event(int, Buffer *);
1167 int mm_answer_audit_command(int, Buffer *);
1168+int mm_answer_audit_end_command(int, Buffer *);
1169+int mm_answer_audit_unsupported_body(int, Buffer *);
1170+int mm_answer_audit_kex_body(int, Buffer *);
1171+int mm_answer_audit_session_key_free_body(int, Buffer *);
1172+int mm_answer_audit_server_key_free(int, Buffer *);
1173 #endif
1174
1175 static int monitor_read_log(struct monitor *);
1176@@ -226,6 +234,10 @@ struct mon_table mon_dispatch_proto20[]
1177 #endif
1178 #ifdef SSH_AUDIT_EVENTS
1179 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
1180+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
1181+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
1182+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
1183+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free},
1184 #endif
1185 #ifdef BSD_AUTH
1186 {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
1187@@ -264,6 +276,11 @@ struct mon_table mon_dispatch_postauth20
1188 #ifdef SSH_AUDIT_EVENTS
1189 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
1190 {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
1191+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
1192+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
1193+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
1194+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
1195+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free},
1196 #endif
1197 {0, 0, NULL}
1198 };
1199@@ -296,6 +313,10 @@ struct mon_table mon_dispatch_proto15[]
1200 #endif
1201 #ifdef SSH_AUDIT_EVENTS
1202 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
1203+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
1204+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
1205+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
1206+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free},
1207 #endif
1208 #endif /* WITH_SSH1 */
1209 {0, 0, NULL}
1210@@ -309,6 +330,11 @@ struct mon_table mon_dispatch_postauth15
1211 #ifdef SSH_AUDIT_EVENTS
1212 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
1213 {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
1214+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
1215+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
1216+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
1217+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
1218+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free},
1219 #endif
1220 #endif /* WITH_SSH1 */
1221 {0, 0, NULL}
1222@@ -1466,9 +1493,11 @@ mm_answer_keyverify(int sock, Buffer *m)
1223 Key *key;
1224 u_char *signature, *data, *blob;
1225 u_int signaturelen, datalen, bloblen;
1226+ int type = 0;
1227 int verified = 0;
1228 int valid_data = 0;
1229
1230+ type = buffer_get_int(m);
1231 blob = buffer_get_string(m, &bloblen);
1232 signature = buffer_get_string(m, &signaturelen);
1233 data = buffer_get_string(m, &datalen);
1234@@ -1476,6 +1505,8 @@ mm_answer_keyverify(int sock, Buffer *m)
1235 if (hostbased_cuser == NULL || hostbased_chost == NULL ||
1236 !monitor_allowed_key(blob, bloblen))
1237 fatal("%s: bad key, not previously allowed", __func__);
1238+ if (type != key_blobtype)
1239+ fatal("%s: bad key type", __func__);
1240
1241 key = key_from_blob(blob, bloblen);
1242 if (key == NULL)
1243@@ -1496,7 +1527,17 @@ mm_answer_keyverify(int sock, Buffer *m)
1244 if (!valid_data)
1245 fatal("%s: bad signature data blob", __func__);
1246
1247- verified = key_verify(key, signature, signaturelen, data, datalen);
1248+ switch (key_blobtype) {
1249+ case MM_USERKEY:
1250+ verified = user_key_verify(key, signature, signaturelen, data, datalen);
1251+ break;
1252+ case MM_HOSTKEY:
1253+ verified = hostbased_key_verify(key, signature, signaturelen, data, datalen);
1254+ break;
1255+ default:
1256+ verified = 0;
1257+ break;
1258+ }
1259 debug3("%s: key %p signature %s",
1260 __func__, key, (verified == 1) ? "verified" : "unverified");
1261
1262@@ -1554,6 +1595,12 @@ mm_session_close(Session *s)
1263 debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
1264 session_pty_cleanup2(s);
1265 }
1266+#ifdef SSH_AUDIT_EVENTS
1267+ if (s->command != NULL) {
1268+ debug3("%s: command %d", __func__, s->command_handle);
1269+ session_end_command2(s);
1270+ }
1271+#endif
1272 session_unused(s->self);
1273 }
1274
1275@@ -1836,6 +1883,8 @@ mm_answer_term(int sock, Buffer *req)
1276 sshpam_cleanup();
1277 #endif
1278
1279+ destroy_sensitive_data(0);
1280+
1281 while (waitpid(pmonitor->m_pid, &status, 0) == -1)
1282 if (errno != EINTR)
1283 exit(1);
1284@@ -1878,11 +1927,43 @@ mm_answer_audit_command(int socket, Buff
1285 {
1286 u_int len;
1287 char *cmd;
1288+ Session *s;
1289
1290 debug3("%s entering", __func__);
1291 cmd = buffer_get_string(m, &len);
1292+
1293 /* sanity check command, if so how? */
1294- audit_run_command(cmd);
1295+ s = session_new();
1296+ if (s == NULL)
1297+ fatal("%s: error allocating a session", __func__);
1298+ s->command = cmd;
1299+ s->command_handle = audit_run_command(cmd);
1300+
1301+ buffer_clear(m);
1302+ buffer_put_int(m, s->self);
1303+
1304+ mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m);
1305+
1306+ return (0);
1307+}
1308+
1309+int
1310+mm_answer_audit_end_command(int socket, Buffer *m)
1311+{
1312+ int handle;
1313+ u_int len;
1314+ char *cmd;
1315+ Session *s;
1316+
1317+ debug3("%s entering", __func__);
1318+ handle = buffer_get_int(m);
1319+ cmd = buffer_get_string(m, &len);
1320+
1321+ s = session_by_id(handle);
1322+ if (s == NULL || s->ttyfd != -1 || s->command == NULL ||
1323+ strcmp(s->command, cmd) != 0)
1324+ fatal("%s: invalid handle", __func__);
1325+ mm_session_close(s);
1326 free(cmd);
1327 return (0);
1328 }
1329@@ -1936,6 +2017,7 @@
1330 void
1331 mm_get_keystate(struct monitor *pmonitor)
1332 {
1333+ Buffer m;
1334 debug3("%s: Waiting for new keys", __func__);
1335
1336 if ((child_state = sshbuf_new()) == NULL)
1337@@ -1946,6 +2027,21 @@ mm_get_keystate(struct monitor *pmonitor
1338 mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT,
1339 child_state);
1340 debug3("%s: GOT new keys", __func__);
1341+
1342+#ifdef SSH_AUDIT_EVENTS
1343+ if (compat20) {
1344+ buffer_init(&m);
1345+ mm_request_receive_expect(pmonitor->m_sendfd,
1346+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m);
1347+ mm_answer_audit_session_key_free_body(pmonitor->m_sendfd, &m);
1348+ buffer_free(&m);
1349+ }
1350+#endif
1351+
1352+ /* Drain any buffered messages from the child */
1353+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0)
1354+ ;
1355+
1356 }
1357
1358
1359@@ -2212,3 +2308,87 @@ mm_answer_gss_updatecreds(int socket, Bu
1360
1361 #endif /* GSSAPI */
1362
1363+#ifdef SSH_AUDIT_EVENTS
1364+int
1365+mm_answer_audit_unsupported_body(int sock, Buffer *m)
1366+{
1367+ int what;
1368+
1369+ what = buffer_get_int(m);
1370+
1371+ audit_unsupported_body(what);
1372+
1373+ buffer_clear(m);
1374+
1375+ mm_request_send(sock, MONITOR_ANS_AUDIT_UNSUPPORTED, m);
1376+ return 0;
1377+}
1378+
1379+int
1380+mm_answer_audit_kex_body(int sock, Buffer *m)
1381+{
1382+ int ctos, len;
1383+ char *cipher, *mac, *compress, *pfs;
1384+ pid_t pid;
1385+ uid_t uid;
1386+
1387+ ctos = buffer_get_int(m);
1388+ cipher = buffer_get_string(m, &len);
1389+ mac = buffer_get_string(m, &len);
1390+ compress = buffer_get_string(m, &len);
1391+ pfs = buffer_get_string(m, &len);
1392+ pid = buffer_get_int64(m);
1393+ uid = buffer_get_int64(m);
1394+
1395+ audit_kex_body(ctos, cipher, mac, compress, pfs, pid, uid);
1396+
1397+ free(cipher);
1398+ free(mac);
1399+ free(compress);
1400+ free(pfs);
1401+ buffer_clear(m);
1402+
1403+ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m);
1404+ return 0;
1405+}
1406+
1407+int
1408+mm_answer_audit_session_key_free_body(int sock, Buffer *m)
1409+{
1410+ int ctos;
1411+ pid_t pid;
1412+ uid_t uid;
1413+
1414+ ctos = buffer_get_int(m);
1415+ pid = buffer_get_int64(m);
1416+ uid = buffer_get_int64(m);
1417+
1418+ audit_session_key_free_body(ctos, pid, uid);
1419+
1420+ buffer_clear(m);
1421+
1422+ mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m);
1423+ return 0;
1424+}
1425+
1426+int
1427+mm_answer_audit_server_key_free(int sock, Buffer *m)
1428+{
1429+ int len;
1430+ char *fp;
1431+ pid_t pid;
1432+ uid_t uid;
1433+
1434+ fp = buffer_get_string(m, &len);
1435+ pid = buffer_get_int64(m);
1436+ uid = buffer_get_int64(m);
1437+
1438+ audit_destroy_sensitive_data(fp, pid, uid);
1439+
1440+ free(fp);
1441+ buffer_clear(m);
1442+
1443+ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m);
1444+ return 0;
1445+}
1446+#endif /* SSH_AUDIT_EVENTS */
1447diff -up openssh-6.8p1/monitor.h.audit openssh-6.8p1/monitor.h
1448--- openssh-6.8p1/monitor.h.audit 2015-03-20 13:41:15.072883814 +0100
1449+++ openssh-6.8p1/monitor.h 2015-03-20 13:41:15.096883775 +0100
1450@@ -69,7 +69,13 @@ enum monitor_reqtype {
1451 MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,
1452 MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,
1453 MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
1454- MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
1455+ MONITOR_REQ_AUDIT_EVENT = 112,
1456+ MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115,
1457+ MONITOR_REQ_AUDIT_END_COMMAND = 116,
1458+ MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119,
1459+ MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121,
1460+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123,
1461+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124, MONITOR_ANS_AUDIT_SERVER_KEY_FREE = 125
1462
1463 };
1464
1465diff -up openssh-6.8p1/monitor_wrap.c.audit openssh-6.8p1/monitor_wrap.c
1466--- openssh-6.8p1/monitor_wrap.c.audit 2015-03-20 13:41:15.047883855 +0100
1467+++ openssh-6.8p1/monitor_wrap.c 2015-03-20 13:41:15.108883756 +0100
1468@@ -461,7 +461,7 @@ mm_key_allowed(enum mm_keytype type, cha
1469 */
1470
1471 int
1472-mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
1473+mm_key_verify(enum mm_keytype type, Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
1474 {
1475 Buffer m;
1476 u_char *blob;
1477@@ -475,6 +475,7 @@ mm_key_verify(Key *key, u_char *sig, u_i
1478 return (0);
1479
1480 buffer_init(&m);
1481+ buffer_put_int(&m, type);
1482 buffer_put_string(&m, blob, len);
1483 buffer_put_string(&m, sig, siglen);
1484 buffer_put_string(&m, data, datalen);
1485@@ -492,6 +493,18 @@ mm_key_verify(Key *key, u_char *sig, u_i
1486 return (verified);
1487 }
1488
1489+int
1490+mm_hostbased_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
1491+{
1492+ return mm_key_verify(MM_HOSTKEY, key, sig, siglen, data, datalen);
1493+}
1494+
1495+int
1496+mm_user_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
1497+{
1498+ return mm_key_verify(MM_USERKEY, key, sig, siglen, data, datalen);
1499+}
1500+
1501 void
1502 mm_send_keystate(struct monitor *monitor)
1503 {
1504@@ -1005,10 +1018,11 @@ mm_audit_event(ssh_audit_event_t event)
1505 buffer_free(&m);
1506 }
1507
1508-void
1509+int
1510 mm_audit_run_command(const char *command)
1511 {
1512 Buffer m;
1513+ int handle;
1514
1515 debug3("%s entering command %s", __func__, command);
1516
1517@@ -1016,6 +1030,26 @@ mm_audit_run_command(const char *command
1518 buffer_put_cstring(&m, command);
1519
1520 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
1521+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, &m);
1522+
1523+ handle = buffer_get_int(&m);
1524+ buffer_free(&m);
1525+
1526+ return (handle);
1527+}
1528+
1529+void
1530+mm_audit_end_command(int handle, const char *command)
1531+{
1532+ Buffer m;
1533+
1534+ debug3("%s entering command %s", __func__, command);
1535+
1536+ buffer_init(&m);
1537+ buffer_put_int(&m, handle);
1538+ buffer_put_cstring(&m, command);
1539+
1540+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m);
1541 buffer_free(&m);
1542 }
1543 #endif /* SSH_AUDIT_EVENTS */
1544@@ -1151,3 +1185,72 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc
1545
1546 #endif /* GSSAPI */
1547
1548+#ifdef SSH_AUDIT_EVENTS
1549+void
1550+mm_audit_unsupported_body(int what)
1551+{
1552+ Buffer m;
1553+
1554+ buffer_init(&m);
1555+ buffer_put_int(&m, what);
1556+
1557+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, &m);
1558+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED,
1559+ &m);
1560+
1561+ buffer_free(&m);
1562+}
1563+
1564+void
1565+mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress, char *fps, pid_t pid,
1566+ uid_t uid)
1567+{
1568+ Buffer m;
1569+
1570+ buffer_init(&m);
1571+ buffer_put_int(&m, ctos);
1572+ buffer_put_cstring(&m, cipher);
1573+ buffer_put_cstring(&m, (mac ? mac : ""));
1574+ buffer_put_cstring(&m, compress);
1575+ buffer_put_cstring(&m, fps);
1576+ buffer_put_int64(&m, pid);
1577+ buffer_put_int64(&m, uid);
1578+
1579+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, &m);
1580+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX,
1581+ &m);
1582+
1583+ buffer_free(&m);
1584+}
1585+
1586+void
1587+mm_audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
1588+{
1589+ Buffer m;
1590+
1591+ buffer_init(&m);
1592+ buffer_put_int(&m, ctos);
1593+ buffer_put_int64(&m, pid);
1594+ buffer_put_int64(&m, uid);
1595+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m);
1596+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SESSION_KEY_FREE,
1597+ &m);
1598+ buffer_free(&m);
1599+}
1600+
1601+void
1602+mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
1603+{
1604+ Buffer m;
1605+
1606+ buffer_init(&m);
1607+ buffer_put_cstring(&m, fp);
1608+ buffer_put_int64(&m, pid);
1609+ buffer_put_int64(&m, uid);
1610+
1611+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m);
1612+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SERVER_KEY_FREE,
1613+ &m);
1614+ buffer_free(&m);
1615+}
1616+#endif /* SSH_AUDIT_EVENTS */
1617diff -up openssh-6.8p1/monitor_wrap.h.audit openssh-6.8p1/monitor_wrap.h
1618--- openssh-6.8p1/monitor_wrap.h.audit 2015-03-20 13:41:15.048883853 +0100
1619+++ openssh-6.8p1/monitor_wrap.h 2015-03-20 13:41:15.096883775 +0100
1620@@ -52,7 +52,8 @@ int mm_key_allowed(enum mm_keytype, char
1621 int mm_user_key_allowed(struct passwd *, Key *);
1622 int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
1623 int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
1624-int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
1625+int mm_hostbased_key_verify(Key *, u_char *, u_int, u_char *, u_int);
1626+int mm_user_key_verify(Key *, u_char *, u_int, u_char *, u_int);
1627 int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
1628 int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
1629 BIGNUM *mm_auth_rsa_generate_challenge(Key *);
1630@@ -79,7 +80,12 @@ void mm_sshpam_free_ctx(void *);
1631 #ifdef SSH_AUDIT_EVENTS
1632 #include "audit.h"
1633 void mm_audit_event(ssh_audit_event_t);
1634-void mm_audit_run_command(const char *);
1635+int mm_audit_run_command(const char *);
1636+void mm_audit_end_command(int, const char *);
1637+void mm_audit_unsupported_body(int);
1638+void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t);
1639+void mm_audit_session_key_free_body(int, pid_t, uid_t);
1640+void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t);
1641 #endif
1642
1643 struct Session;
1644diff -up openssh-6.8p1/packet.c.audit openssh-6.8p1/packet.c
1645--- openssh-6.8p1/packet.c.audit 2015-03-20 13:41:14.990883947 +0100
1646+++ openssh-6.8p1/packet.c 2015-03-20 13:41:15.097883774 +0100
1647@@ -67,6 +67,7 @@
1648 #include "key.h" /* typedefs XXX */
1649
1650 #include "xmalloc.h"
1651+#include "audit.h"
1652 #include "crc32.h"
1653 #include "deattack.h"
1654 #include "compat.h"
1655@@ -448,6 +449,13 @@ ssh_packet_get_connection_out(struct ssh
1656 return ssh->state->connection_out;
1657 }
1658
1659+static int
1660+packet_state_has_keys (const struct session_state *state)
1661+{
1662+ return state != NULL &&
1663+ (state->newkeys[MODE_IN] != NULL || state->newkeys[MODE_OUT] != NULL);
1664+}
1665+
1666 /*
1667 * Returns the IP-address of the remote host as a string. The returned
1668 * string must not be freed.
1669@@ -478,13 +486,6 @@ ssh_packet_close(struct ssh *ssh)
1670 if (!state->initialized)
1671 return;
1672 state->initialized = 0;
1673- if (state->connection_in == state->connection_out) {
1674- shutdown(state->connection_out, SHUT_RDWR);
1675- close(state->connection_out);
1676- } else {
1677- close(state->connection_in);
1678- close(state->connection_out);
1679- }
1680 sshbuf_free(state->input);
1681 sshbuf_free(state->output);
1682 sshbuf_free(state->outgoing_packet);
1683@@ -516,14 +517,24 @@ ssh_packet_close(struct ssh *ssh)
1684 inflateEnd(stream);
1685 }
1686 }
1687- if ((r = cipher_cleanup(&state->send_context)) != 0)
1688- error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
1689- if ((r = cipher_cleanup(&state->receive_context)) != 0)
1690- error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
1691+ if (packet_state_has_keys(state)) {
1692+ if ((r = cipher_cleanup(&state->send_context)) != 0)
1693+ error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
1694+ if ((r = cipher_cleanup(&state->receive_context)) != 0)
1695+ error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
1696+ audit_session_key_free(2);
1697+ }
1698 if (ssh->remote_ipaddr) {
1699 free(ssh->remote_ipaddr);
1700 ssh->remote_ipaddr = NULL;
1701 }
1702+ if (state->connection_in == state->connection_out) {
1703+ shutdown(state->connection_out, SHUT_RDWR);
1704+ close(state->connection_out);
1705+ } else {
1706+ close(state->connection_in);
1707+ close(state->connection_out);
1708+ }
1709 free(ssh->state);
1710 ssh->state = NULL;
1711 }
1712@@ -941,6 +952,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod
1713 }
1714 if (state->newkeys[mode] != NULL) {
1715 debug("set_newkeys: rekeying");
1716+ audit_session_key_free(mode);
1717 if ((r = cipher_cleanup(cc)) != 0)
1718 return r;
1719 enc = &state->newkeys[mode]->enc;
1720@@ -2263,6 +2275,75 @@ ssh_packet_get_output(struct ssh *ssh)
1721 return (void *)ssh->state->output;
1722 }
1723
1724+static void
1725+newkeys_destroy_and_free(struct newkeys *newkeys)
1726+{
1727+ if (newkeys == NULL)
1728+ return;
1729+
1730+ free(newkeys->enc.name);
1731+
1732+ if (newkeys->mac.enabled) {
1733+ mac_clear(&newkeys->mac);
1734+ free(newkeys->mac.name);
1735+ }
1736+
1737+ free(newkeys->comp.name);
1738+
1739+ newkeys_destroy(newkeys);
1740+ free(newkeys);
1741+}
1742+
1743+static void
1744+packet_destroy_state(struct session_state *state)
1745+{
1746+ if (state == NULL)
1747+ return;
1748+
1749+ cipher_cleanup(&state->receive_context);
1750+ cipher_cleanup(&state->send_context);
1751+
1752+ buffer_free(state->input);
1753+ state->input = NULL;
1754+ buffer_free(state->output);
1755+ state->output = NULL;
1756+ buffer_free(state->outgoing_packet);
1757+ state->outgoing_packet = NULL;
1758+ buffer_free(state->incoming_packet);
1759+ state->incoming_packet = NULL;
1760+ if( state->compression_buffer ) {
1761+ buffer_free(state->compression_buffer);
1762+ state->compression_buffer = NULL;
1763+ }
1764+ newkeys_destroy_and_free(state->newkeys[MODE_IN]);
1765+ state->newkeys[MODE_IN] = NULL;
1766+ newkeys_destroy_and_free(state->newkeys[MODE_OUT]);
1767+ state->newkeys[MODE_OUT] = NULL;
1768+ mac_destroy(state->packet_discard_mac);
1769+// TAILQ_HEAD(, packet) outgoing;
1770+// memset(state, 0, sizeof(state));
1771+}
1772+
1773+void
1774+packet_destroy_all(int audit_it, int privsep)
1775+{
1776+ if (audit_it)
1777+ audit_it = (active_state != NULL && packet_state_has_keys(active_state->state))
1778+ || (backup_state != NULL && packet_state_has_keys(backup_state->state));
1779+ if (active_state != NULL)
1780+ packet_destroy_state(active_state->state);
1781+ if (backup_state != NULL)
1782+ packet_destroy_state(backup_state->state);
1783+ if (audit_it) {
1784+#ifdef SSH_AUDIT_EVENTS
1785+ if (privsep)
1786+ audit_session_key_free(2);
1787+ else
1788+ audit_session_key_free_body(2, getpid(), getuid());
1789+#endif
1790+ }
1791+}
1792+
1793 /* XXX TODO update roaming to new API (does not work anyway) */
1794 /*
1795 * Save the state for the real connection, and use a separate state when
1796@@ -2272,18 +2373,12 @@ void
1797 ssh_packet_backup_state(struct ssh *ssh,
1798 struct ssh *backup_state)
1799 {
1800- struct ssh *tmp;
1801-
1802 close(ssh->state->connection_in);
1803 ssh->state->connection_in = -1;
1804 close(ssh->state->connection_out);
1805 ssh->state->connection_out = -1;
1806- if (backup_state)
1807- tmp = backup_state;
1808- else
1809- tmp = ssh_alloc_session_state();
1810 backup_state = ssh;
1811- ssh = tmp;
1812+ ssh = ssh_alloc_session_state();
1813 }
1814
1815 /* XXX FIXME FIXME FIXME */
1816@@ -2302,9 +2397,7 @@ ssh_packet_restore_state(struct ssh *ssh
1817 backup_state = ssh;
1818 ssh = tmp;
1819 ssh->state->connection_in = backup_state->state->connection_in;
1820- backup_state->state->connection_in = -1;
1821 ssh->state->connection_out = backup_state->state->connection_out;
1822- backup_state->state->connection_out = -1;
1823 len = sshbuf_len(backup_state->state->input);
1824 if (len > 0) {
1825 if ((r = sshbuf_putb(ssh->state->input,
1826@@ -2313,6 +2406,11 @@ ssh_packet_restore_state(struct ssh *ssh
1827 sshbuf_reset(backup_state->state->input);
1828 add_recv_bytes(len);
1829 }
1830+ backup_state->state->connection_in = -1;
1831+ backup_state->state->connection_out = -1;
1832+ packet_destroy_state(backup_state->state);
1833+ free(backup_state);
1834+ backup_state = NULL;
1835 }
1836
1837 /* Reset after_authentication and reset compression in post-auth privsep */
1838diff -up openssh-6.8p1/packet.h.audit openssh-6.8p1/packet.h
1839--- openssh-6.8p1/packet.h.audit 2015-03-17 06:49:20.000000000 +0100
1840+++ openssh-6.8p1/packet.h 2015-03-20 13:41:15.097883774 +0100
1841@@ -189,7 +189,7 @@ int sshpkt_get_end(struct ssh *ssh);
1842 const u_char *sshpkt_ptr(struct ssh *, size_t *lenp);
1843
1844 /* OLD API */
1845-extern struct ssh *active_state;
1846+extern struct ssh *active_state, *backup_state;
1847 #include "opacket.h"
1848
1849 #if !defined(WITH_OPENSSL)
1850@@ -203,4 +203,5 @@ extern struct ssh *active_state;
1851 # undef EC_POINT
1852 #endif
1853
1854+void packet_destroy_all(int, int);
1855 #endif /* PACKET_H */
1856diff -up openssh-6.8p1/session.c.audit openssh-6.8p1/session.c
1857--- openssh-6.8p1/session.c.audit 2015-03-20 13:41:15.073883813 +0100
1858+++ openssh-6.8p1/session.c 2015-03-20 13:41:15.097883774 +0100
1859@@ -139,7 +139,7 @@ extern int log_stderr;
1860 extern int debug_flag;
1861 extern u_int utmp_len;
1862 extern int startup_pipe;
1863-extern void destroy_sensitive_data(void);
1864+extern void destroy_sensitive_data(int);
1865 extern Buffer loginmsg;
1866
1867 /* original command from peer. */
1868@@ -731,6 +731,14 @@ do_exec_pty(Session *s, const char *comm
1869 /* Parent. Close the slave side of the pseudo tty. */
1870 close(ttyfd);
1871
1872+#ifndef HAVE_OSF_SIA
1873+ /* do_login in the child did not affect state in this process,
1874+ compensate. From an architectural standpoint, this is extremely
1875+ ugly. */
1876+ if (!(options.use_login && command == NULL))
1877+ audit_count_session_open();
1878+#endif
1879+
1880 /* Enter interactive session. */
1881 s->ptymaster = ptymaster;
1882 packet_set_interactive(1,
1883@@ -853,15 +861,19 @@ do_exec(Session *s, const char *command)
1884 get_remote_port());
1885
1886 #ifdef SSH_AUDIT_EVENTS
1887+ if (s->command != NULL || s->command_handle != -1)
1888+ fatal("do_exec: command already set");
1889 if (command != NULL)
1890- PRIVSEP(audit_run_command(command));
1891+ s->command = xstrdup(command);
1892 else if (s->ttyfd == -1) {
1893 char *shell = s->pw->pw_shell;
1894
1895 if (shell[0] == '\0') /* empty shell means /bin/sh */
1896 shell =_PATH_BSHELL;
1897- PRIVSEP(audit_run_command(shell));
1898+ s->command = xstrdup(shell);
1899 }
1900+ if (s->command != NULL && s->ptyfd == -1)
1901+ s->command_handle = PRIVSEP(audit_run_command(s->command));
1902 #endif
1903 if (s->ttyfd != -1)
1904 ret = do_exec_pty(s, command);
1905@@ -1704,7 +1716,10 @@ do_child(Session *s, const char *command
1906 int r = 0;
1907
1908 /* remove hostkey from the child's memory */
1909- destroy_sensitive_data();
1910+ destroy_sensitive_data(1);
1911+ /* Don't audit this - both us and the parent would be talking to the
1912+ monitor over a single socket, with no synchronization. */
1913+ packet_destroy_all(0, 1);
1914
1915 /* Force a password change */
1916 if (s->authctxt->force_pwchange) {
1917@@ -1934,6 +1949,7 @@ session_unused(int id)
1918 sessions[id].ttyfd = -1;
1919 sessions[id].ptymaster = -1;
1920 sessions[id].x11_chanids = NULL;
1921+ sessions[id].command_handle = -1;
1922 sessions[id].next_unused = sessions_first_unused;
1923 sessions_first_unused = id;
1924 }
1925@@ -2016,6 +2032,19 @@ session_open(Authctxt *authctxt, int cha
1926 }
1927
1928 Session *
1929+session_by_id(int id)
1930+{
1931+ if (id >= 0 && id < sessions_nalloc) {
1932+ Session *s = &sessions[id];
1933+ if (s->used)
1934+ return s;
1935+ }
1936+ debug("session_by_id: unknown id %d", id);
1937+ session_dump();
1938+ return NULL;
1939+}
1940+
1941+Session *
1942 session_by_tty(char *tty)
1943 {
1944 int i;
1945@@ -2532,6 +2561,32 @@ session_exit_message(Session *s, int sta
1946 chan_write_failed(c);
1947 }
1948
1949+#ifdef SSH_AUDIT_EVENTS
1950+void
1951+session_end_command2(Session *s)
1952+{
1953+ if (s->command != NULL) {
1954+ if (s->command_handle != -1)
1955+ audit_end_command(s->command_handle, s->command);
1956+ free(s->command);
1957+ s->command = NULL;
1958+ s->command_handle = -1;
1959+ }
1960+}
1961+
1962+static void
1963+session_end_command(Session *s)
1964+{
1965+ if (s->command != NULL) {
1966+ if (s->command_handle != -1)
1967+ PRIVSEP(audit_end_command(s->command_handle, s->command));
1968+ free(s->command);
1969+ s->command = NULL;
1970+ s->command_handle = -1;
1971+ }
1972+}
1973+#endif
1974+
1975 void
1976 session_close(Session *s)
1977 {
1978@@ -2540,6 +2593,10 @@ session_close(Session *s)
1979 debug("session_close: session %d pid %ld", s->self, (long)s->pid);
1980 if (s->ttyfd != -1)
1981 session_pty_cleanup(s);
1982+#ifdef SSH_AUDIT_EVENTS
1983+ if (s->command)
1984+ session_end_command(s);
1985+#endif
1986 free(s->term);
1987 free(s->display);
1988 free(s->x11_chanids);
1989@@ -2754,6 +2811,15 @@ do_authenticated2(Authctxt *authctxt)
1990 server_loop2(authctxt);
1991 }
1992
1993+static void
1994+do_cleanup_one_session(Session *s)
1995+{
1996+ session_pty_cleanup2(s);
1997+#ifdef SSH_AUDIT_EVENTS
1998+ session_end_command2(s);
1999+#endif
2000+}
2001+
2002 void
2003 do_cleanup(Authctxt *authctxt)
2004 {
2005@@ -2802,5 +2868,5 @@ do_cleanup(Authctxt *authctxt)
2006 * or if running in monitor.
2007 */
2008 if (!use_privsep || mm_is_monitor())
2009- session_destroy_all(session_pty_cleanup2);
2010+ session_destroy_all(do_cleanup_one_session);
2011 }
2012diff -up openssh-6.8p1/session.h.audit openssh-6.8p1/session.h
2013--- openssh-6.8p1/session.h.audit 2015-03-17 06:49:20.000000000 +0100
2014+++ openssh-6.8p1/session.h 2015-03-20 13:41:15.097883774 +0100
2015@@ -61,6 +61,12 @@ struct Session {
2016 char *name;
2017 char *val;
2018 } *env;
2019+
2020+ /* exec */
2021+#ifdef SSH_AUDIT_EVENTS
2022+ int command_handle;
2023+ char *command;
2024+#endif
2025 };
2026
2027 void do_authenticated(Authctxt *);
2028@@ -73,8 +79,10 @@ void session_close_by_pid(pid_t, int);
2029 void session_close_by_channel(int, void *);
2030 void session_destroy_all(void (*)(Session *));
2031 void session_pty_cleanup2(Session *);
2032+void session_end_command2(Session *);
2033
2034 Session *session_new(void);
2035+Session *session_by_id(int);
2036 Session *session_by_tty(char *);
2037 void session_close(Session *);
2038 void do_setusercontext(struct passwd *);
2039diff -up openssh-6.8p1/sshd.c.audit openssh-6.8p1/sshd.c
2040--- openssh-6.8p1/sshd.c.audit 2015-03-20 13:41:15.083883796 +0100
2041+++ openssh-6.8p1/sshd.c 2015-03-20 13:41:15.110883753 +0100
2042@@ -121,6 +124,7 @@
2043 #endif
2044 #include "monitor_wrap.h"
2045 #include "roaming.h"
2046+#include "audit.h"
2047 #include "ssh-sandbox.h"
2048 #include "version.h"
2049 #include "ssherr.h"
2050@@ -260,7 +264,7 @@ Buffer loginmsg;
2051 struct passwd *privsep_pw = NULL;
2052
2053 /* Prototypes for various functions defined later in this file. */
2054-void destroy_sensitive_data(void);
2055+void destroy_sensitive_data(int);
2056 void demote_sensitive_data(void);
2057
2058 #ifdef WITH_SSH1
2059@@ -281,6 +285,15 @@ close_listen_socks(void)
2060 num_listen_socks = -1;
2061 }
2062
2063+/*
2064+ * Is this process listening for clients (i.e. not specific to any specific
2065+ * client connection?)
2066+ */
2067+int listening_for_clients(void)
2068+{
2069+ return num_listen_socks > 0;
2070+}
2071+
2072 static void
2073 close_startup_pipes(void)
2074 {
2075@@ -560,22 +573,45 @@ sshd_exchange_identification(int sock_in
2076 }
2077 }
2078
2079-/* Destroy the host and server keys. They will no longer be needed. */
2080+/*
2081+ * Destroy the host and server keys. They will no longer be needed. Careful,
2082+ * this can be called from cleanup_exit() - i.e. from just about anywhere.
2083+ */
2084 void
2085-destroy_sensitive_data(void)
2086+destroy_sensitive_data(int privsep)
2087 {
2088 int i;
2089+ pid_t pid;
2090+ uid_t uid;
2091
2092 if (sensitive_data.server_key) {
2093 key_free(sensitive_data.server_key);
2094 sensitive_data.server_key = NULL;
2095 }
2096+ pid = getpid();
2097+ uid = getuid();
2098 for (i = 0; i < options.num_host_key_files; i++) {
2099 if (sensitive_data.host_keys[i]) {
2100+ char *fp;
2101+
2102+ if (key_is_private(sensitive_data.host_keys[i]))
2103+ fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, SSH_FP_HEX);
2104+ else
2105+ fp = NULL;
2106 key_free(sensitive_data.host_keys[i]);
2107 sensitive_data.host_keys[i] = NULL;
2108+ if (fp != NULL) {
2109+ if (privsep)
2110+ PRIVSEP(audit_destroy_sensitive_data(fp,
2111+ pid, uid));
2112+ else
2113+ audit_destroy_sensitive_data(fp,
2114+ pid, uid);
2115+ free(fp);
2116+ }
2117 }
2118- if (sensitive_data.host_certificates[i]) {
2119+ if (sensitive_data.host_certificates
2120+ && sensitive_data.host_certificates[i]) {
2121 key_free(sensitive_data.host_certificates[i]);
2122 sensitive_data.host_certificates[i] = NULL;
2123 }
2124@@ -589,6 +625,8 @@ void
2125 demote_sensitive_data(void)
2126 {
2127 Key *tmp;
2128+ pid_t pid;
2129+ uid_t uid;
2130 int i;
2131
2132 if (sensitive_data.server_key) {
2133@@ -597,13 +635,25 @@ demote_sensitive_data(void)
2134 sensitive_data.server_key = tmp;
2135 }
2136
2137+ pid = getpid();
2138+ uid = getuid();
2139 for (i = 0; i < options.num_host_key_files; i++) {
2140 if (sensitive_data.host_keys[i]) {
2141+ char *fp;
2142+
2143+ if (key_is_private(sensitive_data.host_keys[i]))
2144+ fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, SSH_FP_HEX);
2145+ else
2146+ fp = NULL;
2147 tmp = key_demote(sensitive_data.host_keys[i]);
2148 key_free(sensitive_data.host_keys[i]);
2149 sensitive_data.host_keys[i] = tmp;
2150 if (tmp->type == KEY_RSA1)
2151 sensitive_data.ssh1_host_key = tmp;
2152+ if (fp != NULL) {
2153+ audit_destroy_sensitive_data(fp, pid, uid);
2154+ free(fp);
2155+ }
2156 }
2157 /* Certs do not need demotion */
2158 }
2159@@ -675,7 +725,7 @@ privsep_preauth(Authctxt *authctxt)
2160
2161 if (use_privsep == PRIVSEP_ON)
2162 box = ssh_sandbox_init(pmonitor);
2163- pid = fork();
2164+ pmonitor->m_pid = pid = fork();
2165 if (pid == -1) {
2166 fatal("fork of unprivileged child failed");
2167 } else if (pid != 0) {
2168@@ -759,6 +811,12 @@ privsep_postauth(Authctxt *authctxt)
2169 else if (pmonitor->m_pid != 0) {
2170 verbose("User child is on pid %ld", (long)pmonitor->m_pid);
2171 buffer_clear(&loginmsg);
2172+ if (*pmonitor->m_pkex != NULL ){
2173+ newkeys_destroy((*pmonitor->m_pkex)->newkeys[MODE_OUT]);
2174+ newkeys_destroy((*pmonitor->m_pkex)->newkeys[MODE_IN]);
2175+ audit_session_key_free_body(2, getpid(), getuid());
2176+ packet_destroy_all(0, 0);
2177+ }
2178 monitor_child_postauth(pmonitor);
2179
2180 /* NEVERREACHED */
2181@@ -1286,6 +1341,7 @@ server_accept_loop(int *sock_in, int *so
2182 if (received_sigterm) {
2183 logit("Received signal %d; terminating.",
2184 (int) received_sigterm);
2185+ destroy_sensitive_data(0);
2186 close_listen_socks();
2187 if (options.pid_file != NULL)
2188 unlink(options.pid_file);
2189@@ -2242,6 +2321,7 @@ main(int ac, char **av)
2190 */
2191 if (use_privsep) {
2192 mm_send_keystate(pmonitor);
2193+ packet_destroy_all(1, 1);
2194 exit(0);
2195 }
2196
2197@@ -2287,7 +2367,7 @@ main(int ac, char **av)
2198 privsep_postauth(authctxt);
2199 /* the monitor process [priv] will not return */
2200 if (!compat20)
2201- destroy_sensitive_data();
2202+ destroy_sensitive_data(0);
2203 }
2204
2205 packet_set_timeout(options.client_alive_interval,
2206@@ -2301,6 +2381,9 @@ main(int ac, char **av)
2207 do_authenticated(authctxt);
2208
2209 /* The connection has been terminated. */
2210+ packet_destroy_all(1, 1);
2211+ destroy_sensitive_data(1);
2212+
2213 packet_get_bytes(&ibytes, &obytes);
2214 verbose("Transferred: sent %llu, received %llu bytes",
2215 (unsigned long long)obytes, (unsigned long long)ibytes);
2216@@ -2461,6 +2544,10 @@ do_ssh1_kex(void)
2217 if (cookie[i] != packet_get_char())
2218 packet_disconnect("IP Spoofing check bytes do not match.");
2219
2220+#ifdef SSH_AUDIT_EVENTS
2221+ audit_kex(2, cipher_name(cipher_type), "crc", "none", "none");
2222+#endif
2223+
2224 debug("Encryption type: %.200s", cipher_name(cipher_type));
2225
2226 /* Get the encrypted integer. */
2227@@ -2520,7 +2607,7 @@ do_ssh1_kex(void)
2228 }
2229
2230 /* Destroy the private and public keys. No longer. */
2231- destroy_sensitive_data();
2232+ destroy_sensitive_data(1);
2233
2234 if (use_privsep)
2235 mm_ssh1_session_id(session_id);
2236@@ -2703,6 +2802,16 @@ do_ssh2_kex(void)
2237 void
2238 cleanup_exit(int i)
2239 {
2240+ static int in_cleanup = 0;
2241+ int is_privsep_child;
2242+
2243+ /* cleanup_exit can be called at the very least from the privsep
2244+ wrappers used for auditing. Make sure we don't recurse
2245+ indefinitely. */
2246+ if (in_cleanup)
2247+ _exit(i);
2248+ in_cleanup = 1;
2249+
2250 if (the_authctxt) {
2251 do_cleanup(the_authctxt);
2252 if (use_privsep && privsep_is_preauth &&
2253@@ -2714,9 +2823,14 @@ cleanup_exit(int i)
2254 pmonitor->m_pid, strerror(errno));
2255 }
2256 }
2257+ is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0;
2258+ if (sensitive_data.host_keys != NULL)
2259+ destroy_sensitive_data(is_privsep_child);
2260+ packet_destroy_all(1, is_privsep_child);
2261 #ifdef SSH_AUDIT_EVENTS
2262 /* done after do_cleanup so it can cancel the PAM auth 'thread' */
2263- if (!use_privsep || mm_is_monitor())
2264+ if ((the_authctxt == NULL || !the_authctxt->authenticated) &&
2265+ (!use_privsep || mm_is_monitor()))
2266 audit_event(SSH_CONNECTION_ABANDON);
2267 #endif
2268 _exit(i);
2269diff -up openssh-6.8p1/sshkey.c.audit openssh-6.8p1/sshkey.c
2270--- openssh-6.8p1/sshkey.c.audit 2015-03-17 06:49:20.000000000 +0100
2271+++ openssh-6.8p1/sshkey.c 2015-03-20 13:41:15.111883751 +0100
2272@@ -317,6 +319,33 @@ sshkey_type_is_valid_ca(int type)
2273 }
2274
2275 int
2276+sshkey_is_private(const struct sshkey *k)
2277+{
2278+ switch (k->type) {
2279+ case KEY_RSA_CERT_V00:
2280+ case KEY_RSA_CERT:
2281+ case KEY_RSA1:
2282+ case KEY_RSA:
2283+ return k->rsa->d != NULL;
2284+ case KEY_DSA_CERT_V00:
2285+ case KEY_DSA_CERT:
2286+ case KEY_DSA:
2287+ return k->dsa->priv_key != NULL;
2288+#ifdef OPENSSL_HAS_ECC
2289+ case KEY_ECDSA_CERT:
2290+ case KEY_ECDSA:
2291+ return EC_KEY_get0_private_key(k->ecdsa) != NULL;
2292+#endif
2293+ case KEY_ED25519_CERT:
2294+ case KEY_ED25519:
2295+ return (k->ed25519_pk != NULL);
2296+ default:
2297+ /* fatal("key_is_private: bad key type %d", k->type); */
2298+ return 0;
2299+ }
2300+}
2301+
2302+int
2303 sshkey_is_cert(const struct sshkey *k)
2304 {
2305 if (k == NULL)
2306diff -up openssh-6.8p1/sshkey.h.audit openssh-6.8p1/sshkey.h
2307--- openssh-6.8p1/sshkey.h.audit 2015-03-17 06:49:20.000000000 +0100
2308+++ openssh-6.8p1/sshkey.h 2015-03-20 13:41:15.098883772 +0100
2309@@ -134,6 +134,7 @@ u_int sshkey_size(const struct sshkey
2310 int sshkey_generate(int type, u_int bits, struct sshkey **keyp);
2311 int sshkey_from_private(const struct sshkey *, struct sshkey **);
2312 int sshkey_type_from_name(const char *);
2313+int sshkey_is_private(const struct sshkey *);
2314 int sshkey_is_cert(const struct sshkey *);
2315 int sshkey_type_is_cert(int);
2316 int sshkey_type_plain(int);
2317diff -up openssh-6.8p1/sandbox-seccomp-filter.c.audit openssh-6.8p1/sandbox-seccomp-filter.c
2318--- openssh-6.8p1/sandbox-seccomp-filter.c.audit 2015-03-20 13:41:15.088883788 +0100
2319+++ openssh-6.8p1/sandbox-seccomp-filter.c 2015-03-20 13:41:15.097883774 +0100
2320@@ -110,6 +110,12 @@ static const struct sock_filter preauth_
2321 #ifdef __NR_time /* not defined on EABI ARM */
2322 SC_ALLOW(time),
2323 #endif
2324+#ifdef SSH_AUDIT_EVENTS
2325+ SC_ALLOW(getuid),
2326+#ifdef __NR_getuid32 /* not defined on x86_64 */
2327+ SC_ALLOW(getuid32),
2328+#endif
2329+#endif
2330 SC_ALLOW(read),
2331 SC_ALLOW(write),
2332 SC_ALLOW(close),