summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Blin <kai@samba.org>2008-11-07 09:13:26 +0100
committerKai Blin <kai@samba.org>2008-11-10 12:50:02 +0100
commit7d8787c915b97f44851d2ca4c854c5f3aca8a3c6 (patch)
tree7a696cb4201569821f52091f851cc6b234b9220c
parentd64caaf593201ca02ab9eac86e98c5adab3faf72 (diff)
downloadsamba-7d8787c915b97f44851d2ca4c854c5f3aca8a3c6.tar.gz
samba-7d8787c915b97f44851d2ca4c854c5f3aca8a3c6.tar.bz2
samba-7d8787c915b97f44851d2ca4c854c5f3aca8a3c6.zip
ntlm_auth: Put huge NTLMv2 blobs into extra_data on CRAP auth.
This fixes bug #5865
-rw-r--r--source3/nsswitch/winbind_struct_protocol.h4
-rw-r--r--source3/utils/ntlm_auth.c18
-rw-r--r--source3/winbindd/winbindd_pam.c25
3 files changed, 36 insertions, 11 deletions
diff --git a/source3/nsswitch/winbind_struct_protocol.h b/source3/nsswitch/winbind_struct_protocol.h
index ff52dbddaf..169b4a8c95 100644
--- a/source3/nsswitch/winbind_struct_protocol.h
+++ b/source3/nsswitch/winbind_struct_protocol.h
@@ -202,7 +202,9 @@ typedef struct winbindd_gr {
#define WBFLAG_IS_PRIVILEGED 0x00000400 /* not used */
/* Flag to say this is a winbindd internal send - don't recurse. */
#define WBFLAG_RECURSE 0x00000800
-
+/* Flag to tell winbind the NTLMv2 blob is too big for the struct and is in the
+ * extra_data field */
+#define WBFLAG_BIG_NTLMV2_BLOB 0x00010000
#define WINBINDD_MAX_EXTRA_DATA (128*1024)
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 0a76761cb2..fbb105bfe6 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -380,13 +380,25 @@ NTSTATUS contact_winbind_auth_crap(const char *username,
}
if (nt_response && nt_response->length) {
- memcpy(request.data.auth_crap.nt_resp,
- nt_response->data,
- MIN(nt_response->length, sizeof(request.data.auth_crap.nt_resp)));
+ if (nt_response->length > sizeof(request.data.auth_crap.nt_resp)) {
+ request.flags = request.flags | WBFLAG_BIG_NTLMV2_BLOB;
+ request.extra_len = nt_response->length;
+ request.extra_data.data = SMB_MALLOC_ARRAY(char, request.extra_len);
+ if (request.extra_data.data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ memcpy(request.extra_data.data, nt_response->data,
+ nt_response->length);
+
+ } else {
+ memcpy(request.data.auth_crap.nt_resp,
+ nt_response->data, nt_response->length);
+ }
request.data.auth_crap.nt_resp_len = nt_response->length;
}
result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);
+ SAFE_FREE(request.extra_data.data);
/* Display response */
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 9ff3899661..7de28b08a9 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1854,17 +1854,28 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp)
|| state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) {
- DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n",
- state->request.data.auth_crap.lm_resp_len,
- state->request.data.auth_crap.nt_resp_len));
- result = NT_STATUS_INVALID_PARAMETER;
- goto done;
+ if (!state->request.flags & WBFLAG_BIG_NTLMV2_BLOB ||
+ state->request.extra_len != state->request.data.auth_crap.nt_resp_len) {
+ DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n",
+ state->request.data.auth_crap.lm_resp_len,
+ state->request.data.auth_crap.nt_resp_len));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
}
lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp,
state->request.data.auth_crap.lm_resp_len);
- nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp,
- state->request.data.auth_crap.nt_resp_len);
+
+ if (state->request.flags & WBFLAG_BIG_NTLMV2_BLOB) {
+ nt_resp = data_blob_talloc(state->mem_ctx,
+ state->request.extra_data.data,
+ state->request.data.auth_crap.nt_resp_len);
+ } else {
+ nt_resp = data_blob_talloc(state->mem_ctx,
+ state->request.data.auth_crap.nt_resp,
+ state->request.data.auth_crap.nt_resp_len);
+ }
/* what domain should we contact? */