summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2002-05-26 14:59:57 +0000
committerAndrew Bartlett <abartlet@samba.org>2002-05-26 14:59:57 +0000
commit069e6fb9eb4a0bf6720cbbf493d0cb36baac9580 (patch)
tree27461d24724e16992e070157d7ff1e22d2b0e50f
parent34728ec659751f2e14cfb8502300f3fdb96d405a (diff)
downloadsamba-069e6fb9eb4a0bf6720cbbf493d0cb36baac9580.tar.gz
samba-069e6fb9eb4a0bf6720cbbf493d0cb36baac9580.tar.bz2
samba-069e6fb9eb4a0bf6720cbbf493d0cb36baac9580.zip
Add support for NTLMv2 (tested!) with NTLMSSP.
The problem was the NTLMv2 uses extra data in order to make reply/lookup more difficult. That extra data includes the hostname, and the domain. This matches Win2k (sort of) by sending this information. Win2k connects with LMCompatibilityLevel=5 without a problem. We can change the negotiation bits if we want, this should allow us to make NTLMv2 the default for other clients as well. Some of the extra #defines were found in the squid source. Andrew Bartlett (This used to be commit 17a5f67b3d1935baf6197ae967624eb847b66ac8)
-rw-r--r--source3/include/rpc_dce.h13
-rw-r--r--source3/libsmb/clispnego.c43
-rw-r--r--source3/smbd/sesssetup.c66
3 files changed, 101 insertions, 21 deletions
diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h
index 01d974d41d..d46f9def39 100644
--- a/source3/include/rpc_dce.h
+++ b/source3/include/rpc_dce.h
@@ -61,15 +61,22 @@ enum NTLM_MESSAGE_TYPE
#define NTLMSSP_REQUEST_TARGET 0x00000004
#define NTLMSSP_NEGOTIATE_SIGN 0x00000010
#define NTLMSSP_NEGOTIATE_SEAL 0x00000020
+#define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE 0x00000040
#define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
+#define NTLMSSP_NEGOTIATE_NETWARE 0x00000100
#define NTLMSSP_NEGOTIATE_NTLM 0x00000200
-#define NTLMSSP_NEGOTIATE_00001000 0x00001000
-#define NTLMSSP_NEGOTIATE_00002000 0x00002000
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000
+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
+#define NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL 0x00004000
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
+#define NTLMSSP_CHAL_INIT_RESPONSE 0x00010000
+#define NTLMSSP_CHAL_ACCEPT_RESPONSE 0x00020000
+#define NTLMSSP_CHAL_NON_NT_SESSION_KEY 0x00040000
#define NTLMSSP_NEGOTIATE_NTLM2 0x00080000
-#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000
+#define NTLMSSP_CHAL_TARGET_INFO 0x00800000
#define NTLMSSP_NEGOTIATE_128 0x20000000
#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
+#define NTLMSSP_NEGOTIATE_080000000 0x80000000
#define SMBD_NTLMSSP_NEG_FLAGS 0x000082b1
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index a4fcfa5d9a..469b946088 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -549,7 +549,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
format specifiers are:
- U = unicode string (input is unix string)
+ U = unicode string (output is unix string)
B = data blob
b = data blob in header
d = word (4 bytes)
@@ -620,3 +620,44 @@ BOOL msrpc_parse(DATA_BLOB *blob,
return True;
}
+
+/**
+ * Print out the NTLMSSP flags for debugging
+ */
+
+void debug_ntlmssp_flags(uint32 neg_flags)
+{
+ if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_UNICODE\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_OEM)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_OEM\n"));
+ if (neg_flags & NTLMSSP_REQUEST_TARGET)
+ DEBUG(4, (" NTLMSSP_REQUEST_TARGET\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_SIGN\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_SEAL\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_NETWARE\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_NTLM)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_NTLM\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_NTLM2\n"));
+ if (neg_flags & NTLMSSP_CHAL_TARGET_INFO)
+ DEBUG(4, (" NTLMSSP_CHAL_TARGET_INFO\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_128)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_128\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
+}
+
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 66eb6a2d92..cdddb37932 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -235,11 +235,13 @@ static int reply_spnego_negotiate(connection_struct *conn,
char *OIDs[ASN1_MAX_OIDS];
DATA_BLOB secblob;
int i;
- uint32 ntlmssp_command, neg_flags;
- DATA_BLOB sess_key, chal, spnego_chal;
+ uint32 ntlmssp_command, neg_flags, chal_flags;
+ DATA_BLOB sess_key, chal, spnego_chal, extra_data;
+ char *workstation, *domain;
const uint8 *cryptkey;
BOOL got_kerberos = False;
NTSTATUS nt_status;
+ extern pstring global_myname;
/* parse out the OIDs and the first sec blob */
if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
@@ -274,18 +276,23 @@ static int reply_spnego_negotiate(connection_struct *conn,
"NTLMSSP",
&ntlmssp_command,
&neg_flags,
- &sess_key)) {
+ &extra_data)) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
+
+ DEBUG(5, ("Extra data: \n"));
+ dump_data(5, extra_data.data, extra_data.length);
data_blob_free(&secblob);
- data_blob_free(&sess_key);
+ data_blob_free(&extra_data);
if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- DEBUG(3,("Got neg_flags=%08x\n", neg_flags));
+ DEBUG(3,("Got neg_flags=0x%08x\n", neg_flags));
+
+ debug_ntlmssp_flags(neg_flags);
if (ntlmssp_auth_context) {
(ntlmssp_auth_context->free)(&ntlmssp_auth_context);
@@ -300,22 +307,47 @@ static int reply_spnego_negotiate(connection_struct *conn,
/* Give them the challenge. For now, ignore neg_flags and just
return the flags we want. Obviously this is not correct */
- neg_flags = NTLMSSP_NEGOTIATE_UNICODE |
+ chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
NTLMSSP_NEGOTIATE_LM_KEY |
- NTLMSSP_NEGOTIATE_NTLM;
-
- msrpc_gen(&chal, "Cddddbdddd",
- "NTLMSSP",
- NTLMSSP_CHALLENGE,
- 0,
- 0x30, /* ?? */
- neg_flags,
- cryptkey, 8,
- 0, 0, 0,
- 0x3000); /* ?? */
+ NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_CHAL_TARGET_INFO;
+
+ {
+ DATA_BLOB domain_blob, netbios_blob, realm_blob, ident_info_blob;
+
+ msrpc_gen(&domain_blob,
+ "U",
+ lp_workgroup());
+
+ msrpc_gen(&netbios_blob,
+ "U",
+ global_myname);
+
+ msrpc_gen(&realm_blob,
+ "U",
+ lp_realm());
+
+
+ msrpc_gen(&chal, "CddddbBBBB",
+ "NTLMSSP",
+ NTLMSSP_CHALLENGE,
+ 0,
+ 0x30, /* ?? */
+ chal_flags,
+ cryptkey, 8,
+ domain_blob.data, domain_blob.length,
+ domain_blob.data, domain_blob.length,
+ netbios_blob.data, netbios_blob.length,
+ realm_blob.data, realm_blob.length);
+
+ data_blob_free(&domain_blob);
+ data_blob_free(&netbios_blob);
+ data_blob_free(&realm_blob);
+ }
if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
DEBUG(3,("Failed to generate challenge\n"));
+ data_blob_free(&chal);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}