summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/gssapi/krb5/cfx.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/lib/gssapi/krb5/cfx.c')
-rw-r--r--source4/heimdal/lib/gssapi/krb5/cfx.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/source4/heimdal/lib/gssapi/krb5/cfx.c b/source4/heimdal/lib/gssapi/krb5/cfx.c
index 3c1536b60ea..8d806f9fbf1 100644
--- a/source4/heimdal/lib/gssapi/krb5/cfx.c
+++ b/source4/heimdal/lib/gssapi/krb5/cfx.c
@@ -206,11 +206,36 @@ gss_iov_buffer_desc *
_gk_find_buffer(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type)
{
int i;
+ gss_iov_buffer_t iovp = GSS_C_NO_IOV_BUFFER;
- for (i = 0; i < iov_count; i++)
- if (type == GSS_IOV_BUFFER_TYPE(iov[i].type))
- return &iov[i];
- return NULL;
+ if (iov == GSS_C_NO_IOV_BUFFER)
+ return GSS_C_NO_IOV_BUFFER;
+
+ /*
+ * This function is used to find header, padding or trailer buffers
+ * which are singletons; return NULL if multiple instances are found.
+ */
+ for (i = 0; i < iov_count; i++) {
+ if (type == GSS_IOV_BUFFER_TYPE(iov[i].type)) {
+ if (iovp == GSS_C_NO_IOV_BUFFER)
+ iovp = &iov[i];
+ else
+ return GSS_C_NO_IOV_BUFFER;
+ }
+ }
+
+ /*
+ * For compatibility with SSPI, an empty padding buffer is treated
+ * equivalent to an absent padding buffer (unless the caller is
+ * requesting that a padding buffer be allocated).
+ */
+ if (iovp &&
+ iovp->buffer.length == 0 &&
+ type == GSS_IOV_BUFFER_TYPE_PADDING &&
+ (GSS_IOV_BUFFER_FLAGS(iovp->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) == 0)
+ iovp = NULL;
+
+ return iovp;
}
OM_uint32
@@ -239,7 +264,8 @@ _gk_verify_buffers(OM_uint32 *minor_status,
const gsskrb5_ctx ctx,
const gss_iov_buffer_desc *header,
const gss_iov_buffer_desc *padding,
- const gss_iov_buffer_desc *trailer)
+ const gss_iov_buffer_desc *trailer,
+ int block_cipher)
{
if (header == NULL) {
*minor_status = EINVAL;
@@ -260,9 +286,12 @@ _gk_verify_buffers(OM_uint32 *minor_status,
}
} else {
/*
- * In non-DCE style mode we require having a padding buffer
+ * In non-DCE style mode we require having a padding buffer for
+ * encryption types that do not behave as stream ciphers. This
+ * check is superfluous for now, as only RC4 and RFC4121 enctypes
+ * are presently implemented for the IOV APIs; be defensive.
*/
- if (padding == NULL) {
+ if (block_cipher && padding == NULL) {
*minor_status = EINVAL;
return GSS_S_FAILURE;
}
@@ -306,7 +335,8 @@ _gssapi_wrap_cfx_iov(OM_uint32 *minor_status,
trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
- major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer);
+ major_status = _gk_verify_buffers(minor_status, ctx, header,
+ padding, trailer, FALSE);
if (major_status != GSS_S_COMPLETE) {
return major_status;
}
@@ -391,7 +421,6 @@ _gssapi_wrap_cfx_iov(OM_uint32 *minor_status,
if (IS_DCE_STYLE(ctx))
rrc -= ec;
gsshsize += gsstsize;
- gsstsize = 0;
} else if (GSS_IOV_BUFFER_FLAGS(trailer->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
major_status = _gk_allocate_buffer(minor_status, trailer, gsstsize);
if (major_status)
@@ -683,6 +712,7 @@ unrotate_iov(OM_uint32 *minor_status, size_t rrc, gss_iov_buffer_desc *iov, int
if (iov[i].buffer.length <= skip) {
skip -= iov[i].buffer.length;
} else {
+ /* copy back to original buffer */
memcpy(((uint8_t *)iov[i].buffer.value) + skip, q, iov[i].buffer.length - skip);
q += iov[i].buffer.length - skip;
skip = 0;
@@ -697,13 +727,14 @@ unrotate_iov(OM_uint32 *minor_status, size_t rrc, gss_iov_buffer_desc *iov, int
GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING ||
GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER)
{
- memcpy(q, iov[i].buffer.value, min(iov[i].buffer.length, skip));
+ memcpy(iov[i].buffer.value, q, min(iov[i].buffer.length, skip));
if (iov[i].buffer.length > skip)
break;
skip -= iov[i].buffer.length;
q += iov[i].buffer.length;
}
}
+ free(p);
return GSS_S_COMPLETE;
}
@@ -746,7 +777,8 @@ _gssapi_unwrap_cfx_iov(OM_uint32 *minor_status,
trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
- major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer);
+ major_status = _gk_verify_buffers(minor_status, ctx, header,
+ padding, trailer, FALSE);
if (major_status != GSS_S_COMPLETE) {
return major_status;
}
@@ -930,7 +962,6 @@ _gssapi_unwrap_cfx_iov(OM_uint32 *minor_status,
}
gsshsize += gsstsize;
- gsstsize = 0;
} else if (trailer->buffer.length != gsstsize) {
major_status = GSS_S_DEFECTIVE_TOKEN;
goto failure;
@@ -1069,7 +1100,8 @@ _gssapi_wrap_iov_length_cfx(OM_uint32 *minor_status,
}
}
- major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer);
+ major_status = _gk_verify_buffers(minor_status, ctx, header,
+ padding, trailer, FALSE);
if (major_status != GSS_S_COMPLETE) {
return major_status;
}