summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Slebodnik <lslebodn@redhat.com>2017-01-17 10:17:24 +0100
committerLukas Slebodnik <lslebodn@redhat.com>2017-02-01 14:42:56 +0100
commitcb831fbbcb0dac8b6202037d4cd1a0d82db54f54 (patch)
treeb1e6280ec30ec50bbf0b82a4c747fac09291f820
parentb1afef0bc8d98c389a7f71307bee8ef9fc991ced (diff)
downloadsssd-cb831fbbcb0dac8b6202037d4cd1a0d82db54f54.tar.gz
sssd-cb831fbbcb0dac8b6202037d4cd1a0d82db54f54.tar.xz
sssd-cb831fbbcb0dac8b6202037d4cd1a0d82db54f54.zip
ldap_child: Fix use after free
In case on any krb5 related error, we tried to send string interpretation of krb5 error tb parrent in prepare_response. However, we cannot use global krb5 context (krb5_error_ctx) because the context is every time released in done section of ldap_child_get_tgt_sync. This patch rather return duplicated string to prevent use after free. Backtrace: #0 __strchr_sse42 () at ../sysdeps/x86_64/multiarch/strchr.S:100 100 ../sysdeps/x86_64/multiarch/strchr.S: No such file or directory. Thread 1 (Thread 0x7fc96cad5880 (LWP 11201)): #0 __strchr_sse42 () at ../sysdeps/x86_64/multiarch/strchr.S:100 No locals. #1 0x00007fc96be43725 in err_fmt_fmt (msg=0x7fc96d1cf8d0 "Cannot find KDC for requested realm", code=-1765328230, err_fmt=<optimized out>) at kerrs.c:152 buf = {buftype = K5BUF_DYNAMIC, data = 0x7fc96d1cdb10, space = 128, len = 0} p = <optimized out> s = 0xdededededededede <Address 0xdededededededede out of bounds> #2 krb5_get_error_message (ctx=<optimized out>, code=code@entry=-1765328230) at kerrs.c:184 std = 0x7fc96d1cf8d0 "Cannot find KDC for requested realm" #3 0x00007fc96cb224e5 in sss_krb5_get_error_message (ctx=<optimized out>, ec=ec@entry=-1765328230) at src/util/sss_krb5.c:424 No locals. #4 0x00007fc96cb1fbb0 in prepare_response (rsp=<synthetic pointer>, kerr=-1765328230, expire_time=0, ccname=0x0, mem_ctx=0x7fc96d1cb390) at src/providers/ldap/ldap_child.c:553 ret = <optimized out> r = 0x7fc96d1cd8b0 krb5_msg = 0x0 Reviewed-by: Fabiano FidĂȘncio <fidencio@redhat.com>
-rw-r--r--src/providers/ldap/ldap_child.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
index ffcbc3985..3f88a28dc 100644
--- a/src/providers/ldap/ldap_child.c
+++ b/src/providers/ldap/ldap_child.c
@@ -276,7 +276,8 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
const char *keytab_name,
const krb5_deltat lifetime,
const char **ccname_out,
- time_t *expire_time_out)
+ time_t *expire_time_out,
+ char **_krb5_msg)
{
char *ccname;
char *ccname_dummy;
@@ -522,7 +523,14 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
*expire_time_out = my_creds.times.endtime - kdc_time_offset;
done:
- if (krberr != 0) KRB5_SYSLOG(krberr);
+ if (krberr != 0) {
+ const char *krb5_msg;
+
+ KRB5_SYSLOG(krberr);
+ krb5_msg = sss_krb5_get_error_message(context, krberr);
+ *_krb5_msg = talloc_strdup(memctx, krb5_msg);
+ sss_krb5_free_error_message(context, krb5_msg);
+ }
if (keytab) krb5_kt_close(context, keytab);
if (context) krb5_free_context(context);
talloc_free(tmp_ctx);
@@ -533,11 +541,11 @@ static int prepare_response(TALLOC_CTX *mem_ctx,
const char *ccname,
time_t expire_time,
krb5_error_code kerr,
+ char *krb5_msg,
struct response **rsp)
{
int ret;
struct response *r = NULL;
- const char *krb5_msg = NULL;
r = talloc_zero(mem_ctx, struct response);
if (!r) return ENOMEM;
@@ -550,15 +558,13 @@ static int prepare_response(TALLOC_CTX *mem_ctx,
if (kerr == 0) {
ret = pack_buffer(r, EOK, kerr, ccname, expire_time);
} else {
- krb5_msg = sss_krb5_get_error_message(krb5_error_ctx, kerr);
if (krb5_msg == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
- "sss_krb5_get_error_message failed.\n");
+ "Empty krb5 error message for non-zero kerr: %"PRIi32"\n",
+ kerr);
return ENOMEM;
}
-
ret = pack_buffer(r, EFAULT, kerr, krb5_msg, 0);
- sss_krb5_free_error_message(krb5_error_ctx, krb5_msg);
}
if (ret != EOK) {
@@ -605,6 +611,7 @@ int main(int argc, const char *argv[])
uint8_t *buf = NULL;
ssize_t len = 0;
const char *ccname = NULL;
+ char *krb5_msg = NULL;
time_t expire_time = 0;
struct input_buffer *ibuf = NULL;
struct response *resp = NULL;
@@ -721,13 +728,14 @@ int main(int argc, const char *argv[])
kerr = ldap_child_get_tgt_sync(main_ctx, ibuf->context,
ibuf->realm_str, ibuf->princ_str,
ibuf->keytab_name, ibuf->lifetime,
- &ccname, &expire_time);
+ &ccname, &expire_time, &krb5_msg);
if (kerr != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "ldap_child_get_tgt_sync failed.\n");
/* Do not return, must report failure */
}
- ret = prepare_response(main_ctx, ccname, expire_time, kerr, &resp);
+ ret = prepare_response(main_ctx, ccname, expire_time, kerr, krb5_msg,
+ &resp);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "prepare_response failed. [%d][%s].\n",
ret, strerror(ret));