parent
13a890c182
commit
6b353f5ca3
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
|||||||
|
From 347079e258e6ded99d8dda162cafaf133b982ab9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Greg Hudson <ghudson@mit.edu>
|
||||||
|
Date: Fri, 27 Oct 2023 00:44:53 -0400
|
||||||
|
Subject: [PATCH] End connection on KDC_ERR_SVC_UNAVAILABLE
|
||||||
|
|
||||||
|
In sendto_kdc.c:service_fds(), if a message handler indicates that a
|
||||||
|
message should be discarded, kill the connection so we don't continue
|
||||||
|
waiting on it for more data.
|
||||||
|
|
||||||
|
ticket: 7899
|
||||||
|
(cherry picked from commit ca80f64c786341d5871ae1de18142e62af64f7b9)
|
||||||
|
---
|
||||||
|
src/lib/krb5/os/sendto_kdc.c | 5 ++++-
|
||||||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
index 0f4bf23a95..262edf09b4 100644
|
||||||
|
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
@@ -1440,7 +1440,10 @@ service_fds(krb5_context context, struct select_state *selstate,
|
||||||
|
if (msg_handler != NULL) {
|
||||||
|
krb5_data reply = make_data(state->in.buf, state->in.pos);
|
||||||
|
|
||||||
|
- stop = (msg_handler(context, &reply, msg_handler_data) != 0);
|
||||||
|
+ if (!msg_handler(context, &reply, msg_handler_data)) {
|
||||||
|
+ kill_conn(context, state, selstate);
|
||||||
|
+ stop = 0;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stop) {
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
@ -0,0 +1,226 @@
|
|||||||
|
From d71ebaef4619d6281551793c297caed7a025a909 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Greg Hudson <ghudson@mit.edu>
|
||||||
|
Date: Thu, 26 Oct 2023 14:20:34 -0400
|
||||||
|
Subject: [PATCH] Add request_timeout configuration parameter
|
||||||
|
|
||||||
|
Add a parameter to limit the total amount of time taken for a KDC or
|
||||||
|
password change request.
|
||||||
|
|
||||||
|
ticket: 9106 (new)
|
||||||
|
(cherry picked from commit 802318cda963456b3ed7856c836e89da891483be)
|
||||||
|
---
|
||||||
|
doc/admin/conf_files/krb5_conf.rst | 9 ++++++
|
||||||
|
src/include/k5-int.h | 2 ++
|
||||||
|
src/lib/krb5/krb/init_ctx.c | 14 +++++++-
|
||||||
|
src/lib/krb5/os/sendto_kdc.c | 51 ++++++++++++++++++++----------
|
||||||
|
4 files changed, 58 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||||
|
index a33711d918..65fb592d98 100644
|
||||||
|
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||||
|
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||||
|
@@ -356,6 +356,15 @@ The libdefaults section may contain any of the following relations:
|
||||||
|
(:ref:`duration` string.) Sets the default renewable lifetime
|
||||||
|
for initial ticket requests. The default value is 0.
|
||||||
|
|
||||||
|
+**request_timeout**
|
||||||
|
+ (:ref:`duration` string.) Sets the maximum total time for KDC or
|
||||||
|
+ password change requests. This timeout does not affect the
|
||||||
|
+ intervals between requests, so setting a low timeout may result in
|
||||||
|
+ fewer requests being attempted and/or some servers not being
|
||||||
|
+ contacted. A value of 0 indicates no specific maximum, in which
|
||||||
|
+ case requests will time out if no server responds after several
|
||||||
|
+ tries. The default value is 0. (New in release 1.22.)
|
||||||
|
+
|
||||||
|
**spake_preauth_groups**
|
||||||
|
A whitespace or comma-separated list of words which specifies the
|
||||||
|
groups allowed for SPAKE preauthentication. The possible values
|
||||||
|
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
|
||||||
|
index b3e07945c1..69d6a6f569 100644
|
||||||
|
--- a/src/include/k5-int.h
|
||||||
|
+++ b/src/include/k5-int.h
|
||||||
|
@@ -296,6 +296,7 @@ typedef unsigned char u_char;
|
||||||
|
#define KRB5_CONF_SPAKE_PREAUTH_INDICATOR "spake_preauth_indicator"
|
||||||
|
#define KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE "spake_preauth_kdc_challenge"
|
||||||
|
#define KRB5_CONF_SPAKE_PREAUTH_GROUPS "spake_preauth_groups"
|
||||||
|
+#define KRB5_CONF_REQUEST_TIMEOUT "request_timeout"
|
||||||
|
#define KRB5_CONF_TICKET_LIFETIME "ticket_lifetime"
|
||||||
|
#define KRB5_CONF_UDP_PREFERENCE_LIMIT "udp_preference_limit"
|
||||||
|
#define KRB5_CONF_UNLOCKITER "unlockiter"
|
||||||
|
@@ -1200,6 +1201,7 @@ struct _krb5_context {
|
||||||
|
kdb5_dal_handle *dal_handle;
|
||||||
|
/* allowable clock skew */
|
||||||
|
krb5_deltat clockskew;
|
||||||
|
+ krb5_deltat req_timeout;
|
||||||
|
krb5_flags kdc_default_options;
|
||||||
|
krb5_flags library_options;
|
||||||
|
krb5_boolean profile_secure;
|
||||||
|
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
|
||||||
|
index 2b5abcd817..582a2945ff 100644
|
||||||
|
--- a/src/lib/krb5/krb/init_ctx.c
|
||||||
|
+++ b/src/lib/krb5/krb/init_ctx.c
|
||||||
|
@@ -157,7 +157,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||||
|
krb5_context ctx = 0;
|
||||||
|
krb5_error_code retval;
|
||||||
|
int tmp;
|
||||||
|
- char *plugin_dir = NULL;
|
||||||
|
+ char *plugin_dir = NULL, *timeout_str = NULL;
|
||||||
|
|
||||||
|
/* Verify some assumptions. If the assumptions hold and the
|
||||||
|
compiler is optimizing, this should result in no code being
|
||||||
|
@@ -240,6 +240,17 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||||
|
get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp);
|
||||||
|
ctx->clockskew = tmp;
|
||||||
|
|
||||||
|
+ retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS,
|
||||||
|
+ KRB5_CONF_REQUEST_TIMEOUT, NULL, NULL,
|
||||||
|
+ &timeout_str);
|
||||||
|
+ if (retval)
|
||||||
|
+ goto cleanup;
|
||||||
|
+ if (timeout_str != NULL) {
|
||||||
|
+ retval = krb5_string_to_deltat(timeout_str, &ctx->req_timeout);
|
||||||
|
+ if (retval)
|
||||||
|
+ goto cleanup;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK,
|
||||||
|
&tmp);
|
||||||
|
ctx->kdc_default_options = tmp;
|
||||||
|
@@ -281,6 +292,7 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
profile_release_string(plugin_dir);
|
||||||
|
+ profile_release_string(timeout_str);
|
||||||
|
krb5_free_context(ctx);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
index 262edf09b4..98247a1089 100644
|
||||||
|
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
@@ -1395,34 +1395,41 @@ get_endtime(time_ms endtime, struct conn_state *conns)
|
||||||
|
|
||||||
|
static krb5_boolean
|
||||||
|
service_fds(krb5_context context, struct select_state *selstate,
|
||||||
|
- time_ms interval, struct conn_state *conns,
|
||||||
|
+ time_ms interval, time_ms timeout, struct conn_state *conns,
|
||||||
|
struct select_state *seltemp, const krb5_data *realm,
|
||||||
|
int (*msg_handler)(krb5_context, const krb5_data *, void *),
|
||||||
|
void *msg_handler_data, struct conn_state **winner_out)
|
||||||
|
{
|
||||||
|
int e, selret = 0;
|
||||||
|
- time_ms endtime;
|
||||||
|
+ time_ms curtime, interval_end, endtime;
|
||||||
|
struct conn_state *state;
|
||||||
|
|
||||||
|
*winner_out = NULL;
|
||||||
|
|
||||||
|
- e = get_curtime_ms(&endtime);
|
||||||
|
+ e = get_curtime_ms(&curtime);
|
||||||
|
if (e)
|
||||||
|
return TRUE;
|
||||||
|
- endtime += interval;
|
||||||
|
+ interval_end = curtime + interval;
|
||||||
|
|
||||||
|
e = 0;
|
||||||
|
while (selstate->nfds > 0) {
|
||||||
|
- e = cm_select_or_poll(selstate, get_endtime(endtime, conns),
|
||||||
|
- seltemp, &selret);
|
||||||
|
+ endtime = get_endtime(interval_end, conns);
|
||||||
|
+ /* Don't wait longer than the whole request should last. */
|
||||||
|
+ if (timeout && endtime > timeout)
|
||||||
|
+ endtime = timeout;
|
||||||
|
+ e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
|
||||||
|
if (e == EINTR)
|
||||||
|
continue;
|
||||||
|
if (e != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
- if (selret == 0)
|
||||||
|
- /* Timeout, return to caller. */
|
||||||
|
+ if (selret == 0) {
|
||||||
|
+ /* We timed out. Stop if we hit the overall request timeout. */
|
||||||
|
+ if (timeout && (get_curtime_ms(&curtime) || curtime >= timeout))
|
||||||
|
+ return TRUE;
|
||||||
|
+ /* Otherwise return to the caller to send the next request. */
|
||||||
|
return FALSE;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Got something on a socket, process it. */
|
||||||
|
for (state = conns; state != NULL; state = state->next) {
|
||||||
|
@@ -1495,7 +1502,7 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||||
|
void *msg_handler_data)
|
||||||
|
{
|
||||||
|
int pass;
|
||||||
|
- time_ms delay;
|
||||||
|
+ time_ms delay, timeout = 0;
|
||||||
|
krb5_error_code retval;
|
||||||
|
struct conn_state *conns = NULL, *state, **tailptr, *next, *winner;
|
||||||
|
size_t s;
|
||||||
|
@@ -1505,6 +1512,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||||
|
|
||||||
|
*reply = empty_data();
|
||||||
|
|
||||||
|
+ if (context->req_timeout) {
|
||||||
|
+ retval = get_curtime_ms(&timeout);
|
||||||
|
+ if (retval)
|
||||||
|
+ return retval;
|
||||||
|
+ timeout += 1000 * context->req_timeout;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* One for use here, listing all our fds in use, and one for
|
||||||
|
* temporary use in service_fds, for the fds of interest. */
|
||||||
|
sel_state = malloc(2 * sizeof(*sel_state));
|
||||||
|
@@ -1532,8 +1546,9 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||||
|
if (maybe_send(context, state, message, sel_state, realm,
|
||||||
|
callback_info))
|
||||||
|
continue;
|
||||||
|
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||||
|
- realm, msg_handler, msg_handler_data, &winner);
|
||||||
|
+ done = service_fds(context, sel_state, 1000, timeout, conns,
|
||||||
|
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||||
|
+ &winner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1545,13 +1560,13 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||||
|
if (maybe_send(context, state, message, sel_state, realm,
|
||||||
|
callback_info))
|
||||||
|
continue;
|
||||||
|
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||||
|
+ done = service_fds(context, sel_state, 1000, timeout, conns, seltemp,
|
||||||
|
realm, msg_handler, msg_handler_data, &winner);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for two seconds at the end of the first pass. */
|
||||||
|
if (!done) {
|
||||||
|
- done = service_fds(context, sel_state, 2000, conns, seltemp,
|
||||||
|
+ done = service_fds(context, sel_state, 2000, timeout, conns, seltemp,
|
||||||
|
realm, msg_handler, msg_handler_data, &winner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1562,15 +1577,17 @@ k5_sendto(krb5_context context, const krb5_data *message,
|
||||||
|
if (maybe_send(context, state, message, sel_state, realm,
|
||||||
|
callback_info))
|
||||||
|
continue;
|
||||||
|
- done = service_fds(context, sel_state, 1000, conns, seltemp,
|
||||||
|
- realm, msg_handler, msg_handler_data, &winner);
|
||||||
|
+ done = service_fds(context, sel_state, 1000, timeout, conns,
|
||||||
|
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||||
|
+ &winner);
|
||||||
|
if (sel_state->nfds == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Wait for the delay backoff at the end of this pass. */
|
||||||
|
if (!done) {
|
||||||
|
- done = service_fds(context, sel_state, delay, conns, seltemp,
|
||||||
|
- realm, msg_handler, msg_handler_data, &winner);
|
||||||
|
+ done = service_fds(context, sel_state, delay, timeout, conns,
|
||||||
|
+ seltemp, realm, msg_handler, msg_handler_data,
|
||||||
|
+ &winner);
|
||||||
|
}
|
||||||
|
if (sel_state->nfds == 0)
|
||||||
|
break;
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
@ -0,0 +1,138 @@
|
|||||||
|
From 0bf66d2018db92c95d3bab54a62f6a3265ceb158 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Greg Hudson <ghudson@mit.edu>
|
||||||
|
Date: Thu, 26 Oct 2023 16:26:42 -0400
|
||||||
|
Subject: [PATCH] Wait indefinitely on KDC TCP connections
|
||||||
|
|
||||||
|
When making a KDC or password change request, wait indefinitely
|
||||||
|
(limited only by request_timeout if set) once a KDC has accepted a TCP
|
||||||
|
connection.
|
||||||
|
|
||||||
|
ticket: 9105 (new)
|
||||||
|
(cherry picked from commit 6436a3808061da787a43c6810f5f0370cdfb6e36)
|
||||||
|
---
|
||||||
|
doc/admin/conf_files/krb5_conf.rst | 2 +-
|
||||||
|
src/lib/krb5/os/sendto_kdc.c | 50 ++++++++++++++++--------------
|
||||||
|
2 files changed, 27 insertions(+), 25 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
|
||||||
|
index 65fb592d98..b7284c47df 100644
|
||||||
|
--- a/doc/admin/conf_files/krb5_conf.rst
|
||||||
|
+++ b/doc/admin/conf_files/krb5_conf.rst
|
||||||
|
@@ -357,7 +357,7 @@ The libdefaults section may contain any of the following relations:
|
||||||
|
for initial ticket requests. The default value is 0.
|
||||||
|
|
||||||
|
**request_timeout**
|
||||||
|
- (:ref:`duration` string.) Sets the maximum total time for KDC or
|
||||||
|
+ (:ref:`duration` string.) Sets the maximum total time for KDC and
|
||||||
|
password change requests. This timeout does not affect the
|
||||||
|
intervals between requests, so setting a low timeout may result in
|
||||||
|
fewer requests being attempted and/or some servers not being
|
||||||
|
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
index 98247a1089..924f5b2d26 100644
|
||||||
|
--- a/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
+++ b/src/lib/krb5/os/sendto_kdc.c
|
||||||
|
@@ -134,7 +134,6 @@ struct conn_state {
|
||||||
|
krb5_data callback_buffer;
|
||||||
|
size_t server_index;
|
||||||
|
struct conn_state *next;
|
||||||
|
- time_ms endtime;
|
||||||
|
krb5_boolean defer;
|
||||||
|
struct {
|
||||||
|
const char *uri_path;
|
||||||
|
@@ -344,15 +343,19 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
|
||||||
|
struct select_state *out, int *sret)
|
||||||
|
{
|
||||||
|
#ifndef USE_POLL
|
||||||
|
- struct timeval tv;
|
||||||
|
+ struct timeval tv, *tvp;
|
||||||
|
#endif
|
||||||
|
krb5_error_code retval;
|
||||||
|
time_ms curtime, interval;
|
||||||
|
|
||||||
|
- retval = get_curtime_ms(&curtime);
|
||||||
|
- if (retval != 0)
|
||||||
|
- return retval;
|
||||||
|
- interval = (curtime < endtime) ? endtime - curtime : 0;
|
||||||
|
+ if (endtime != 0) {
|
||||||
|
+ retval = get_curtime_ms(&curtime);
|
||||||
|
+ if (retval != 0)
|
||||||
|
+ return retval;
|
||||||
|
+ interval = (curtime < endtime) ? endtime - curtime : 0;
|
||||||
|
+ } else {
|
||||||
|
+ interval = -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* We don't need a separate copy of the selstate for poll, but use one for
|
||||||
|
* consistency with how we use select. */
|
||||||
|
@@ -361,9 +364,14 @@ cm_select_or_poll(const struct select_state *in, time_ms endtime,
|
||||||
|
#ifdef USE_POLL
|
||||||
|
*sret = poll(out->fds, out->nfds, interval);
|
||||||
|
#else
|
||||||
|
- tv.tv_sec = interval / 1000;
|
||||||
|
- tv.tv_usec = interval % 1000 * 1000;
|
||||||
|
- *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, &tv);
|
||||||
|
+ if (interval != -1) {
|
||||||
|
+ tv.tv_sec = interval / 1000;
|
||||||
|
+ tv.tv_usec = interval % 1000 * 1000;
|
||||||
|
+ tvp = &tv;
|
||||||
|
+ } else {
|
||||||
|
+ tvp = NULL;
|
||||||
|
+ }
|
||||||
|
+ *sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, tvp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (*sret < 0) ? SOCKET_ERRNO : 0;
|
||||||
|
@@ -1099,11 +1107,6 @@ service_tcp_connect(krb5_context context, const krb5_data *realm,
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->state = WRITING;
|
||||||
|
-
|
||||||
|
- /* Record this connection's timeout for service_fds. */
|
||||||
|
- if (get_curtime_ms(&conn->endtime) == 0)
|
||||||
|
- conn->endtime += 10000;
|
||||||
|
-
|
||||||
|
return conn->service_write(context, realm, conn, selstate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1378,19 +1381,18 @@ kill_conn:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Return the maximum of endtime and the endtime fields of all currently active
|
||||||
|
- * TCP connections. */
|
||||||
|
-static time_ms
|
||||||
|
-get_endtime(time_ms endtime, struct conn_state *conns)
|
||||||
|
+/* Return true if conns contains any states with connected TCP sockets. */
|
||||||
|
+static krb5_boolean
|
||||||
|
+any_tcp_connections(struct conn_state *conns)
|
||||||
|
{
|
||||||
|
struct conn_state *state;
|
||||||
|
|
||||||
|
for (state = conns; state != NULL; state = state->next) {
|
||||||
|
- if ((state->state == READING || state->state == WRITING) &&
|
||||||
|
- state->endtime > endtime)
|
||||||
|
- endtime = state->endtime;
|
||||||
|
+ if (state->addr.transport != UDP &&
|
||||||
|
+ (state->state == READING || state->state == WRITING))
|
||||||
|
+ return TRUE;
|
||||||
|
}
|
||||||
|
- return endtime;
|
||||||
|
+ return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static krb5_boolean
|
||||||
|
@@ -1413,9 +1415,9 @@ service_fds(krb5_context context, struct select_state *selstate,
|
||||||
|
|
||||||
|
e = 0;
|
||||||
|
while (selstate->nfds > 0) {
|
||||||
|
- endtime = get_endtime(interval_end, conns);
|
||||||
|
+ endtime = any_tcp_connections(conns) ? 0 : interval_end;
|
||||||
|
/* Don't wait longer than the whole request should last. */
|
||||||
|
- if (timeout && endtime > timeout)
|
||||||
|
+ if (timeout && (!endtime || endtime > timeout))
|
||||||
|
endtime = timeout;
|
||||||
|
e = cm_select_or_poll(selstate, endtime, seltemp, &selret);
|
||||||
|
if (e == EINTR)
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
@ -0,0 +1,381 @@
|
|||||||
|
From 0cb2e6c09fee3863c16664bf180e773f662cd313 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Steffen=20Kie=C3=9F?=
|
||||||
|
<steffen.kiess@cis.iti.uni-stuttgart.de>
|
||||||
|
Date: Tue, 13 Feb 2024 18:39:27 +0100
|
||||||
|
Subject: [PATCH] Avoid strict-prototype compiler errors
|
||||||
|
|
||||||
|
Commit 4b9d7f7c107f01a61600fddcd8cde3812d0366a2 added the
|
||||||
|
-Werror=strict-prototypes parameter to the build process, but left
|
||||||
|
behind 28 function definitions using "()" instead of "(void)". Most
|
||||||
|
of these definitions could not cause compiler errors for various
|
||||||
|
reasons (such as an accompanying prototype), but a few could cause
|
||||||
|
errors in gcc depending on the build configuration.
|
||||||
|
|
||||||
|
For consistency and safety, add "(void)" to all 28 definitions.
|
||||||
|
|
||||||
|
[ghudson@mit.edu: rewrote commit message]
|
||||||
|
|
||||||
|
(cherry picked from commit 3ae9244cd021a75eba909d872a92c25db490714d)
|
||||||
|
---
|
||||||
|
src/clients/kcpytkt/kcpytkt.c | 2 +-
|
||||||
|
src/clients/kdeltkt/kdeltkt.c | 2 +-
|
||||||
|
src/clients/kinit/kinit.c | 4 ++--
|
||||||
|
src/clients/kinit/kinit_kdb.c | 2 +-
|
||||||
|
src/clients/klist/klist.c | 4 ++--
|
||||||
|
src/kadmin/cli/kadmin.c | 2 +-
|
||||||
|
src/kadmin/dbutil/kdb5_util.c | 4 ++--
|
||||||
|
src/kdc/main.c | 2 +-
|
||||||
|
src/kprop/kpropd.c | 4 ++--
|
||||||
|
src/lib/crypto/builtin/enc_provider/aes.c | 2 +-
|
||||||
|
src/lib/crypto/openssl/hmac.c | 2 +-
|
||||||
|
src/lib/krb5/ccache/t_memory.c | 4 ++--
|
||||||
|
src/lib/krb5/ccache/t_stdio.c | 4 ++--
|
||||||
|
src/plugins/kdb/db2/libdb2/btree/bt_debug.c | 2 +-
|
||||||
|
src/plugins/kdb/db2/libdb2/btree/bt_open.c | 4 ++--
|
||||||
|
src/plugins/kdb/db2/libdb2/hash/dbm.c | 2 +-
|
||||||
|
src/plugins/kdb/db2/libdb2/test/btree.tests/main.c | 2 +-
|
||||||
|
src/plugins/kdb/db2/libdb2/test/dbtest.c | 2 +-
|
||||||
|
src/plugins/preauth/pkinit/pkinit_crypto_openssl.c | 2 +-
|
||||||
|
src/plugins/tls/k5tls/openssl.c | 2 +-
|
||||||
|
src/tests/asn.1/make-vectors.c | 2 +-
|
||||||
|
21 files changed, 28 insertions(+), 28 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/clients/kcpytkt/kcpytkt.c b/src/clients/kcpytkt/kcpytkt.c
|
||||||
|
index 0b8802261e..f1d50e5de0 100644
|
||||||
|
--- a/src/clients/kcpytkt/kcpytkt.c
|
||||||
|
+++ b/src/clients/kcpytkt/kcpytkt.c
|
||||||
|
@@ -10,7 +10,7 @@ static char *prog;
|
||||||
|
static int quiet = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
-xusage()
|
||||||
|
+xusage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "xusage: %s [-c from_ccache] [-e etype] [-f flags] "
|
||||||
|
"dest_ccache service1 service2 ...\n", prog);
|
||||||
|
diff --git a/src/clients/kdeltkt/kdeltkt.c b/src/clients/kdeltkt/kdeltkt.c
|
||||||
|
index cd0bf637db..66a32a8bd3 100644
|
||||||
|
--- a/src/clients/kdeltkt/kdeltkt.c
|
||||||
|
+++ b/src/clients/kdeltkt/kdeltkt.c
|
||||||
|
@@ -10,7 +10,7 @@ static char *prog;
|
||||||
|
static int quiet = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
-xusage()
|
||||||
|
+xusage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "xusage: %s [-c ccache] [-e etype] [-f flags] service1 "
|
||||||
|
"service2 ...\n", prog);
|
||||||
|
diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
|
||||||
|
index 7a33ffae59..b27b723f2d 100644
|
||||||
|
--- a/src/clients/kinit/kinit.c
|
||||||
|
+++ b/src/clients/kinit/kinit.c
|
||||||
|
@@ -55,7 +55,7 @@ get_name_from_os(void)
|
||||||
|
#else /* HAVE_PWD_H */
|
||||||
|
#ifdef _WIN32
|
||||||
|
static char *
|
||||||
|
-get_name_from_os()
|
||||||
|
+get_name_from_os(void)
|
||||||
|
{
|
||||||
|
static char name[1024];
|
||||||
|
DWORD name_size = sizeof(name);
|
||||||
|
@@ -69,7 +69,7 @@ get_name_from_os()
|
||||||
|
}
|
||||||
|
#else /* _WIN32 */
|
||||||
|
static char *
|
||||||
|
-get_name_from_os()
|
||||||
|
+get_name_from_os(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
diff --git a/src/clients/kinit/kinit_kdb.c b/src/clients/kinit/kinit_kdb.c
|
||||||
|
index fbd174bf0c..4e7cd50169 100644
|
||||||
|
--- a/src/clients/kinit/kinit_kdb.c
|
||||||
|
+++ b/src/clients/kinit/kinit_kdb.c
|
||||||
|
@@ -69,7 +69,7 @@ kinit_kdb_init(krb5_context *pcontext, char *realm)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
-kinit_kdb_fini()
|
||||||
|
+kinit_kdb_fini(void)
|
||||||
|
{
|
||||||
|
kadm5_destroy(server_handle);
|
||||||
|
}
|
||||||
|
diff --git a/src/clients/klist/klist.c b/src/clients/klist/klist.c
|
||||||
|
index c797b1698f..27cf0ee11b 100644
|
||||||
|
--- a/src/clients/klist/klist.c
|
||||||
|
+++ b/src/clients/klist/klist.c
|
||||||
|
@@ -359,7 +359,7 @@ do_keytab(const char *name)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-list_all_ccaches()
|
||||||
|
+list_all_ccaches(void)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
krb5_ccache cache;
|
||||||
|
@@ -451,7 +451,7 @@ show_all_ccaches(void)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-do_ccache()
|
||||||
|
+do_ccache(void)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
krb5_ccache cache;
|
||||||
|
diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c
|
||||||
|
index 23b64b0f58..c1256f7708 100644
|
||||||
|
--- a/src/kadmin/cli/kadmin.c
|
||||||
|
+++ b/src/kadmin/cli/kadmin.c
|
||||||
|
@@ -607,7 +607,7 @@ kadmin_startup(int argc, char *argv[], char **request_out, char ***args_out)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-quit()
|
||||||
|
+quit(void)
|
||||||
|
{
|
||||||
|
kadm5_ret_t retval;
|
||||||
|
|
||||||
|
diff --git a/src/kadmin/dbutil/kdb5_util.c b/src/kadmin/dbutil/kdb5_util.c
|
||||||
|
index 55d529fa4c..b9b61e3f91 100644
|
||||||
|
--- a/src/kadmin/dbutil/kdb5_util.c
|
||||||
|
+++ b/src/kadmin/dbutil/kdb5_util.c
|
||||||
|
@@ -367,7 +367,7 @@ main(int argc, char *argv[])
|
||||||
|
* program is run).
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
-open_db_and_mkey()
|
||||||
|
+open_db_and_mkey(void)
|
||||||
|
{
|
||||||
|
krb5_error_code retval;
|
||||||
|
krb5_data scratch, pwd, seed;
|
||||||
|
@@ -489,7 +489,7 @@ open_db_and_mkey()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
-quit()
|
||||||
|
+quit(void)
|
||||||
|
{
|
||||||
|
krb5_error_code retval;
|
||||||
|
static krb5_boolean finished = 0;
|
||||||
|
diff --git a/src/kdc/main.c b/src/kdc/main.c
|
||||||
|
index b43fe9a082..2dfad5673f 100644
|
||||||
|
--- a/src/kdc/main.c
|
||||||
|
+++ b/src/kdc/main.c
|
||||||
|
@@ -854,7 +854,7 @@ write_pid_file(const char *path)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-finish_realms()
|
||||||
|
+finish_realms(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
|
||||||
|
index f883ae2df8..fbb8e37ae9 100644
|
||||||
|
--- a/src/kprop/kpropd.c
|
||||||
|
+++ b/src/kprop/kpropd.c
|
||||||
|
@@ -376,7 +376,7 @@ get_wildcard_addr(struct addrinfo **res)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-do_standalone()
|
||||||
|
+do_standalone(void)
|
||||||
|
{
|
||||||
|
struct sockaddr_in frominet;
|
||||||
|
struct addrinfo *res;
|
||||||
|
@@ -639,7 +639,7 @@ full_resync(CLIENT *clnt)
|
||||||
|
* Returns non-zero on failure due to errors.
|
||||||
|
*/
|
||||||
|
krb5_error_code
|
||||||
|
-do_iprop()
|
||||||
|
+do_iprop(void)
|
||||||
|
{
|
||||||
|
kadm5_ret_t retval;
|
||||||
|
krb5_principal iprop_svc_principal = NULL;
|
||||||
|
diff --git a/src/lib/crypto/builtin/enc_provider/aes.c b/src/lib/crypto/builtin/enc_provider/aes.c
|
||||||
|
index 7fa9449797..39e2a84005 100644
|
||||||
|
--- a/src/lib/crypto/builtin/enc_provider/aes.c
|
||||||
|
+++ b/src/lib/crypto/builtin/enc_provider/aes.c
|
||||||
|
@@ -69,7 +69,7 @@ void k5_iEnc256_CBC(struct aes_data *data);
|
||||||
|
void k5_iDec256_CBC(struct aes_data *data);
|
||||||
|
|
||||||
|
static krb5_boolean
|
||||||
|
-aesni_supported_by_cpu()
|
||||||
|
+aesni_supported_by_cpu(void)
|
||||||
|
{
|
||||||
|
unsigned int a, b, c, d;
|
||||||
|
|
||||||
|
diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
|
||||||
|
index 25a419d73a..32dec3022e 100644
|
||||||
|
--- a/src/lib/crypto/openssl/hmac.c
|
||||||
|
+++ b/src/lib/crypto/openssl/hmac.c
|
||||||
|
@@ -71,7 +71,7 @@
|
||||||
|
|
||||||
|
#define HMAC_CTX_new compat_hmac_ctx_new
|
||||||
|
static HMAC_CTX *
|
||||||
|
-compat_hmac_ctx_new()
|
||||||
|
+compat_hmac_ctx_new(void)
|
||||||
|
{
|
||||||
|
HMAC_CTX *ctx;
|
||||||
|
|
||||||
|
diff --git a/src/lib/krb5/ccache/t_memory.c b/src/lib/krb5/ccache/t_memory.c
|
||||||
|
index 6d103a00d1..0f94e823cb 100644
|
||||||
|
--- a/src/lib/krb5/ccache/t_memory.c
|
||||||
|
+++ b/src/lib/krb5/ccache/t_memory.c
|
||||||
|
@@ -85,7 +85,7 @@ krb5_creds test_creds = {
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
-init_test_cred()
|
||||||
|
+init_test_cred(void)
|
||||||
|
{
|
||||||
|
test_creds.client = (krb5_principal) malloc(sizeof(krb5_data *)*3);
|
||||||
|
test_creds.client[0] = &client1;
|
||||||
|
@@ -104,7 +104,7 @@ init_test_cred()
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
-mcc_test()
|
||||||
|
+mcc_test(void)
|
||||||
|
{
|
||||||
|
krb5_ccache id;
|
||||||
|
krb5_creds creds;
|
||||||
|
diff --git a/src/lib/krb5/ccache/t_stdio.c b/src/lib/krb5/ccache/t_stdio.c
|
||||||
|
index 15185e301c..06a9c2dea1 100644
|
||||||
|
--- a/src/lib/krb5/ccache/t_stdio.c
|
||||||
|
+++ b/src/lib/krb5/ccache/t_stdio.c
|
||||||
|
@@ -98,7 +98,7 @@ krb5_creds test_creds = {
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
-init_test_cred()
|
||||||
|
+init_test_cred(void)
|
||||||
|
{
|
||||||
|
test_creds.client = (krb5_principal) malloc(sizeof(krb5_data *)*3);
|
||||||
|
test_creds.client[0] = &client1;
|
||||||
|
@@ -118,7 +118,7 @@ init_test_cred()
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
void
|
||||||
|
-scc_test()
|
||||||
|
+scc_test(void)
|
||||||
|
{
|
||||||
|
krb5_ccache id;
|
||||||
|
krb5_creds creds;
|
||||||
|
diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_debug.c b/src/plugins/kdb/db2/libdb2/btree/bt_debug.c
|
||||||
|
index bc71076a35..5a955e09be 100644
|
||||||
|
--- a/src/plugins/kdb/db2/libdb2/btree/bt_debug.c
|
||||||
|
+++ b/src/plugins/kdb/db2/libdb2/btree/bt_debug.c
|
||||||
|
@@ -56,7 +56,7 @@ static FILE *tracefp;
|
||||||
|
* initialize debugging.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
-__bt_dinit()
|
||||||
|
+__bt_dinit(void)
|
||||||
|
{
|
||||||
|
static int first = 1;
|
||||||
|
|
||||||
|
diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
|
||||||
|
index a2910422eb..ef7515c3d4 100644
|
||||||
|
--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c
|
||||||
|
+++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
|
||||||
|
@@ -391,7 +391,7 @@ nroot(BTREE *t)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-tmp()
|
||||||
|
+tmp(void)
|
||||||
|
{
|
||||||
|
#ifdef SIG_BLOCK
|
||||||
|
sigset_t set, oset;
|
||||||
|
@@ -438,7 +438,7 @@ tmp()
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-byteorder()
|
||||||
|
+byteorder(void)
|
||||||
|
{
|
||||||
|
u_int32_t x;
|
||||||
|
u_char *p;
|
||||||
|
diff --git a/src/plugins/kdb/db2/libdb2/hash/dbm.c b/src/plugins/kdb/db2/libdb2/hash/dbm.c
|
||||||
|
index 2dca256dc3..e643634433 100644
|
||||||
|
--- a/src/plugins/kdb/db2/libdb2/hash/dbm.c
|
||||||
|
+++ b/src/plugins/kdb/db2/libdb2/hash/dbm.c
|
||||||
|
@@ -143,7 +143,7 @@ kdb2_store(datum key, datum dat)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-no_open_db()
|
||||||
|
+no_open_db(void)
|
||||||
|
{
|
||||||
|
(void)fprintf(stderr, "dbm: no open database.\n");
|
||||||
|
}
|
||||||
|
diff --git a/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c b/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c
|
||||||
|
index 088f903231..eec843d4db 100644
|
||||||
|
--- a/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c
|
||||||
|
+++ b/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c
|
||||||
|
@@ -908,7 +908,7 @@ keydata(key, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
-usage()
|
||||||
|
+usage(void)
|
||||||
|
{
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"usage: %s [-bdluw] [-c cache] [-i file] [-p page] [file]\n",
|
||||||
|
diff --git a/src/plugins/kdb/db2/libdb2/test/dbtest.c b/src/plugins/kdb/db2/libdb2/test/dbtest.c
|
||||||
|
index 04bf34b90d..a2866b4412 100644
|
||||||
|
--- a/src/plugins/kdb/db2/libdb2/test/dbtest.c
|
||||||
|
+++ b/src/plugins/kdb/db2/libdb2/test/dbtest.c
|
||||||
|
@@ -792,7 +792,7 @@ xmalloc(char *text, size_t len)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
-usage()
|
||||||
|
+usage(void)
|
||||||
|
{
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n");
|
||||||
|
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
index 6d96499d77..af3fa9ee8b 100644
|
||||||
|
--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
+++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
|
||||||
|
@@ -3090,7 +3090,7 @@ cleanup:
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-pkinit_openssl_init()
|
||||||
|
+pkinit_openssl_init(void)
|
||||||
|
{
|
||||||
|
/* Initialize OpenSSL. */
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
diff --git a/src/plugins/tls/k5tls/openssl.c b/src/plugins/tls/k5tls/openssl.c
|
||||||
|
index 99fda7ffcd..aab67c01cb 100644
|
||||||
|
--- a/src/plugins/tls/k5tls/openssl.c
|
||||||
|
+++ b/src/plugins/tls/k5tls/openssl.c
|
||||||
|
@@ -49,7 +49,7 @@ static int ex_handle_id = -1;
|
||||||
|
MAKE_INIT_FUNCTION(init_openssl);
|
||||||
|
|
||||||
|
int
|
||||||
|
-init_openssl()
|
||||||
|
+init_openssl(void)
|
||||||
|
{
|
||||||
|
SSL_library_init();
|
||||||
|
SSL_load_error_strings();
|
||||||
|
diff --git a/src/tests/asn.1/make-vectors.c b/src/tests/asn.1/make-vectors.c
|
||||||
|
index 2fc85466bb..6f2b7dd021 100644
|
||||||
|
--- a/src/tests/asn.1/make-vectors.c
|
||||||
|
+++ b/src/tests/asn.1/make-vectors.c
|
||||||
|
@@ -224,7 +224,7 @@ printbuf(void)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-main()
|
||||||
|
+main(void)
|
||||||
|
{
|
||||||
|
/* Initialize values which can't use static initializers. */
|
||||||
|
asn_long2INTEGER(&otp_format, 2); /* Alphanumeric */
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From f54763bc90df9c76c69ee9a837cf856bcf93e633 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Greg Hudson <ghudson@mit.edu>
|
||||||
|
Date: Tue, 5 Mar 2024 17:38:49 -0500
|
||||||
|
Subject: [PATCH] Fix leak in KDC NDR encoding
|
||||||
|
|
||||||
|
If the KDC tries to encode a principal containing encode invalid UTF-8
|
||||||
|
sequences for inclusion in a PAC delegation info buffer, it will leak
|
||||||
|
a small amount of memory in enc_wchar_pointer() before failing. Fix
|
||||||
|
the leak.
|
||||||
|
|
||||||
|
ticket: 9115 (new)
|
||||||
|
tags: pullup
|
||||||
|
target_version: 1.21-next
|
||||||
|
|
||||||
|
(cherry picked from commit 7d0d85bf99caf60c0afd4dcf91b0c4c683b983fe)
|
||||||
|
---
|
||||||
|
src/kdc/ndr.c | 3 +--
|
||||||
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/kdc/ndr.c b/src/kdc/ndr.c
|
||||||
|
index 48395abe52..d438408ee2 100644
|
||||||
|
--- a/src/kdc/ndr.c
|
||||||
|
+++ b/src/kdc/ndr.c
|
||||||
|
@@ -96,14 +96,13 @@ enc_wchar_pointer(const char *utf8, struct encoded_wchars *encoded_out)
|
||||||
|
size_t utf16len, num_wchars;
|
||||||
|
uint8_t *utf16;
|
||||||
|
|
||||||
|
- k5_buf_init_dynamic(&b);
|
||||||
|
-
|
||||||
|
ret = k5_utf8_to_utf16le(utf8, &utf16, &utf16len);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
num_wchars = utf16len / 2;
|
||||||
|
|
||||||
|
+ k5_buf_init_dynamic(&b);
|
||||||
|
k5_buf_add_uint32_le(&b, num_wchars + 1);
|
||||||
|
k5_buf_add_uint32_le(&b, 0);
|
||||||
|
k5_buf_add_uint32_le(&b, num_wchars);
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
@ -0,0 +1,206 @@
|
|||||||
|
From d230c72573430803c569817a71b79be8656fa6c5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Greg Hudson <ghudson@mit.edu>
|
||||||
|
Date: Tue, 5 Mar 2024 19:53:07 -0500
|
||||||
|
Subject: [PATCH] Fix two unlikely memory leaks
|
||||||
|
|
||||||
|
In gss_krb5int_make_seal_token_v3(), one of the bounds checks (which
|
||||||
|
could probably never be triggered) leaks plain.data. Fix this leak
|
||||||
|
and use current practices for cleanup throughout the function.
|
||||||
|
|
||||||
|
In xmt_rmtcallres() (unused within the tree and likely elsewhere),
|
||||||
|
store port_ptr into crp->port_ptr as soon as it is allocated;
|
||||||
|
otherwise it could leak if the subsequent xdr_u_int32() operation
|
||||||
|
fails.
|
||||||
|
|
||||||
|
(cherry picked from commit c5f9c816107f70139de11b38aa02db2f1774ee0d)
|
||||||
|
---
|
||||||
|
src/lib/gssapi/krb5/k5sealv3.c | 56 +++++++++++++++-------------------
|
||||||
|
src/lib/rpc/pmap_rmt.c | 10 +++---
|
||||||
|
2 files changed, 29 insertions(+), 37 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c
|
||||||
|
index 3b4f8cb837..e881eee835 100644
|
||||||
|
--- a/src/lib/gssapi/krb5/k5sealv3.c
|
||||||
|
+++ b/src/lib/gssapi/krb5/k5sealv3.c
|
||||||
|
@@ -65,7 +65,7 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
int conf_req_flag, int toktype)
|
||||||
|
{
|
||||||
|
size_t bufsize = 16;
|
||||||
|
- unsigned char *outbuf = 0;
|
||||||
|
+ unsigned char *outbuf = NULL;
|
||||||
|
krb5_error_code err;
|
||||||
|
int key_usage;
|
||||||
|
unsigned char acceptor_flag;
|
||||||
|
@@ -75,9 +75,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
#endif
|
||||||
|
size_t ec;
|
||||||
|
unsigned short tok_id;
|
||||||
|
- krb5_checksum sum;
|
||||||
|
+ krb5_checksum sum = { 0 };
|
||||||
|
krb5_key key;
|
||||||
|
krb5_cksumtype cksumtype;
|
||||||
|
+ krb5_data plain = empty_data();
|
||||||
|
+
|
||||||
|
+ token->value = NULL;
|
||||||
|
+ token->length = 0;
|
||||||
|
|
||||||
|
acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR;
|
||||||
|
key_usage = (toktype == KG_TOK_WRAP_MSG
|
||||||
|
@@ -107,14 +111,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) {
|
||||||
|
- krb5_data plain;
|
||||||
|
krb5_enc_data cipher;
|
||||||
|
size_t ec_max;
|
||||||
|
size_t encrypt_size;
|
||||||
|
|
||||||
|
/* 300: Adds some slop. */
|
||||||
|
- if (SIZE_MAX - 300 < message->length)
|
||||||
|
- return ENOMEM;
|
||||||
|
+ if (SIZE_MAX - 300 < message->length) {
|
||||||
|
+ err = ENOMEM;
|
||||||
|
+ goto cleanup;
|
||||||
|
+ }
|
||||||
|
ec_max = SIZE_MAX - message->length - 300;
|
||||||
|
if (ec_max > 0xffff)
|
||||||
|
ec_max = 0xffff;
|
||||||
|
@@ -126,20 +131,20 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
#endif
|
||||||
|
err = alloc_data(&plain, message->length + 16 + ec);
|
||||||
|
if (err)
|
||||||
|
- return err;
|
||||||
|
+ goto cleanup;
|
||||||
|
|
||||||
|
/* Get size of ciphertext. */
|
||||||
|
encrypt_size = krb5_encrypt_size(plain.length, key->keyblock.enctype);
|
||||||
|
if (encrypt_size > SIZE_MAX / 2) {
|
||||||
|
err = ENOMEM;
|
||||||
|
- goto error;
|
||||||
|
+ goto cleanup;
|
||||||
|
}
|
||||||
|
bufsize = 16 + encrypt_size;
|
||||||
|
/* Allocate space for header plus encrypted data. */
|
||||||
|
outbuf = gssalloc_malloc(bufsize);
|
||||||
|
if (outbuf == NULL) {
|
||||||
|
- free(plain.data);
|
||||||
|
- return ENOMEM;
|
||||||
|
+ err = ENOMEM;
|
||||||
|
+ goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TOK_ID */
|
||||||
|
@@ -164,11 +169,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
cipher.ciphertext.length = bufsize - 16;
|
||||||
|
cipher.enctype = key->keyblock.enctype;
|
||||||
|
err = krb5_k_encrypt(context, key, key_usage, 0, &plain, &cipher);
|
||||||
|
- zap(plain.data, plain.length);
|
||||||
|
- free(plain.data);
|
||||||
|
- plain.data = 0;
|
||||||
|
if (err)
|
||||||
|
- goto error;
|
||||||
|
+ goto cleanup;
|
||||||
|
|
||||||
|
/* Now that we know we're returning a valid token.... */
|
||||||
|
ctx->seq_send++;
|
||||||
|
@@ -181,7 +183,6 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
/* If the rotate fails, don't worry about it. */
|
||||||
|
#endif
|
||||||
|
} else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) {
|
||||||
|
- krb5_data plain;
|
||||||
|
size_t cksumsize;
|
||||||
|
|
||||||
|
/* Here, message is the application-supplied data; message2 is
|
||||||
|
@@ -193,21 +194,19 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
wrap_with_checksum:
|
||||||
|
err = alloc_data(&plain, message->length + 16);
|
||||||
|
if (err)
|
||||||
|
- return err;
|
||||||
|
+ goto cleanup;
|
||||||
|
|
||||||
|
err = krb5_c_checksum_length(context, cksumtype, &cksumsize);
|
||||||
|
if (err)
|
||||||
|
- goto error;
|
||||||
|
+ goto cleanup;
|
||||||
|
|
||||||
|
assert(cksumsize <= 0xffff);
|
||||||
|
|
||||||
|
bufsize = 16 + message2->length + cksumsize;
|
||||||
|
outbuf = gssalloc_malloc(bufsize);
|
||||||
|
if (outbuf == NULL) {
|
||||||
|
- free(plain.data);
|
||||||
|
- plain.data = 0;
|
||||||
|
err = ENOMEM;
|
||||||
|
- goto error;
|
||||||
|
+ goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TOK_ID */
|
||||||
|
@@ -239,23 +238,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
if (message2->length)
|
||||||
|
memcpy(outbuf + 16, message2->value, message2->length);
|
||||||
|
|
||||||
|
- sum.contents = outbuf + 16 + message2->length;
|
||||||
|
- sum.length = cksumsize;
|
||||||
|
-
|
||||||
|
err = krb5_k_make_checksum(context, cksumtype, key,
|
||||||
|
key_usage, &plain, &sum);
|
||||||
|
- zap(plain.data, plain.length);
|
||||||
|
- free(plain.data);
|
||||||
|
- plain.data = 0;
|
||||||
|
if (err) {
|
||||||
|
zap(outbuf,bufsize);
|
||||||
|
- goto error;
|
||||||
|
+ goto cleanup;
|
||||||
|
}
|
||||||
|
if (sum.length != cksumsize)
|
||||||
|
abort();
|
||||||
|
memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize);
|
||||||
|
- krb5_free_checksum_contents(context, &sum);
|
||||||
|
- sum.contents = 0;
|
||||||
|
/* Now that we know we're actually generating the token... */
|
||||||
|
ctx->seq_send++;
|
||||||
|
|
||||||
|
@@ -285,12 +276,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context,
|
||||||
|
|
||||||
|
token->value = outbuf;
|
||||||
|
token->length = bufsize;
|
||||||
|
- return 0;
|
||||||
|
+ outbuf = NULL;
|
||||||
|
+ err = 0;
|
||||||
|
|
||||||
|
-error:
|
||||||
|
+cleanup:
|
||||||
|
+ krb5_free_checksum_contents(context, &sum);
|
||||||
|
+ zapfree(plain.data, plain.length);
|
||||||
|
gssalloc_free(outbuf);
|
||||||
|
- token->value = NULL;
|
||||||
|
- token->length = 0;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c
|
||||||
|
index 434e4eea65..f55ca46c60 100644
|
||||||
|
--- a/src/lib/rpc/pmap_rmt.c
|
||||||
|
+++ b/src/lib/rpc/pmap_rmt.c
|
||||||
|
@@ -161,12 +161,12 @@ xdr_rmtcallres(
|
||||||
|
caddr_t port_ptr;
|
||||||
|
|
||||||
|
port_ptr = (caddr_t)(void *)crp->port_ptr;
|
||||||
|
- if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
|
||||||
|
- (xdrproc_t)xdr_u_int32) &&
|
||||||
|
- xdr_u_int32(xdrs, &crp->resultslen)) {
|
||||||
|
- crp->port_ptr = (uint32_t *)(void *)port_ptr;
|
||||||
|
+ if (!xdr_reference(xdrs, &port_ptr, sizeof (uint32_t),
|
||||||
|
+ (xdrproc_t)xdr_u_int32))
|
||||||
|
+ return (FALSE);
|
||||||
|
+ crp->port_ptr = (uint32_t *)(void *)port_ptr;
|
||||||
|
+ if (xdr_u_int32(xdrs, &crp->resultslen))
|
||||||
|
return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
|
||||||
|
- }
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
@ -0,0 +1,535 @@
|
|||||||
|
From 28009fda028c489ae38902b2c513c4208889f043 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Greg Hudson <ghudson@mit.edu>
|
||||||
|
Date: Fri, 14 Jun 2024 10:56:12 -0400
|
||||||
|
Subject: [PATCH] Fix vulnerabilities in GSS message token handling
|
||||||
|
|
||||||
|
In gss_krb5int_unseal_token_v3() and gss_krb5int_unseal_v3_iov(),
|
||||||
|
verify the Extra Count field of CFX wrap tokens against the encrypted
|
||||||
|
header. Reported by Jacob Champion.
|
||||||
|
|
||||||
|
In gss_krb5int_unseal_token_v3(), check for a decrypted plaintext
|
||||||
|
length too short to contain the encrypted header and extra count
|
||||||
|
bytes. Reported by Jacob Champion.
|
||||||
|
|
||||||
|
In kg_unseal_iov_token(), separately track the header IOV length and
|
||||||
|
complete token length when parsing the token's ASN.1 wrapper. This
|
||||||
|
fix contains modified versions of functions from k5-der.h and
|
||||||
|
util_token.c; this duplication will be cleaned up in a future commit.
|
||||||
|
|
||||||
|
CVE-2024-37370:
|
||||||
|
|
||||||
|
In MIT krb5 release 1.3 and later, an attacker can modify the
|
||||||
|
plaintext Extra Count field of a confidential GSS krb5 wrap token,
|
||||||
|
causing the unwrapped token to appear truncated to the application.
|
||||||
|
|
||||||
|
CVE-2024-37371:
|
||||||
|
|
||||||
|
In MIT krb5 release 1.3 and later, an attacker can cause invalid
|
||||||
|
memory reads by sending message tokens with invalid length fields.
|
||||||
|
|
||||||
|
ticket: 9128 (new)
|
||||||
|
tags: pullup
|
||||||
|
target_version: 1.21-next
|
||||||
|
|
||||||
|
(cherry picked from commit b0a2f8a5365f2eec3e27d78907de9f9d2c80505a)
|
||||||
|
---
|
||||||
|
src/lib/gssapi/krb5/k5sealv3.c | 5 +
|
||||||
|
src/lib/gssapi/krb5/k5sealv3iov.c | 3 +-
|
||||||
|
src/lib/gssapi/krb5/k5unsealiov.c | 80 +++++++++-
|
||||||
|
src/tests/gssapi/t_invalid.c | 233 +++++++++++++++++++++++++-----
|
||||||
|
4 files changed, 275 insertions(+), 46 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c
|
||||||
|
index e881eee835..d3210c1107 100644
|
||||||
|
--- a/src/lib/gssapi/krb5/k5sealv3.c
|
||||||
|
+++ b/src/lib/gssapi/krb5/k5sealv3.c
|
||||||
|
@@ -400,10 +400,15 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr,
|
||||||
|
/* Don't use bodysize here! Use the fact that
|
||||||
|
cipher.ciphertext.length has been adjusted to the
|
||||||
|
correct length. */
|
||||||
|
+ if (plain.length < 16 + ec) {
|
||||||
|
+ free(plain.data);
|
||||||
|
+ goto defective;
|
||||||
|
+ }
|
||||||
|
althdr = (unsigned char *)plain.data + plain.length - 16;
|
||||||
|
if (load_16_be(althdr) != KG2_TOK_WRAP_MSG
|
||||||
|
|| althdr[2] != ptr[2]
|
||||||
|
|| althdr[3] != ptr[3]
|
||||||
|
+ || load_16_be(althdr+4) != ec
|
||||||
|
|| memcmp(althdr+8, ptr+8, 8)) {
|
||||||
|
free(plain.data);
|
||||||
|
goto defective;
|
||||||
|
diff --git a/src/lib/gssapi/krb5/k5sealv3iov.c b/src/lib/gssapi/krb5/k5sealv3iov.c
|
||||||
|
index 333ee124dd..f8e90c35b4 100644
|
||||||
|
--- a/src/lib/gssapi/krb5/k5sealv3iov.c
|
||||||
|
+++ b/src/lib/gssapi/krb5/k5sealv3iov.c
|
||||||
|
@@ -402,9 +402,10 @@ gss_krb5int_unseal_v3_iov(krb5_context context,
|
||||||
|
if (load_16_be(althdr) != KG2_TOK_WRAP_MSG
|
||||||
|
|| althdr[2] != ptr[2]
|
||||||
|
|| althdr[3] != ptr[3]
|
||||||
|
+ || load_16_be(althdr + 4) != ec
|
||||||
|
|| memcmp(althdr + 8, ptr + 8, 8) != 0) {
|
||||||
|
*minor_status = 0;
|
||||||
|
- return GSS_S_BAD_SIG;
|
||||||
|
+ return GSS_S_DEFECTIVE_TOKEN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Verify checksum: note EC is checksum size here, not padding */
|
||||||
|
diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c
|
||||||
|
index 3ce2a90ce9..6a6585d9af 100644
|
||||||
|
--- a/src/lib/gssapi/krb5/k5unsealiov.c
|
||||||
|
+++ b/src/lib/gssapi/krb5/k5unsealiov.c
|
||||||
|
@@ -25,6 +25,7 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "k5-int.h"
|
||||||
|
+#include "k5-der.h"
|
||||||
|
#include "gssapiP_krb5.h"
|
||||||
|
|
||||||
|
static OM_uint32
|
||||||
|
@@ -247,6 +248,73 @@ cleanup:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Similar to k5_der_get_value(), but output an unchecked content length
|
||||||
|
+ * instead of a k5input containing the contents. */
|
||||||
|
+static inline bool
|
||||||
|
+get_der_tag(struct k5input *in, uint8_t idbyte, size_t *len_out)
|
||||||
|
+{
|
||||||
|
+ uint8_t lenbyte, i;
|
||||||
|
+ size_t len;
|
||||||
|
+
|
||||||
|
+ /* Do nothing if in is empty or the next byte doesn't match idbyte. */
|
||||||
|
+ if (in->status || in->len == 0 || *in->ptr != idbyte)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ /* Advance past the identifier byte and decode the length. */
|
||||||
|
+ (void)k5_input_get_byte(in);
|
||||||
|
+ lenbyte = k5_input_get_byte(in);
|
||||||
|
+ if (lenbyte < 128) {
|
||||||
|
+ len = lenbyte;
|
||||||
|
+ } else {
|
||||||
|
+ len = 0;
|
||||||
|
+ for (i = 0; i < (lenbyte & 0x7F); i++) {
|
||||||
|
+ if (len > (SIZE_MAX >> 8)) {
|
||||||
|
+ k5_input_set_status(in, EOVERFLOW);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ len = (len << 8) | k5_input_get_byte(in);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (in->status)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ *len_out = len;
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Similar to g_verify_token_header() without toktype or flags, but do not read
|
||||||
|
+ * more than *header_len bytes of ASN.1 wrapper, and on output set *header_len
|
||||||
|
+ * to the remaining number of header bytes. Verify the outer DER tag's length
|
||||||
|
+ * against token_len, which may be larger (but not smaller) than *header_len.
|
||||||
|
+ */
|
||||||
|
+static gss_int32
|
||||||
|
+verify_detached_wrapper(const gss_OID_desc *mech, size_t *header_len,
|
||||||
|
+ uint8_t **header_in, size_t token_len)
|
||||||
|
+{
|
||||||
|
+ struct k5input in, mech_der;
|
||||||
|
+ gss_OID_desc toid;
|
||||||
|
+ size_t len;
|
||||||
|
+
|
||||||
|
+ k5_input_init(&in, *header_in, *header_len);
|
||||||
|
+
|
||||||
|
+ if (get_der_tag(&in, 0x60, &len)) {
|
||||||
|
+ if (len != token_len - (in.ptr - *header_in))
|
||||||
|
+ return G_BAD_TOK_HEADER;
|
||||||
|
+ if (!k5_der_get_value(&in, 0x06, &mech_der))
|
||||||
|
+ return G_BAD_TOK_HEADER;
|
||||||
|
+ toid.elements = (uint8_t *)mech_der.ptr;
|
||||||
|
+ toid.length = mech_der.len;
|
||||||
|
+ if (!g_OID_equal(&toid, mech))
|
||||||
|
+ return G_WRONG_MECH;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *header_in = (uint8_t *)in.ptr;
|
||||||
|
+ *header_len = in.len;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Caller must provide TOKEN | DATA | PADDING | TRAILER, except
|
||||||
|
* for DCE in which case it can just provide TOKEN | DATA (must
|
||||||
|
@@ -267,8 +335,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
|
||||||
|
gss_iov_buffer_t header;
|
||||||
|
gss_iov_buffer_t padding;
|
||||||
|
gss_iov_buffer_t trailer;
|
||||||
|
- size_t input_length;
|
||||||
|
- unsigned int bodysize;
|
||||||
|
+ size_t input_length, hlen;
|
||||||
|
int toktype2;
|
||||||
|
|
||||||
|
header = kg_locate_header_iov(iov, iov_count, toktype);
|
||||||
|
@@ -298,15 +365,14 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
|
||||||
|
input_length += trailer->buffer.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
- code = g_verify_token_header(ctx->mech_used,
|
||||||
|
- &bodysize, &ptr, -1,
|
||||||
|
- input_length, 0);
|
||||||
|
+ hlen = header->buffer.length;
|
||||||
|
+ code = verify_detached_wrapper(ctx->mech_used, &hlen, &ptr, input_length);
|
||||||
|
if (code != 0) {
|
||||||
|
*minor_status = code;
|
||||||
|
return GSS_S_DEFECTIVE_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (bodysize < 2) {
|
||||||
|
+ if (hlen < 2) {
|
||||||
|
*minor_status = (OM_uint32)G_BAD_TOK_HEADER;
|
||||||
|
return GSS_S_DEFECTIVE_TOKEN;
|
||||||
|
}
|
||||||
|
@@ -314,7 +380,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status,
|
||||||
|
toktype2 = load_16_be(ptr);
|
||||||
|
|
||||||
|
ptr += 2;
|
||||||
|
- bodysize -= 2;
|
||||||
|
+ hlen -= 2;
|
||||||
|
|
||||||
|
switch (toktype2) {
|
||||||
|
case KG2_TOK_MIC_MSG:
|
||||||
|
diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c
|
||||||
|
index e08c0039f8..a052b8ab6e 100644
|
||||||
|
--- a/src/tests/gssapi/t_invalid.c
|
||||||
|
+++ b/src/tests/gssapi/t_invalid.c
|
||||||
|
@@ -36,31 +36,41 @@
|
||||||
|
*
|
||||||
|
* 1. A pre-CFX wrap or MIC token processed with a CFX-only context causes a
|
||||||
|
* null pointer dereference. (The token must use SEAL_ALG_NONE or it will
|
||||||
|
- * be rejected.)
|
||||||
|
+ * be rejected.) This vulnerability also applies to IOV unwrap.
|
||||||
|
*
|
||||||
|
- * 2. A pre-CFX wrap or MIC token with fewer than 24 bytes after the ASN.1
|
||||||
|
+ * 2. A CFX wrap token with a different value of EC between the plaintext and
|
||||||
|
+ * encrypted copies will be erroneously accepted, which allows a message
|
||||||
|
+ * truncation attack. This vulnerability also applies to IOV unwrap.
|
||||||
|
+ *
|
||||||
|
+ * 3. A CFX wrap token with a plaintext length fewer than 16 bytes causes an
|
||||||
|
+ * access before the beginning of the input buffer, possibly leading to a
|
||||||
|
+ * crash.
|
||||||
|
+ *
|
||||||
|
+ * 4. A CFX wrap token with a plaintext EC value greater than the plaintext
|
||||||
|
+ * length - 16 causes an integer underflow when computing the result length,
|
||||||
|
+ * likely causing a crash.
|
||||||
|
+ *
|
||||||
|
+ * 5. An IOV unwrap operation will overrun the header buffer if an ASN.1
|
||||||
|
+ * wrapper longer than the header buffer is present.
|
||||||
|
+ *
|
||||||
|
+ * 6. A pre-CFX wrap or MIC token with fewer than 24 bytes after the ASN.1
|
||||||
|
* header causes an input buffer overrun, usually leading to either a segv
|
||||||
|
* or a GSS_S_DEFECTIVE_TOKEN error due to garbage algorithm, filler, or
|
||||||
|
- * sequence number values.
|
||||||
|
+ * sequence number values. This vulnerability also applies to IOV unwrap.
|
||||||
|
*
|
||||||
|
- * 3. A pre-CFX wrap token with fewer than 16 + cksumlen bytes after the ASN.1
|
||||||
|
+ * 7. A pre-CFX wrap token with fewer than 16 + cksumlen bytes after the ASN.1
|
||||||
|
* header causes an integer underflow when computing the ciphertext length,
|
||||||
|
* leading to an allocation error on 32-bit platforms or a segv on 64-bit
|
||||||
|
* platforms. A pre-CFX MIC token of this size causes an input buffer
|
||||||
|
* overrun when comparing the checksum, perhaps leading to a segv.
|
||||||
|
*
|
||||||
|
- * 4. A pre-CFX wrap token with fewer than conflen + padlen bytes in the
|
||||||
|
+ * 8. A pre-CFX wrap token with fewer than conflen + padlen bytes in the
|
||||||
|
* ciphertext (where padlen is the last byte of the decrypted ciphertext)
|
||||||
|
* causes an integer underflow when computing the original message length,
|
||||||
|
* leading to an allocation error.
|
||||||
|
*
|
||||||
|
- * 5. In the mechglue, truncated encapsulation in the initial context token can
|
||||||
|
+ * 9. In the mechglue, truncated encapsulation in the initial context token can
|
||||||
|
* cause input buffer overruns in gss_accept_sec_context().
|
||||||
|
- *
|
||||||
|
- * Vulnerabilities #1 and #2 also apply to IOV unwrap, although tokens with
|
||||||
|
- * fewer than 16 bytes after the ASN.1 header will be rejected.
|
||||||
|
- * Vulnerabilities #2 and #5 can only be robustly detected using a
|
||||||
|
- * memory-checking environment such as valgrind.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "k5-int.h"
|
||||||
|
@@ -97,17 +107,25 @@ struct test {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
-/* Fake up enough of a CFX GSS context for gss_unwrap, using an AES key. */
|
||||||
|
+static void *
|
||||||
|
+ealloc(size_t len)
|
||||||
|
+{
|
||||||
|
+ void *ptr = calloc(len, 1);
|
||||||
|
+
|
||||||
|
+ if (ptr == NULL)
|
||||||
|
+ abort();
|
||||||
|
+ return ptr;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Fake up enough of a CFX GSS context for gss_unwrap, using an AES key.
|
||||||
|
+ * The context takes ownership of subkey. */
|
||||||
|
static gss_ctx_id_t
|
||||||
|
-make_fake_cfx_context(void)
|
||||||
|
+make_fake_cfx_context(krb5_key subkey)
|
||||||
|
{
|
||||||
|
gss_union_ctx_id_t uctx;
|
||||||
|
krb5_gss_ctx_id_t kgctx;
|
||||||
|
- krb5_keyblock kb;
|
||||||
|
|
||||||
|
- kgctx = calloc(1, sizeof(*kgctx));
|
||||||
|
- if (kgctx == NULL)
|
||||||
|
- abort();
|
||||||
|
+ kgctx = ealloc(sizeof(*kgctx));
|
||||||
|
kgctx->established = 1;
|
||||||
|
kgctx->proto = 1;
|
||||||
|
if (g_seqstate_init(&kgctx->seqstate, 0, 0, 0, 0) != 0)
|
||||||
|
@@ -116,15 +134,10 @@ make_fake_cfx_context(void)
|
||||||
|
kgctx->sealalg = -1;
|
||||||
|
kgctx->signalg = -1;
|
||||||
|
|
||||||
|
- kb.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
|
||||||
|
- kb.length = 16;
|
||||||
|
- kb.contents = (unsigned char *)"1234567887654321";
|
||||||
|
- if (krb5_k_create_key(NULL, &kb, &kgctx->subkey) != 0)
|
||||||
|
- abort();
|
||||||
|
+ kgctx->subkey = subkey;
|
||||||
|
+ kgctx->cksumtype = CKSUMTYPE_HMAC_SHA1_96_AES128;
|
||||||
|
|
||||||
|
- uctx = calloc(1, sizeof(*uctx));
|
||||||
|
- if (uctx == NULL)
|
||||||
|
- abort();
|
||||||
|
+ uctx = ealloc(sizeof(*uctx));
|
||||||
|
uctx->mech_type = &mech_krb5;
|
||||||
|
uctx->internal_ctx_id = (gss_ctx_id_t)kgctx;
|
||||||
|
return (gss_ctx_id_t)uctx;
|
||||||
|
@@ -138,9 +151,7 @@ make_fake_context(const struct test *test)
|
||||||
|
krb5_gss_ctx_id_t kgctx;
|
||||||
|
krb5_keyblock kb;
|
||||||
|
|
||||||
|
- kgctx = calloc(1, sizeof(*kgctx));
|
||||||
|
- if (kgctx == NULL)
|
||||||
|
- abort();
|
||||||
|
+ kgctx = ealloc(sizeof(*kgctx));
|
||||||
|
kgctx->established = 1;
|
||||||
|
if (g_seqstate_init(&kgctx->seqstate, 0, 0, 0, 0) != 0)
|
||||||
|
abort();
|
||||||
|
@@ -162,9 +173,7 @@ make_fake_context(const struct test *test)
|
||||||
|
if (krb5_k_create_key(NULL, &kb, &kgctx->enc) != 0)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
- uctx = calloc(1, sizeof(*uctx));
|
||||||
|
- if (uctx == NULL)
|
||||||
|
- abort();
|
||||||
|
+ uctx = ealloc(sizeof(*uctx));
|
||||||
|
uctx->mech_type = &mech_krb5;
|
||||||
|
uctx->internal_ctx_id = (gss_ctx_id_t)kgctx;
|
||||||
|
return (gss_ctx_id_t)uctx;
|
||||||
|
@@ -194,9 +203,7 @@ make_token(unsigned char *token, size_t len, gss_buffer_t out)
|
||||||
|
|
||||||
|
assert(mech_krb5.length == 9);
|
||||||
|
assert(len + 11 < 128);
|
||||||
|
- wrapped = malloc(len + 13);
|
||||||
|
- if (wrapped == NULL)
|
||||||
|
- abort();
|
||||||
|
+ wrapped = ealloc(len + 13);
|
||||||
|
wrapped[0] = 0x60;
|
||||||
|
wrapped[1] = len + 11;
|
||||||
|
wrapped[2] = 0x06;
|
||||||
|
@@ -207,6 +214,18 @@ make_token(unsigned char *token, size_t len, gss_buffer_t out)
|
||||||
|
out->value = wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Create a 16-byte header for a CFX confidential wrap token to be processed by
|
||||||
|
+ * the fake CFX context. */
|
||||||
|
+static void
|
||||||
|
+write_cfx_header(uint16_t ec, uint8_t *out)
|
||||||
|
+{
|
||||||
|
+ memset(out, 0, 16);
|
||||||
|
+ store_16_be(KG2_TOK_WRAP_MSG, out);
|
||||||
|
+ out[2] = FLAG_WRAP_CONFIDENTIAL;
|
||||||
|
+ out[3] = 0xFF;
|
||||||
|
+ store_16_be(ec, out + 4);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Unwrap a superficially valid RFC 1964 token with a CFX-only context, with
|
||||||
|
* regular and IOV unwrap. */
|
||||||
|
static void
|
||||||
|
@@ -238,6 +257,134 @@ test_bogus_1964_token(gss_ctx_id_t ctx)
|
||||||
|
free(in.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+test_cfx_altered_ec(gss_ctx_id_t ctx, krb5_key subkey)
|
||||||
|
+{
|
||||||
|
+ OM_uint32 major, minor;
|
||||||
|
+ uint8_t tokbuf[128], plainbuf[24];
|
||||||
|
+ krb5_data plain;
|
||||||
|
+ krb5_enc_data cipher;
|
||||||
|
+ gss_buffer_desc in, out;
|
||||||
|
+ gss_iov_buffer_desc iov[2];
|
||||||
|
+
|
||||||
|
+ /* Construct a header with a plaintext EC value of 3. */
|
||||||
|
+ write_cfx_header(3, tokbuf);
|
||||||
|
+
|
||||||
|
+ /* Encrypt a plaintext and a copy of the header with the EC value 0. */
|
||||||
|
+ memcpy(plainbuf, "truncate", 8);
|
||||||
|
+ memcpy(plainbuf + 8, tokbuf, 16);
|
||||||
|
+ store_16_be(0, plainbuf + 12);
|
||||||
|
+ plain = make_data(plainbuf, 24);
|
||||||
|
+ cipher.ciphertext.data = (char *)tokbuf + 16;
|
||||||
|
+ cipher.ciphertext.length = sizeof(tokbuf) - 16;
|
||||||
|
+ cipher.enctype = subkey->keyblock.enctype;
|
||||||
|
+ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL,
|
||||||
|
+ &plain, &cipher) != 0)
|
||||||
|
+ abort();
|
||||||
|
+
|
||||||
|
+ /* Verify that the token is rejected by gss_unwrap(). */
|
||||||
|
+ in.value = tokbuf;
|
||||||
|
+ in.length = 16 + cipher.ciphertext.length;
|
||||||
|
+ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL);
|
||||||
|
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||||
|
+ abort();
|
||||||
|
+ (void)gss_release_buffer(&minor, &out);
|
||||||
|
+
|
||||||
|
+ /* Verify that the token is rejected by gss_unwrap_iov(). */
|
||||||
|
+ iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
|
||||||
|
+ iov[0].buffer = in;
|
||||||
|
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
|
||||||
|
+ major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2);
|
||||||
|
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||||
|
+ abort();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+test_cfx_short_plaintext(gss_ctx_id_t ctx, krb5_key subkey)
|
||||||
|
+{
|
||||||
|
+ OM_uint32 major, minor;
|
||||||
|
+ uint8_t tokbuf[128], zerobyte = 0;
|
||||||
|
+ krb5_data plain;
|
||||||
|
+ krb5_enc_data cipher;
|
||||||
|
+ gss_buffer_desc in, out;
|
||||||
|
+
|
||||||
|
+ write_cfx_header(0, tokbuf);
|
||||||
|
+
|
||||||
|
+ /* Encrypt a single byte, with no copy of the header. */
|
||||||
|
+ plain = make_data(&zerobyte, 1);
|
||||||
|
+ cipher.ciphertext.data = (char *)tokbuf + 16;
|
||||||
|
+ cipher.ciphertext.length = sizeof(tokbuf) - 16;
|
||||||
|
+ cipher.enctype = subkey->keyblock.enctype;
|
||||||
|
+ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL,
|
||||||
|
+ &plain, &cipher) != 0)
|
||||||
|
+ abort();
|
||||||
|
+
|
||||||
|
+ /* Verify that the token is rejected by gss_unwrap(). */
|
||||||
|
+ in.value = tokbuf;
|
||||||
|
+ in.length = 16 + cipher.ciphertext.length;
|
||||||
|
+ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL);
|
||||||
|
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||||
|
+ abort();
|
||||||
|
+ (void)gss_release_buffer(&minor, &out);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+test_cfx_large_ec(gss_ctx_id_t ctx, krb5_key subkey)
|
||||||
|
+{
|
||||||
|
+ OM_uint32 major, minor;
|
||||||
|
+ uint8_t tokbuf[128] = { 0 }, plainbuf[20];
|
||||||
|
+ krb5_data plain;
|
||||||
|
+ krb5_enc_data cipher;
|
||||||
|
+ gss_buffer_desc in, out;
|
||||||
|
+
|
||||||
|
+ /* Construct a header with an EC value of 5. */
|
||||||
|
+ write_cfx_header(5, tokbuf);
|
||||||
|
+
|
||||||
|
+ /* Encrypt a 4-byte plaintext plus the header. */
|
||||||
|
+ memcpy(plainbuf, "abcd", 4);
|
||||||
|
+ memcpy(plainbuf + 4, tokbuf, 16);
|
||||||
|
+ plain = make_data(plainbuf, 20);
|
||||||
|
+ cipher.ciphertext.data = (char *)tokbuf + 16;
|
||||||
|
+ cipher.ciphertext.length = sizeof(tokbuf) - 16;
|
||||||
|
+ cipher.enctype = subkey->keyblock.enctype;
|
||||||
|
+ if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL,
|
||||||
|
+ &plain, &cipher) != 0)
|
||||||
|
+ abort();
|
||||||
|
+
|
||||||
|
+ /* Verify that the token is rejected by gss_unwrap(). */
|
||||||
|
+ in.value = tokbuf;
|
||||||
|
+ in.length = 16 + cipher.ciphertext.length;
|
||||||
|
+ major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL);
|
||||||
|
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||||
|
+ abort();
|
||||||
|
+ (void)gss_release_buffer(&minor, &out);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+test_iov_large_asn1_wrapper(gss_ctx_id_t ctx)
|
||||||
|
+{
|
||||||
|
+ OM_uint32 minor, major;
|
||||||
|
+ uint8_t databuf[10] = { 0 };
|
||||||
|
+ gss_iov_buffer_desc iov[2];
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * In this IOV array, the header contains a DER tag with a dangling eight
|
||||||
|
+ * bytes of length field. The data IOV indicates a total token length
|
||||||
|
+ * sufficient to contain the length bytes.
|
||||||
|
+ */
|
||||||
|
+ iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
|
||||||
|
+ iov[0].buffer.value = ealloc(2);
|
||||||
|
+ iov[0].buffer.length = 2;
|
||||||
|
+ memcpy(iov[0].buffer.value, "\x60\x88", 2);
|
||||||
|
+ iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
|
||||||
|
+ iov[1].buffer.value = databuf;
|
||||||
|
+ iov[1].buffer.length = 10;
|
||||||
|
+ major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2);
|
||||||
|
+ if (major != GSS_S_DEFECTIVE_TOKEN)
|
||||||
|
+ abort();
|
||||||
|
+ free(iov[0].buffer.value);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Process wrap and MIC tokens with incomplete headers. */
|
||||||
|
static void
|
||||||
|
test_short_header(gss_ctx_id_t ctx)
|
||||||
|
@@ -387,9 +534,7 @@ try_accept(void *value, size_t len)
|
||||||
|
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
|
||||||
|
|
||||||
|
/* Copy the provided value to make input overruns more obvious. */
|
||||||
|
- in.value = malloc(len);
|
||||||
|
- if (in.value == NULL)
|
||||||
|
- abort();
|
||||||
|
+ in.value = ealloc(len);
|
||||||
|
memcpy(in.value, value, len);
|
||||||
|
in.length = len;
|
||||||
|
(void)gss_accept_sec_context(&minor, &ctx, GSS_C_NO_CREDENTIAL, &in,
|
||||||
|
@@ -424,11 +569,23 @@ test_short_encapsulation(void)
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
+ krb5_keyblock kb;
|
||||||
|
+ krb5_key cfx_subkey;
|
||||||
|
gss_ctx_id_t ctx;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
- ctx = make_fake_cfx_context();
|
||||||
|
+ kb.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
|
||||||
|
+ kb.length = 16;
|
||||||
|
+ kb.contents = (unsigned char *)"1234567887654321";
|
||||||
|
+ if (krb5_k_create_key(NULL, &kb, &cfx_subkey) != 0)
|
||||||
|
+ abort();
|
||||||
|
+
|
||||||
|
+ ctx = make_fake_cfx_context(cfx_subkey);
|
||||||
|
test_bogus_1964_token(ctx);
|
||||||
|
+ test_cfx_altered_ec(ctx, cfx_subkey);
|
||||||
|
+ test_cfx_short_plaintext(ctx, cfx_subkey);
|
||||||
|
+ test_cfx_large_ec(ctx, cfx_subkey);
|
||||||
|
+ test_iov_large_asn1_wrapper(ctx);
|
||||||
|
free_fake_context(ctx);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
|
||||||
|
--
|
||||||
|
2.45.1
|
||||||
|
|
Loading…
Reference in new issue