From 5965589a349832ddfa3bcce7439b6228b2cbd6b7 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Tue, 22 Mar 2011 12:44:38 +1100 Subject: [PATCH] use draft-josefsson-gss-capsulate-01 if present --- cmulocal/sasl2.m4 | 3 + config.h.in | 12 ++++ configure | 33 ++++++++++ plugins/gs2.c | 62 ++++++++---------- plugins/gs2_token.c | 180 ++++++++++++++++++++++++++++++++++++++++----------- plugins/gs2_token.h | 41 +++++++----- saslauthd/aclocal.m4 | 11 ---- 7 files changed, 245 insertions(+), 97 deletions(-) diff --git a/cmulocal/sasl2.m4 b/cmulocal/sasl2.m4 index 9c03e73..9eacd68 100644 --- a/cmulocal/sasl2.m4 +++ b/cmulocal/sasl2.m4 @@ -264,6 +264,9 @@ if test "$gssapi" != no; then cmu_save_LIBS="$LIBS" LIBS="$LIBS $GSSAPIBASE_LIBS" AC_CHECK_FUNCS(gsskrb5_register_acceptor_identity) + AC_CHECK_FUNCS(gss_decapsulate_token) + AC_CHECK_FUNCS(gss_encapsulate_token) + AC_CHECK_FUNCS(gss_oid_equal) LIBS="$cmu_save_LIBS" else AC_MSG_RESULT([disabled]) diff --git a/config.h.in b/config.h.in index 5f8799d..308b967 100644 --- a/config.h.in +++ b/config.h.in @@ -129,6 +129,15 @@ /* Define if your GSSAPI implimentation defines GSS_C_NT_USER_NAME */ #undef HAVE_GSS_C_NT_USER_NAME +/* Define to 1 if you have the `gss_decapsulate_token' function. */ +#undef HAVE_GSS_DECAPSULATE_TOKEN + +/* Define to 1 if you have the `gss_encapsulate_token' function. */ +#undef HAVE_GSS_ENCAPSULATE_TOKEN + +/* Define to 1 if you have the `gss_oid_equal' function. */ +#undef HAVE_GSS_OID_EQUAL + /* Define to 1 if you have the `inet_aton' function. */ #undef HAVE_INET_ATON @@ -330,6 +339,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION diff --git a/configure b/configure index 05274fb..bf13154 100755 --- a/configure +++ b/configure @@ -14620,6 +14620,39 @@ _ACEOF fi done + for ac_func in gss_decapsulate_token +do : + ac_fn_c_check_func "$LINENO" "gss_decapsulate_token" "ac_cv_func_gss_decapsulate_token" +if test "x$ac_cv_func_gss_decapsulate_token" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GSS_DECAPSULATE_TOKEN 1 +_ACEOF + +fi +done + + for ac_func in gss_encapsulate_token +do : + ac_fn_c_check_func "$LINENO" "gss_encapsulate_token" "ac_cv_func_gss_encapsulate_token" +if test "x$ac_cv_func_gss_encapsulate_token" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GSS_ENCAPSULATE_TOKEN 1 +_ACEOF + +fi +done + + for ac_func in gss_oid_equal +do : + ac_fn_c_check_func "$LINENO" "gss_oid_equal" "ac_cv_func_gss_oid_equal" +if test "x$ac_cv_func_gss_oid_equal" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GSS_OID_EQUAL 1 +_ACEOF + +fi +done + LIBS="$cmu_save_LIBS" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 diff --git a/plugins/gs2.c b/plugins/gs2.c index 5afe7bb..1b6dc6a 100644 --- a/plugins/gs2.c +++ b/plugins/gs2.c @@ -1013,6 +1013,7 @@ gs2_verify_initial_message(context_t *text, unsigned inlen, gss_buffer_t token) { + OM_uint32 major, minor; char *p = (char *)in; unsigned remain = inlen; int ret; @@ -1088,32 +1089,29 @@ gs2_verify_initial_message(context_t *text, if (ret != SASL_OK) return ret; - buf.length = remain; - buf.value = p; - if (text->gs2_flags & GS2_NONSTD_FLAG) { - token->value = text->utils->malloc(buf.length); - if (token->value == NULL) - return SASL_NOMEM; - - token->length = buf.length; - memcpy(token->value, buf.value, buf.length); + buf.length = remain; + buf.value = p; } else { - unsigned int token_size; + gss_buffer_desc tmp; - /* create a properly formed GSS token */ - token_size = gs2_token_size(text->mechanism, buf.length); - token->value = text->utils->malloc(token_size); - if (token->value == NULL) + tmp.length = remain; + tmp.value = p; + + major = gss_encapsulate_token(&tmp, text->mechanism, &buf); + if (GSS_ERROR(major)) return SASL_NOMEM; + } + + token->value = text->utils->malloc(buf.length); + if (token->value == NULL) + return SASL_NOMEM; - token->length = token_size; + token->length = buf.length; + memcpy(token->value, buf.value, buf.length); - p = (char *)token->value; - gs2_make_token_header(text->mechanism, buf.length, - (unsigned char **)&p); - memcpy(p, buf.value, buf.length); - } + if ((text->gs2_flags & GS2_NONSTD_FLAG) == 0) + gss_release_buffer(&minor, &buf); return SASL_OK; } @@ -1231,36 +1229,32 @@ gs2_make_message(context_t *text, unsigned *outlen) { OM_uint32 major, minor; - unsigned char *mech_token_data; - size_t mech_token_size; - char *p; - unsigned header_len = 0; int ret; - - mech_token_size = token->length; - mech_token_data = (unsigned char *)token->value; + unsigned header_len = 0; + gss_buffer_desc decap_token = GSS_C_EMPTY_BUFFER; if (initialContextToken) { header_len = *outlen; - major = gs2_verify_token_header(&minor, text->mechanism, - &mech_token_size, &mech_token_data, - token->length); + major = gss_decapsulate_token(token, text->mechanism, &decap_token); if ((major == GSS_S_DEFECTIVE_TOKEN && (text->plug.client->features & SASL_FEAT_GSS_FRAMING)) || GSS_ERROR(major)) return SASL_FAIL; + + token = &decap_token; } ret = _plug_buf_alloc(text->utils, out, outlen, - header_len + mech_token_size); + header_len + token->length); if (ret != 0) return ret; - p = *out + header_len; - memcpy(p, mech_token_data, mech_token_size); + memcpy(*out + header_len, token->value, token->length); + *outlen = header_len + token->length; - *outlen = header_len + mech_token_size; + if (initialContextToken) + gss_release_buffer(&minor, &decap_token); return SASL_OK; } diff --git a/plugins/gs2_token.c b/plugins/gs2_token.c index 9a97243..02c6192 100644 --- a/plugins/gs2_token.c +++ b/plugins/gs2_token.c @@ -1,4 +1,35 @@ /* + * Copyright (c) 2011, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -20,14 +51,17 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include #include -#include +#include + #include "gs2_token.h" /* * $Id: util_token.c 23457 2009-12-08 00:04:48Z tlyu $ */ +#ifndef HAVE_GSS_ENCAPSULATE_TOKEN /* XXXX this code currently makes the assumption that a mech oid will never be longer than 127 bytes. This assumption is not inherent in the interfaces, so the code can be fixed if the OSI namespace @@ -95,6 +129,65 @@ der_write_length(unsigned char **buf, size_t length) } } +/* returns the length of a token, given the mech oid and the body size */ + +static size_t +token_size(const gss_OID_desc *mech, size_t body_size) +{ + /* set body_size to sequence contents size */ + body_size += 2 + (size_t) mech->length; /* NEED overflow check */ + return 1 + der_length_size(body_size) + body_size; +} + +/* fills in a buffer with the token header. The buffer is assumed to + be the right size. buf is advanced past the token header */ + +static void +make_token_header( + const gss_OID_desc *mech, + size_t body_size, + unsigned char **buf) +{ + *(*buf)++ = 0x60; + der_write_length(buf, 2 + mech->length + body_size); + *(*buf)++ = 0x06; + *(*buf)++ = (unsigned char)mech->length; + memcpy(*buf, mech->elements, mech->length); + *buf += mech->length; +} + +OM_uint32 +gs2_encapsulate_token(const gss_buffer_t input_token, + const gss_OID token_oid, + gss_buffer_t output_token) +{ + size_t tokenSize; + unsigned char *buf; + + if (input_token == GSS_C_NO_BUFFER || token_oid == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (output_token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + tokenSize = token_size(token_oid, input_token->length); + + output_token->value = malloc(tokenSize); + if (output_token->value == NULL) + return GSS_S_FAILURE; + + buf = output_token->value; + + make_token_header(token_oid, input_token->length, &buf); + memcpy(buf, input_token->value, input_token->length); + output_token->length = tokenSize; + + return GSS_S_COMPLETE; +} +#endif + + +#ifndef HAVE_GSS_DECAPSULATE_TOKEN /* returns decoded length, or < 0 on failure. Advances buf and decrements bufsize */ @@ -126,33 +219,6 @@ der_read_length(unsigned char **buf, ssize_t *bufsize) return ret; } -/* returns the length of a token, given the mech oid and the body size */ - -size_t -gs2_token_size(const gss_OID_desc *mech, size_t body_size) -{ - /* set body_size to sequence contents size */ - body_size += 2 + (size_t) mech->length; /* NEED overflow check */ - return 1 + der_length_size(body_size) + body_size; -} - -/* fills in a buffer with the token header. The buffer is assumed to - be the right size. buf is advanced past the token header */ - -void -gs2_make_token_header( - const gss_OID_desc *mech, - size_t body_size, - unsigned char **buf) -{ - *(*buf)++ = 0x60; - der_write_length(buf, 2 + mech->length + body_size); - *(*buf)++ = 0x06; - *(*buf)++ = (unsigned char)mech->length; - memcpy(*buf, mech->elements, mech->length); - *buf += mech->length; -} - /* * Given a buffer containing a token, reads and verifies the token, * leaving buf advanced past the token header, and setting body_size @@ -162,12 +228,12 @@ gs2_make_token_header( * *body_size are left unmodified on error. */ -OM_uint32 -gs2_verify_token_header(OM_uint32 *minor, - gss_const_OID mech, - size_t *body_size, - unsigned char **buf_in, - size_t toksize_in) +static OM_uint32 +verify_token_header(OM_uint32 *minor, + const gss_OID mech, + size_t *body_size, + unsigned char **buf_in, + size_t toksize_in) { unsigned char *buf = *buf_in; ssize_t seqsize; @@ -206,11 +272,53 @@ gs2_verify_token_header(OM_uint32 *minor, toid.elements = buf; buf += toid.length; - if (!g_OID_equal(&toid, mech)) - return GSS_S_BAD_MECH; + if (!gss_oid_equal(&toid, mech)) + return GSS_S_DEFECTIVE_TOKEN; *buf_in = buf; *body_size = toksize; return GSS_S_COMPLETE; } + +OM_uint32 +gs2_decapsulate_token(const gss_buffer_t input_token, + const gss_OID token_oid, + gss_buffer_t output_token) +{ + OM_uint32 major, minor; + size_t body_size = 0; + unsigned char *buf_in; + + if (input_token == GSS_C_NO_BUFFER || token_oid == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (output_token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + buf_in = input_token->value; + + major = verify_token_header(&minor, token_oid, &body_size, &buf_in, + input_token->length); + if (minor != 0) + return GSS_S_DEFECTIVE_TOKEN; + + output_token->value = malloc(body_size); + if (output_token->value == NULL) + return GSS_S_FAILURE; + + memcpy(output_token->value, buf_in, body_size); + output_token->length = body_size; + + return GSS_S_COMPLETE; +} +#endif + +#ifndef HAVE_GSS_OID_EQUAL +int +gs2_oid_equal(const gss_OID o1, const gss_OID o2) +{ + return o1->length == o2->length && + (memcmp(o1->elements, o2->elements, o1->length) == 0); +} +#endif diff --git a/plugins/gs2_token.h b/plugins/gs2_token.h index a83e264..52cb390 100644 --- a/plugins/gs2_token.h +++ b/plugins/gs2_token.h @@ -23,24 +23,33 @@ #ifndef _GS2_TOKEN_H_ #define _GS2_TOKEN_H_ 1 -#define g_OID_equal(o1, o2) \ - (((o1)->length == (o2)->length) && \ - (memcmp((o1)->elements, (o2)->elements, (o1)->length) == 0)) +#include -extern OM_uint32 -gs2_verify_token_header(OM_uint32 *minor, - gss_const_OID mech, - size_t *body_size, - unsigned char **buf_in, - size_t toksize_in); +#include +#ifdef HAVE_GSSAPI_GSSAPI_EXT_H +#include +#endif -extern void -gs2_make_token_header( - const gss_OID_desc *mech, - size_t body_size, - unsigned char **buf); +#ifndef HAVE_GSS_DECAPSULATE_TOKEN +OM_uint32 +gs2_decapsulate_token(const gss_buffer_t input_token, + const gss_OID token_oid, + gss_buffer_t output_token); +#define gss_decapsulate_token gs2_decapsulate_token +#endif -extern size_t -gs2_token_size(const gss_OID_desc *mech, size_t body_size); +#ifndef HAVE_GSS_ENCAPSULATE_TOKEN +OM_uint32 +gs2_encapsulate_token(const gss_buffer_t input_token, + const gss_OID token_oid, + gss_buffer_t output_token); +#define gss_encapsulate_token gs2_encapsulate_token +#endif + +#ifndef HAVE_GSS_OID_EQUAL +int +gs2_oid_equal(const gss_OID o1, const gss_OID o2); +#define gss_oid_equal gs2_oid_equal +#endif #endif /* _GS2_TOKEN_H_ */ diff --git a/saslauthd/aclocal.m4 b/saslauthd/aclocal.m4 index a13bc14..93d6510 100644 --- a/saslauthd/aclocal.m4 +++ b/saslauthd/aclocal.m4 @@ -901,14 +901,3 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR -m4_include([../config/kerberos_v4.m4]) -m4_include([../config/sasldb.m4]) -m4_include([../cmulocal/berkdb.m4]) -m4_include([../cmulocal/bsd_sockets.m4]) -m4_include([../cmulocal/c-attribute.m4]) -m4_include([../cmulocal/common.m4]) -m4_include([../cmulocal/cyrus.m4]) -m4_include([../cmulocal/init_automake.m4]) -m4_include([../cmulocal/ipv6.m4]) -m4_include([../cmulocal/openssl.m4]) -m4_include([../cmulocal/sasl2.m4]) -- 2.1.4