unsigned inlen,
gss_buffer_t token)
{
+ OM_uint32 major, minor;
char *p = (char *)in;
unsigned remain = inlen;
int ret;
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;
}
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;
}
/*
+ * 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
* PERFORMANCE OF THIS SOFTWARE.
*/
+#include <config.h>
#include <string.h>
-#include <gssapi/gssapi.h>
+#include <stdlib.h>
+
#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
}
}
+/* 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 */
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
* *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;
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
#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 <config.h>
-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 <gssapi/gssapi.h>
+#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
+#include <gssapi/gssapi_ext.h>
+#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_ */