summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2013-10-16 11:04:30 -0400
committerSimo Sorce <simo@redhat.com>2013-10-18 16:29:51 -0400
commit1793582754d508191bf90404b0936060060b9027 (patch)
tree66298b3b6b112e25ebb2e0fe8160af88b59454d9
parent11b40086ed584a20764be67f4345ccee7ea5bcaf (diff)
downloadgss-ntlmssp-1793582754d508191bf90404b0936060060b9027.tar.gz
gss-ntlmssp-1793582754d508191bf90404b0936060060b9027.tar.xz
gss-ntlmssp-1793582754d508191bf90404b0936060060b9027.zip
Add support for connectionless mode
This needs a new GSSAPI flag, for now grab a number and define GSS_C_DATAGRAM_FLAG ourselves.
-rw-r--r--src/gss_sec_ctx.c163
1 files changed, 117 insertions, 46 deletions
diff --git a/src/gss_sec_ctx.c b/src/gss_sec_ctx.c
index 528cb13..855aa9f 100644
--- a/src/gss_sec_ctx.c
+++ b/src/gss_sec_ctx.c
@@ -20,9 +20,7 @@
#include <string.h>
#include <time.h>
-#include <gssapi/gssapi.h>
-#include <gssapi/gssapi_ext.h>
-
+#include "gssapi_ntlmssp.h"
#include "gss_ntlmssp.h"
@@ -86,11 +84,9 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
}
}
- if (*context_handle == GSS_C_NO_CONTEXT) {
+ ctx = (struct gssntlm_ctx *)(*context_handle);
- if (input_token && input_token->length != 0) {
- return GSS_S_DEFECTIVE_TOKEN;
- }
+ if (ctx == NULL) {
/* first call */
ctx = calloc(1, sizeof(struct gssntlm_ctx));
@@ -177,6 +173,10 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
if (req_flags & GSS_C_IDENTIFY_FLAG) {
ctx->neg_flags |= NTLMSSP_NEGOTIATE_IDENTIFY;
}
+ if (req_flags & GSS_C_DATAGRAM_FLAG) {
+ ctx->neg_flags |= NTLMSSP_NEGOTIATE_DATAGRAM |
+ NTLMSSP_NEGOTIATE_KEY_EXCH;
+ }
if (ctx->cred.type == GSSNTLM_CRED_USER &&
ctx->cred.cred.user.user.data.user.domain) {
@@ -207,28 +207,64 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
goto done;
}
- retmin = ntlm_encode_neg_msg(ctx->ntlm, ctx->neg_flags,
- domain, workstation, &ctx->nego_msg);
- if (retmin) {
- retmaj = GSS_S_FAILURE;
- goto done;
- }
+ /* only in connecionless mode we may receive an input buffer
+ * on the the first call, if DATAGRAM is not selected and
+ * we have a buffer here, somethings wrong */
+ if (ctx->neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM) {
- ctx->stage = NTLMSSP_STAGE_NEGOTIATE;
+ if ((input_token == GSS_C_NO_BUFFER) ||
+ (input_token->length == 0)) {
+ /* in connectionless mode we return an empty buffer here:
+ * see MS-NLMP 1.3.1.3 and 1.7 */
+ output_token->value = NULL;
+ output_token->length = 0;
- output_token->value = malloc(ctx->nego_msg.length);
- if (!output_token->value) {
- retmin = ENOMEM;
- retmaj = GSS_S_FAILURE;
+ /* and return the ball */
+ ctx->stage = NTLMSSP_STAGE_NEGOTIATE;
+ retmaj = GSS_S_CONTINUE_NEEDED;
+ goto done;
+ }
+ } else {
+
+ if (input_token && input_token->length != 0) {
+ retmin = EINVAL;
+ retmaj = GSS_S_DEFECTIVE_TOKEN;
+ goto done;
+ }
+
+ retmin = ntlm_encode_neg_msg(ctx->ntlm, ctx->neg_flags,
+ domain, workstation, &ctx->nego_msg);
+ if (retmin) {
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+
+ output_token->value = malloc(ctx->nego_msg.length);
+ if (!output_token->value) {
+ retmin = ENOMEM;
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+ memcpy(output_token->value, ctx->nego_msg.data, ctx->nego_msg.length);
+ output_token->length = ctx->nego_msg.length;
+
+ ctx->stage = NTLMSSP_STAGE_NEGOTIATE;
+ retmaj = GSS_S_CONTINUE_NEEDED;
goto done;
}
- memcpy(output_token->value, ctx->nego_msg.data, ctx->nego_msg.length);
- output_token->length = ctx->nego_msg.length;
- retmaj = GSS_S_CONTINUE_NEEDED;
+ /* If we get here we are in connectionless mode and where called
+ * with a chalenge message in the input buffer */
+ ctx->stage = NTLMSSP_STAGE_NEGOTIATE;
+ }
+
+ if (ctx == NULL) {
+ /* this should not happen */
+ retmin = EFAULT;
+ retmaj = GSS_S_FAILURE;
+ goto done;
} else {
- ctx = (struct gssntlm_ctx *)(*context_handle);
if (ctx->role != GSSNTLM_CLIENT) {
retmaj = GSS_S_NO_CONTEXT;
@@ -309,6 +345,21 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
goto done;
}
+ if (ctx->gss_flags & GSS_C_DATAGRAM_FLAG) {
+ if (!(in_flags & NTLMSSP_NEGOTIATE_DATAGRAM)) {
+ /* no common understanding */
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+ if (!(in_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
+ /* no common understanding */
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+ } else {
+ in_flags &= ~NTLMSSP_NEGOTIATE_DATAGRAM;
+ }
+
if (ctx->gss_flags & GSS_C_ANON_FLAG) {
/* Anonymous auth, empty responses */
memset(&nt_chal_resp, 0, sizeof(nt_chal_resp));
@@ -671,9 +722,6 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
char *p;
if (context_handle == NULL) return GSS_S_CALL_INACCESSIBLE_READ;
- if (input_token == GSS_C_NO_BUFFER) {
- return GSS_S_CALL_INACCESSIBLE_READ;
- }
if (output_token == GSS_C_NO_BUFFER) {
return GSS_S_CALL_INACCESSIBLE_WRITE;
}
@@ -742,33 +790,39 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
goto done;
}
- ctx->nego_msg.data = malloc(input_token->length);
- if (!ctx->nego_msg.data) {
- retmin = ENOMEM;
- retmaj = GSS_S_FAILURE;
- goto done;
- }
- memcpy(ctx->nego_msg.data, input_token->value, input_token->length);
- ctx->nego_msg.length = input_token->length;
+ if (input_token && input_token->length != 0) {
+ ctx->nego_msg.data = malloc(input_token->length);
+ if (!ctx->nego_msg.data) {
+ retmin = ENOMEM;
+ retmaj = GSS_S_FAILURE;
+ goto done;
+ }
+ memcpy(ctx->nego_msg.data, input_token->value, input_token->length);
+ ctx->nego_msg.length = input_token->length;
- retmin = ntlm_decode_msg_type(ctx->ntlm, &ctx->nego_msg, &msg_type);
- if (retmin || (msg_type != NEGOTIATE_MESSAGE)) {
- retmaj = GSS_S_DEFECTIVE_TOKEN;
- goto done;
- }
+ retmin = ntlm_decode_msg_type(ctx->ntlm, &ctx->nego_msg, &msg_type);
+ if (retmin || (msg_type != NEGOTIATE_MESSAGE)) {
+ retmaj = GSS_S_DEFECTIVE_TOKEN;
+ goto done;
+ }
- retmin = ntlm_decode_neg_msg(ctx->ntlm, &ctx->nego_msg, &in_flags,
- &domain, &workstation);
- if (retmin) {
- retmaj = GSS_S_DEFECTIVE_TOKEN;
- goto done;
+ retmin = ntlm_decode_neg_msg(ctx->ntlm, &ctx->nego_msg, &in_flags,
+ &domain, &workstation);
+ if (retmin) {
+ retmaj = GSS_S_DEFECTIVE_TOKEN;
+ goto done;
+ }
+
+ /* leave only the crossing between requested and allowed flags */
+ ctx->neg_flags &= in_flags;
+ } else {
+ /* If there is no negotiate message set datagram mode */
+ ctx->neg_flags |= NTLMSSP_NEGOTIATE_DATAGRAM | \
+ NTLMSSP_NEGOTIATE_KEY_EXCH;
}
/* TODO: Support MS-NLMP ServerBlock ? */
- /* leave only the crossing between requested and allowed flags */
- ctx->neg_flags &= in_flags;
-
/* TODO: Check some minimum required flags ? */
/* TODO: Check MS-NLMP ServerRequire128bitEncryption */
@@ -802,6 +856,9 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
if (ctx->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
ctx->gss_flags |= GSS_C_CONF_FLAG;
}
+ if (ctx->neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM) {
+ ctx->gss_flags |= GSS_C_DATAGRAM_FLAG;
+ }
/* Random server challenge */
challenge.data = ctx->server_chal;
@@ -882,6 +939,13 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
goto done;
}
+ if ((input_token == GSS_C_NO_BUFFER) ||
+ (input_token->length == 0)) {
+ retmin = EINVAL;
+ retmaj = GSS_S_DEFECTIVE_TOKEN;
+ goto done;
+ }
+
ctx->auth_msg.data = malloc(input_token->length);
if (!ctx->auth_msg.data) {
retmin = ENOMEM;
@@ -913,6 +977,13 @@ uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
goto done;
}
+ if ((ctx->neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM) &&
+ !(ctx->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
+ retmin = EINVAL;
+ retmaj = GSS_S_DEFECTIVE_TOKEN;
+ goto done;
+ }
+
lm_compat_lvl = gssntlm_get_lm_compatibility_level();
sec_req = gssntlm_required_security(lm_compat_lvl, ctx->role);
if (sec_req == 0xff) {