dovecot-2.2: auth: GSSAPI RFC compliancy fixes.
dovecot at dovecot.org
dovecot at dovecot.org
Fri Aug 10 05:24:41 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/ced6a796f56d
changeset: 14803:ced6a796f56d
user: Timo Sirainen <tss at iki.fi>
date: Tue Jul 17 16:17:40 2012 +0300
description:
auth: GSSAPI RFC compliancy fixes.
Patch by Ben Morrow:
The first problem is that, because of the way the client invokes
libsasl, it sends a GSSAPI request which does not ask for mutual
authentication. This means that on the server gss_accept_sec_context
returns GSS_S_COMPLETE with a zero-length output token. Dovecot
currently sends this to the client as a zero-length continuation
response, but this is incorrect according to RFC 4752: what it ought to
do instead is proceed straight to the security layer negotiations, and
send a gss_wrap packet.
The second is that Cyrus sends an empty authz identity; that is, the
security layer negotiation packet, when gss_unwrapped, is exactly 4
bytes long. Dovecot objects to this, but in RFC 4422 this is explicitly
allowed, and means the authz identity is identical to the authn
identity.
diffstat:
src/auth/mech-gssapi.c | 58 +++++++++++++++++++++++++++++++++++++++----------
1 files changed, 46 insertions(+), 12 deletions(-)
diffs (96 lines):
diff -r 56ef4e70b1a9 -r ced6a796f56d src/auth/mech-gssapi.c
--- a/src/auth/mech-gssapi.c Tue Jul 17 15:44:36 2012 +0300
+++ b/src/auth/mech-gssapi.c Tue Jul 17 16:17:40 2012 +0300
@@ -78,6 +78,9 @@
static gss_OID_desc mech_gssapi_krb5_oid =
{ 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
+static int
+mech_gssapi_wrap(struct gssapi_auth_request *request, gss_buffer_desc inbuf);
+
static void mech_gssapi_log_error(struct auth_request *request,
OM_uint32 status_value, int status_type,
const char *description)
@@ -214,6 +217,21 @@
return name;
}
+static gss_name_t
+duplicate_name(struct auth_request *request, gss_name_t old)
+{
+ OM_uint32 major_status, minor_status;
+ gss_name_t new;
+
+ major_status = gss_duplicate_name(&minor_status, old, &new);
+ if (GSS_ERROR(major_status)) {
+ mech_gssapi_log_error(request, major_status, GSS_C_GSS_CODE,
+ "gss_duplicate_name");
+ return GSS_C_NO_NAME;
+ }
+ return new;
+}
+
static bool data_has_nuls(const void *data, unsigned int len)
{
const unsigned char *c = data;
@@ -328,9 +346,15 @@
}
if (ret == 0) {
- auth_request_handler_reply_continue(auth_request,
- output_token.value,
- output_token.length);
+ if (output_token.length > 0) {
+ auth_request_handler_reply_continue(auth_request,
+ output_token.value,
+ output_token.length);
+ } else {
+ /* If there is no output token, go straight to wrap,
+ which is expecting an empty input token. */
+ ret = mech_gssapi_wrap(request, output_token);
+ }
}
(void)gss_release_buffer(&minor_status, &output_token);
return ret;
@@ -510,22 +534,32 @@
/* outbuf[0] contains bitmask for selected security layer,
outbuf[1..3] contains maximum output_message size */
- if (outbuf.length <= 4) {
+ if (outbuf.length < 4) {
auth_request_log_error(auth_request, "gssapi",
"Invalid response length");
return -1;
}
- name = (unsigned char *)outbuf.value + 4;
- name_len = outbuf.length - 4;
- if (data_has_nuls(name, name_len)) {
- auth_request_log_info(auth_request, "gssapi",
- "authz_name has NULs");
- return -1;
+ if (outbuf.length > 4) {
+ name = (unsigned char *)outbuf.value + 4;
+ name_len = outbuf.length - 4;
+
+ if (data_has_nuls(name, name_len)) {
+ auth_request_log_info(auth_request, "gssapi",
+ "authz_name has NULs");
+ return -1;
+ }
+
+ login_user = p_strndup(auth_request->pool, name, name_len);
+ request->authz_name = import_name(auth_request, name, name_len);
+ } else {
+ request->authz_name = duplicate_name(auth_request,
+ request->authn_name);
+ if (get_display_name(auth_request, request->authz_name,
+ NULL, &login_user) < 0)
+ return -1;
}
- login_user = p_strndup(auth_request->pool, name, name_len);
- request->authz_name = import_name(auth_request, name, name_len);
if (request->authz_name == GSS_C_NO_NAME) {
auth_request_log_info(auth_request, "gssapi", "no authz_name");
return -1;
More information about the dovecot-cvs
mailing list