audit/backport-audisp-remote-cleanup-krb5-memory-leaks-on-error-paths.patch
2022-12-28 10:53:05 +08:00

201 lines
5.9 KiB
Diff

From 09c62a6f4e4a6963a731d3018209b91dc6447f70 Mon Sep 17 00:00:00 2001
From: Steve Grubb <sgrubb@redhat.com>
Date: Mon, 11 Jul 2022 14:21:04 -0400
Subject: audisp-remote - cleanup krb5 memory leaks on error
paths
Conflict:context adaptation
---
audisp/plugins/remote/audisp-remote.c | 75 ++++++++++++++++++++-------
1 file changed, 56 insertions(+), 19 deletions(-)
diff --git a/audisp/plugins/remote/audisp-remote.c b/audisp/plugins/remote/audisp-remote.c
index 3be91b3..3b9d8f0 100644
--- a/audisp/plugins/remote/audisp-remote.c
+++ b/audisp/plugins/remote/audisp-remote.c
@@ -757,9 +757,8 @@ static void gss_failure (const char *msg, int major_status, int minor_status)
gss_failure_2 (msg, minor_status, GSS_C_MECH_CODE);
}
-#define KCHECK(x,f) if (x) { \
- syslog (LOG_ERR, "krb5 error: %s in %s\n", krb5_get_error_message (kcontext, x), f); \
- return -1; }
+#define KLOG(x,f) syslog (LOG_ERR, "krb5 error: %s in %s\n", \
+ krb5_get_error_message (kcontext, x), f);
/* Each time we connect to the server, we negotiate a set of credentials and
a security context. To do this, we need our own credentials first. For
@@ -800,7 +799,10 @@ static int negotiate_credentials (void)
recv_tok.value = NULL;
krberr = krb5_init_context (&kcontext);
- KCHECK (krberr, "krb5_init_context");
+ if (krberr) {
+ KLOG (krberr, "krb5_init_context");
+ return -1;
+ }
if (config.krb5_key_file)
key_file = config.krb5_key_file;
@@ -815,21 +817,24 @@ static int negotiate_credentials (void)
syslog (LOG_ERR,
"%s is not mode 0400 (it's %#o) - compromised key?",
key_file, st.st_mode & 07777);
- return -1;
+ goto error1;
}
if (st.st_uid != 0) {
if (!quiet)
syslog (LOG_ERR,
"%s is not owned by root (it's %d) - compromised key?",
key_file, st.st_uid);
- return -1;
+ goto error1;
}
}
/* This looks up the default real (*our* realm) from
/etc/krb5.conf (or wherever) */
krberr = krb5_get_default_realm (kcontext, &realm_name);
- KCHECK (krberr, "krb5_get_default_realm");
+ if (krberr) {
+ KLOG (krberr, "krb5_get_default_realm");
+ goto error1;
+ }
krb5_client_name = config.krb5_client_name ?
config.krb5_client_name : "auditd";
@@ -838,7 +843,7 @@ static int negotiate_credentials (void)
syslog (LOG_ERR,
"gethostname: host name longer than %ld characters?",
sizeof (host_name));
- return -1;
+ goto error2;
}
syslog (LOG_ERR, "kerberos principal: %s/%s@%s\n",
@@ -847,17 +852,26 @@ static int negotiate_credentials (void)
krberr = krb5_build_principal (kcontext, &audit_princ,
strlen(realm_name), realm_name,
krb5_client_name, host_name, NULL);
- KCHECK (krberr, "krb5_build_principal");
+ if (krberr) {
+ KLOG (krberr, "krb5_build_principal");
+ goto error2;
+ }
/* Locate our machine's key table, where our private key is
* held. */
krberr = krb5_kt_resolve (kcontext, key_file, &keytab);
- KCHECK (krberr, "krb5_kt_resolve");
+ if (krberr) {
+ KLOG (krberr, "krb5_kt_resolve");
+ goto error3;
+ }
/* Identify a cache to hold the key in. The GSS wrappers look
up our credentials here. */
krberr = krb5_cc_resolve (kcontext, CCACHE_NAME, &ccache);
- KCHECK (krberr, "krb5_cc_resolve");
+ if (krberr) {
+ KLOG (krberr, "krb5_cc_resolve");
+ goto error4;
+ }
setenv("KRB5CCNAME", CCACHE_NAME, 1);
@@ -872,15 +886,24 @@ static int negotiate_credentials (void)
krberr = krb5_get_init_creds_keytab(kcontext, &my_creds, audit_princ,
keytab, 0, NULL,
&options);
- KCHECK (krberr, "krb5_get_init_creds_keytab");
+ if (krberr) {
+ KLOG (krberr, "krb5_get_init_creds_keytab");
+ goto error5;
+ }
/* Create the cache... */
krberr = krb5_cc_initialize(kcontext, ccache, audit_princ);
- KCHECK (krberr, "krb5_cc_initialize");
+ if (krberr) {
+ KLOG (krberr, "krb5_cc_initialize");
+ goto error6;
+ }
/* ...and store our credentials in it. */
krberr = krb5_cc_store_cred(kcontext, ccache, &my_creds);
- KCHECK (krberr, "krb5_cc_store_cred");
+ if (krberr) {
+ KLOG (krberr, "krb5_cc_store_cred");
+ goto error6;
+ }
/* The GSS code now has a set of credentials for this program.
I.e. we know who "we" are. Now we talk to the server to
@@ -903,13 +926,13 @@ static int negotiate_credentials (void)
(gss_OID) gss_nt_service_name, &service_name_e);
if (major_status != GSS_S_COMPLETE) {
gss_failure("importing name", major_status, minor_status);
- return -1;
+ goto error6;
}
/* Someone has to go first. In this case, it's us. */
if (send_token(sock, empty_token) < 0) {
(void) gss_release_name(&minor_status, &service_name_e);
- return -1;
+ goto error6;
}
/* The server starts this loop with the token we just sent
@@ -936,7 +959,7 @@ static int negotiate_credentials (void)
&send_tok);
(void) gss_release_name(&minor_status,
&service_name_e);
- return -1;
+ goto error6;
}
}
(void) gss_release_buffer(&minor_status, &send_tok);
@@ -949,7 +972,7 @@ static int negotiate_credentials (void)
if (*gss_context != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&minor_status,
gss_context, GSS_C_NO_BUFFER);
- return -1;
+ goto error6;
}
/* Now get any tokens the sever sends back. We use
@@ -958,7 +981,7 @@ static int negotiate_credentials (void)
if (recv_token(sock, &recv_tok) < 0) {
(void) gss_release_name(&minor_status,
&service_name_e);
- return -1;
+ goto error6;
}
token_ptr = &recv_tok;
}
@@ -985,6 +1008,20 @@ static int negotiate_credentials (void)
(char *)recv_tok.value);
#endif
return 0;
+
+error6:
+ krb5_free_creds(kcontext, &my_creds);
+error5:
+ krb5_cc_close(kcontext, ccache);
+error4:
+ krb5_kt_close(kcontext, keytab);
+error3:
+ krb5_free_principal(kcontext, audit_princ);
+error2:
+ krb5_free_default_realm(kcontext, realm_name);
+error1:
+ krb5_free_context(kcontext);
+ return -1;
}
#endif // USE_GSSAPI
--
2.27.0