summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/gssapi/krb5/aeap.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/lib/gssapi/krb5/aeap.c')
-rw-r--r--source4/heimdal/lib/gssapi/krb5/aeap.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/source4/heimdal/lib/gssapi/krb5/aeap.c b/source4/heimdal/lib/gssapi/krb5/aeap.c
new file mode 100644
index 0000000000..7dab7877d7
--- /dev/null
+++ b/source4/heimdal/lib/gssapi/krb5/aeap.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2008 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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.
+ */
+
+#include "gsskrb5_locl.h"
+
+#include <roken.h>
+
+static OM_uint32
+iov_allocate(OM_uint32 *minor_status, gss_iov_buffer_desc *iov, int iov_count)
+{
+ unsigned int i;
+
+ for (i = 0; i < iov_count; i++) {
+ if (GSS_IOV_BUFFER_FLAGS(iov[i].type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE){
+ void *ptr = malloc(iov[i].buffer.length);
+ if (ptr == NULL)
+ abort();
+ if (iov[i].buffer.value)
+ memcpy(ptr, iov[i].buffer.value, iov[i].buffer.length);
+ iov[i].buffer.value = ptr;
+ iov[i].type |= GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED;
+ }
+ }
+ return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+iov_map(OM_uint32 *minor_status,
+ const gss_iov_buffer_desc *iov,
+ int iov_count,
+ krb5_crypto_iov *data)
+{
+ unsigned int i;
+
+ for (i = 0; i < iov_count; i++) {
+ switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
+ case GSS_IOV_BUFFER_TYPE_EMPTY:
+ data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
+ break;
+ case GSS_IOV_BUFFER_TYPE_DATA:
+ data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+ break;
+ case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+ data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+ break;
+ case GSS_IOV_BUFFER_TYPE_HEADER:
+ data[i].flags = KRB5_CRYPTO_TYPE_HEADER;
+ break;
+ case GSS_IOV_BUFFER_TYPE_TRAILER:
+ data[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
+ break;
+ case GSS_IOV_BUFFER_TYPE_PADDING:
+ data[i].flags = KRB5_CRYPTO_TYPE_PADDING;
+ break;
+ case GSS_IOV_BUFFER_TYPE_STREAM:
+ abort();
+ break;
+ default:
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+ data[i].data.data = iov[i].buffer.value;
+ data[i].data.length = iov[i].buffer.length;
+ }
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+_gk_wrap_iov(OM_uint32 * minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int * conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
+ krb5_context context;
+ OM_uint32 major_status, junk;
+ krb5_crypto_iov *data;
+ krb5_error_code ret;
+ unsigned usage;
+
+ GSSAPI_KRB5_INIT (&context);
+
+ major_status = iov_allocate(minor_status, iov, iov_count);
+ if (major_status != GSS_S_COMPLETE)
+ return major_status;
+
+ data = calloc(iov_count, sizeof(data[0]));
+ if (data == NULL) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ major_status = iov_map(minor_status, iov, iov_count, data);
+ if (major_status != GSS_S_COMPLETE) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ free(data);
+ return major_status;
+ }
+
+ if (ctx->more_flags & LOCAL) {
+ usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
+ } else {
+ usage = KRB5_KU_USAGE_INITIATOR_SIGN;
+ }
+
+ ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage,
+ data, iov_count, NULL);
+ free(data);
+ if (ret) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ *minor_status = ret;
+ return GSS_S_FAILURE;
+ }
+
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+_gk_unwrap_iov(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int *conf_state,
+ gss_qop_t *qop_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
+ krb5_context context;
+ krb5_error_code ret;
+ OM_uint32 major_status, junk;
+ krb5_crypto_iov *data;
+ unsigned usage;
+
+ GSSAPI_KRB5_INIT (&context);
+
+ major_status = iov_allocate(minor_status, iov, iov_count);
+ if (major_status != GSS_S_COMPLETE)
+ return major_status;
+
+ data = calloc(iov_count, sizeof(data[0]));
+ if (data == NULL) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ major_status = iov_map(minor_status, iov, iov_count, data);
+ if (major_status != GSS_S_COMPLETE) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ free(data);
+ return major_status;
+ }
+
+ if (ctx->more_flags & LOCAL) {
+ usage = KRB5_KU_USAGE_INITIATOR_SIGN;
+ } else {
+ usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
+ }
+
+ ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage,
+ data, iov_count, NULL);
+ free(data);
+ if (ret) {
+ *minor_status = ret;
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ return GSS_S_FAILURE;
+ }
+
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+_gk_wrap_iov_length(OM_uint32 * minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int *conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
+ krb5_context context;
+ unsigned int i;
+ size_t size;
+ size_t *padding = NULL;
+
+ GSSAPI_KRB5_INIT (&context);
+ *minor_status = 0;
+
+ for (size = 0, i = 0; i < iov_count; i++) {
+ switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
+ case GSS_IOV_BUFFER_TYPE_EMPTY:
+ break;
+ case GSS_IOV_BUFFER_TYPE_DATA:
+ size += iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_HEADER:
+ iov[i].buffer.length =
+ krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER);
+ size += iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_TRAILER:
+ iov[i].buffer.length =
+ krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER);
+ size += iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_PADDING:
+ if (padding != NULL) {
+ *minor_status = 0;
+ return GSS_S_FAILURE;
+ }
+ padding = &iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_STREAM:
+ size += iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+ break;
+ default:
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+ }
+ if (padding) {
+ size_t pad = krb5_crypto_length(context, ctx->crypto,
+ KRB5_CRYPTO_TYPE_PADDING);
+ if (pad > 1) {
+ *padding = pad - (size % pad);
+ if (*padding == pad)
+ *padding = 0;
+ } else
+ *padding = 0;
+ }
+
+ return GSS_S_COMPLETE;
+}