Blob Blame History Raw
diff -Naur libreswan-3.29-orig/programs/pluto/ikev1.c libreswan-3.29/programs/pluto/ikev1.c
--- libreswan-3.29-orig/programs/pluto/ikev1.c	2019-06-26 22:03:27.801184503 -0400
+++ libreswan-3.29/programs/pluto/ikev1.c	2019-06-27 13:26:11.443969779 -0400
@@ -2675,6 +2675,12 @@
 	passert(st != NULL);
 	pexpect(!state_is_busy(st));
 
+	if (result > STF_OK) {
+		if (st != NULL) {
+			linux_audit_conn(md->st, IS_IKE_SA_ESTABLISHED(md->st) ? LAK_CHILD_FAIL : LAK_PARENT_FAIL);
+		}
+	}
+
 	switch (result) {
 	case STF_OK:
 	{
diff -Naur libreswan-3.29-orig/programs/pluto/ikev1_quick.c libreswan-3.29/programs/pluto/ikev1_quick.c
--- libreswan-3.29-orig/programs/pluto/ikev1_quick.c	2019-06-26 22:03:27.803184531 -0400
+++ libreswan-3.29/programs/pluto/ikev1_quick.c	2019-06-27 13:23:53.787080070 -0400
@@ -1663,6 +1663,9 @@
 	if (!install_inbound_ipsec_sa(st))
 		return STF_INTERNAL_ERROR; /* ??? we may be partly committed */
 
+	/* we only audit once for IPsec SA's, we picked the inbound SA */
+	linux_audit_conn(st, LAK_CHILD_START);
+
 	/* encrypt message, except for fixed part of header */
 
 	if (!ikev1_encrypt_message(&rbody, st)) {
diff -Naur libreswan-3.29-orig/programs/pluto/ikev2.c libreswan-3.29/programs/pluto/ikev2.c
--- libreswan-3.29-orig/programs/pluto/ikev2.c	2019-06-10 10:22:04.000000000 -0400
+++ libreswan-3.29/programs/pluto/ikev2.c	2019-06-27 13:25:16.529215928 -0400
@@ -3204,6 +3204,13 @@
 		lswlog_v2_stf_status(buf, result);
 	}
 
+	/* audit log failures - success is audit logged in ikev2_ike_sa_established() */
+	if (result > STF_OK) {
+		if (st != NULL) {
+			linux_audit_conn(st, IS_IKE_SA_ESTABLISHED(st) ? LAK_CHILD_FAIL : LAK_PARENT_FAIL);
+		}
+	}
+
 	switch (result) {
 
 	case STF_SUSPEND:
diff -Naur libreswan-3.29-orig/programs/pluto/ikev2_child.c libreswan-3.29/programs/pluto/ikev2_child.c
--- libreswan-3.29-orig/programs/pluto/ikev2_child.c	2019-06-10 10:22:04.000000000 -0400
+++ libreswan-3.29/programs/pluto/ikev2_child.c	2019-06-27 13:23:53.788080084 -0400
@@ -102,6 +102,10 @@
 	return STF_OK;
 }
 
+/*
+ * The caller could have done the linux_audit_conn() call, except one case
+ * here deletes the state before returning an STF error
+ */
 stf_status ikev2_child_sa_respond(struct msg_digest *md,
 				  pb_stream *outpbs,
 				  enum isakmp_xchg_types isa_xchg)
diff -Naur libreswan-3.29-orig/programs/pluto/ikev2_parent.c libreswan-3.29/programs/pluto/ikev2_parent.c
--- libreswan-3.29-orig/programs/pluto/ikev2_parent.c	2019-06-10 10:22:04.000000000 -0400
+++ libreswan-3.29/programs/pluto/ikev2_parent.c	2019-06-27 13:23:53.789080097 -0400
@@ -239,6 +239,7 @@
 	c->newest_isakmp_sa = ike->sa.st_serialno;
 	v2_schedule_replace_event(&ike->sa);
 	ike->sa.st_viable_parent = TRUE;
+	linux_audit_conn(&ike->sa, LAK_PARENT_START);
 	pstat_sa_established(&ike->sa);
 }
 
@@ -1581,6 +1582,24 @@
 				libreswan_log("IKE_AUTH response contained an unknown error notification (%d)", n);
 			} else {
 				libreswan_log("IKE_AUTH response contained the error notification %s", name);
+				/*
+				 * There won't be a child state transition, so log if error is child related.
+				 * see RFC 7296 Section 1.2
+				 */
+				switch(n) {
+				case v2N_NO_PROPOSAL_CHOSEN:
+				case v2N_SINGLE_PAIR_REQUIRED:
+				case v2N_NO_ADDITIONAL_SAS:
+				case v2N_INTERNAL_ADDRESS_FAILURE:
+				case v2N_FAILED_CP_REQUIRED:
+				case v2N_TS_UNACCEPTABLE:
+				case v2N_INVALID_SELECTORS:
+					/* fallthrough */
+					linux_audit_conn(st, LAK_CHILD_FAIL);
+					break;
+				default:
+					break;
+				}
 			}
 		}
 	}
@@ -3063,10 +3082,6 @@
 	ikev2_ike_sa_established(pexpect_ike_sa(st), md->svm,
 				 STATE_PARENT_R2);
 
-#ifdef USE_LINUX_AUDIT
-	linux_audit_conn(st, LAK_PARENT_START);
-#endif
-
 	if (LHAS(st->hidden_variables.st_nat_traversal, NATED_HOST)) {
 		/* ensure we run keepalives if needed */
 		if (c->nat_keepalive)
@@ -3801,10 +3816,6 @@
 	ikev2_ike_sa_established(pexpect_ike_sa(pst), md->svm,
 				 STATE_PARENT_I3);
 
-#ifdef USE_LINUX_AUDIT
-	linux_audit_conn(st, LAK_PARENT_START);
-#endif
-
 	if (LHAS(st->hidden_variables.st_nat_traversal, NATED_HOST)) {
 		/* ensure we run keepalives if needed */
 		if (c->nat_keepalive)
diff -Naur libreswan-3.29-orig/programs/pluto/kernel.c libreswan-3.29/programs/pluto/kernel.c
--- libreswan-3.29-orig/programs/pluto/kernel.c	2019-06-10 10:22:04.000000000 -0400
+++ libreswan-3.29/programs/pluto/kernel.c	2019-06-27 13:23:53.790080111 -0400
@@ -3334,7 +3334,8 @@
 	}
 
 #ifdef USE_LINUX_AUDIT
-	linux_audit_conn(st, LAK_CHILD_START);
+	if (inbound_also)
+		linux_audit_conn(st, LAK_CHILD_START);
 #endif
 	statetime_stop(&start, "%s()", __func__);
 
@@ -3378,8 +3379,13 @@
 {
 #ifdef USE_LINUX_AUDIT
 	/* XXX in IKEv2 we get a spurious call with a parent st :( */
-	if (IS_CHILD_SA(st))
-		linux_audit_conn(st, LAK_CHILD_DESTROY);
+	if (IS_CHILD_SA(st)) {
+		/* child destruction already logged for STATE_CHILDSA_DEL state */
+		if (st->st_esp.present || st->st_ah.present) {
+			/* ESP or AH means this was an established IPsec SA */
+			linux_audit_conn(st, LAK_CHILD_DESTROY);
+		}
+	}
 #endif
 	switch (kern_interface) {
 	case USE_KLIPS:
diff -Naur libreswan-3.29-orig/programs/pluto/linux_audit.c libreswan-3.29/programs/pluto/linux_audit.c
--- libreswan-3.29-orig/programs/pluto/linux_audit.c	2019-06-10 10:22:04.000000000 -0400
+++ libreswan-3.29/programs/pluto/linux_audit.c	2019-06-27 13:24:21.474460154 -0400
@@ -176,12 +176,16 @@
 	zero(&cipher_str);	/* OK: no pointer fields */
 	zero(&spi_str);	/* OK: no pointer fields */
 
+	ip_address_buf raddr_buf;
+	const char *raddr = ipstr(&c->spd.that.host_addr, &raddr_buf);
+
 	switch (op) {
 	case LAK_PARENT_START:
 	case LAK_PARENT_DESTROY:
+	case LAK_PARENT_FAIL:
 		initiator = (st->st_original_role == ORIGINAL_INITIATOR) || IS_PHASE1_INIT(st->st_state);
 		snprintf(head, sizeof(head), "op=%s direction=%s %s connstate=%lu ike-version=%s auth=%s",
-			op == LAK_PARENT_START ? "start" : "destroy",
+			op == LAK_PARENT_DESTROY ? "destroy" : "start", /* fail to start logged under op=start */
 			initiator ? "initiator" : "responder",
 			conn_encode,
 			st->st_serialno,
@@ -191,7 +195,8 @@
 					st->st_oakley.auth, &esb));
 
 		snprintf(prfname, sizeof(prfname), "%s",
-			 st->st_oakley.ta_prf->prf_ike_audit_name);
+			st->st_oakley.ta_prf == NULL ? "none" :
+				st->st_oakley.ta_prf->prf_ike_audit_name);
 
 		if (st->st_oakley.ta_integ == &ike_alg_integ_none) {
 			if (st->st_ike_version == IKEv1) {
@@ -220,18 +225,21 @@
 		}
 
 		snprintf(cipher_str, sizeof(cipher_str),
-			"cipher=%s ksize=%d integ=%s prf=%s pfs=%s",
-			st->st_oakley.ta_encrypt->encrypt_ike_audit_name,
+			"cipher=%s ksize=%d integ=%s prf=%s pfs=%s raddr=%s",
+				st->st_oakley.ta_encrypt == NULL ? "none" :
+					st->st_oakley.ta_encrypt->encrypt_ike_audit_name,
 			st->st_oakley.enckeylen,
 			integname, prfname,
-			st->st_oakley.ta_dh->common.name);
+			st->st_oakley.ta_dh == NULL ? "none" :
+				st->st_oakley.ta_dh->common.name, raddr);
 		break;
 
 	case LAK_CHILD_START:
 	case LAK_CHILD_DESTROY:
+	case LAK_CHILD_FAIL:
 	{
 		snprintf(head, sizeof(head), "op=%s %s connstate=%lu, satype=%s samode=%s",
-			op == LAK_CHILD_START ? "start" : "destroy",
+			op == LAK_CHILD_DESTROY ? "destroy" : "start", /* fail to start logged under op=start */
 			conn_encode,
 			st->st_serialno,
 			st->st_esp.present ? "ipsec-esp" : (st->st_ah.present ? "ipsec-ah" : "ipsec-policy"),
@@ -274,7 +282,7 @@
 
 		/* note: each arg appears twice because it is printed two ways */
 		snprintf(spi_str, sizeof(spi_str),
-			"in-spi=%" PRIu32 "(0x%08" PRIu32 ") out-spi=%" PRIu32 "(0x%08" PRIu32 ") in-ipcomp=%" PRIu32 "(0x%08" PRIu32 ") out-ipcomp=%" PRIu32 "(0x%08" PRIu32 ")",
+			"in-spi=%" PRIu32 "(0x%08" PRIu32 ") out-spi=%" PRIu32 "(0x%08" PRIu32 ") in-ipcomp=%" PRIu32 "(0x%08" PRIu32 ") out-ipcomp=%" PRIu32 "(0x%08" PRIu32 ") raddr=%s",
 			ntohl(pi->attrs.spi),
 			ntohl(pi->attrs.spi),
 			ntohl(pi->our_spi),
@@ -282,7 +290,8 @@
 			ntohl(st->st_ipcomp.attrs.spi),	/* zero if missing */
 			ntohl(st->st_ipcomp.attrs.spi),	/* zero if missing */
 			ntohl(st->st_ipcomp.our_spi),	/* zero if missing */
-			ntohl(st->st_ipcomp.our_spi));	/* zero if missing */
+			ntohl(st->st_ipcomp.our_spi),	/* zero if missing */
+			raddr);
 		break;
 	}
 	default:
@@ -290,21 +299,18 @@
 	}
 	free(conn_encode); /* allocated by audit_encode_nv_string() */
 
-	ip_address_buf laddr_buf;
-	const char *laddr = ipstr(&c->spd.this.host_addr, &laddr_buf);
-
-	ip_address_buf raddr_buf;
-	const char *raddr = ipstr(&c->spd.that.host_addr, &raddr_buf);
-
-	snprintf(audit_str, sizeof(audit_str), "%s %s %s laddr=%s",
+	snprintf(audit_str, sizeof(audit_str), "%s %s %s",
 		head,
 		cipher_str,
-		spi_str,
-		laddr);
+		spi_str);
+
+	ip_address_buf laddr_buf;
+	const char *laddr = ipstr(&c->spd.this.host_addr, &laddr_buf);
 
-	linux_audit((op == LAK_CHILD_START || op == LAK_CHILD_DESTROY) ?
+	linux_audit((op == LAK_CHILD_START || op == LAK_CHILD_DESTROY || op == LAK_CHILD_FAIL) ?
 			AUDIT_CRYPTO_IPSEC_SA : AUDIT_CRYPTO_IKE_SA,
-		audit_str, raddr, AUDIT_RESULT_OK);
+		audit_str, laddr,
+		(op == LAK_PARENT_FAIL || op == LAK_CHILD_FAIL) ? AUDIT_RESULT_FAIL : AUDIT_RESULT_OK);
 }
 #if __GNUC__ >= 7
 #pragma GCC diagnostic pop
diff -Naur libreswan-3.29-orig/programs/pluto/log.h libreswan-3.29/programs/pluto/log.h
--- libreswan-3.29-orig/programs/pluto/log.h	2019-06-10 10:22:04.000000000 -0400
+++ libreswan-3.29/programs/pluto/log.h	2019-06-27 13:23:53.791080125 -0400
@@ -174,7 +174,9 @@
 	LAK_PARENT_START,
 	LAK_CHILD_START,
 	LAK_PARENT_DESTROY,
-	LAK_CHILD_DESTROY
+	LAK_CHILD_DESTROY,
+	LAK_PARENT_FAIL,
+	LAK_CHILD_FAIL
 };
 extern void linux_audit_init(void);
 extern void linux_audit(const int type, const char *message,
diff -Naur libreswan-3.29-orig/programs/pluto/retry.c libreswan-3.29/programs/pluto/retry.c
--- libreswan-3.29-orig/programs/pluto/retry.c	2019-06-10 10:22:04.000000000 -0400
+++ libreswan-3.29/programs/pluto/retry.c	2019-06-27 13:25:27.536367032 -0400
@@ -123,6 +123,10 @@
 
 	set_cur_state(st);  /* ipsecdoi_replace would reset cur_state, set it again */
 	pstat_sa_failed(st, REASON_TOO_MANY_RETRANSMITS);
+
+        /* placed here because IKEv1 doesn't do a proper state change to STF_FAIL/STF_FATAL */
+        linux_audit_conn(st, IS_IKE_SA(st) ? LAK_PARENT_FAIL : LAK_CHILD_FAIL);
+
 	delete_state(st);
 	/* note: no md->st to clear */
 }
diff -Naur libreswan-3.29-orig/programs/pluto/state.c libreswan-3.29/programs/pluto/state.c
--- libreswan-3.29-orig/programs/pluto/state.c	2019-06-10 10:22:04.000000000 -0400
+++ libreswan-3.29/programs/pluto/state.c	2019-06-27 13:23:53.792080138 -0400
@@ -875,6 +875,16 @@
 
 #ifdef USE_LINUX_AUDIT
 	/*
+	 * IKEv2 IKE failures are logged in the state transition conpletion.
+	 * IKEv1 IKE failures do not go through a transition, so we catch
+	 * these in delete_state()
+	 */
+	if (IS_IKE_SA(st) && st->st_ike_version == IKEv1 &&
+		!IS_IKE_SA_ESTABLISHED(st)) {
+		linux_audit_conn(st, LAK_PARENT_FAIL);
+	}
+
+	/*
 	 * only log parent state deletes, we log children in
 	 * ipsec_delete_sa()
 	 */