diff options
author | Andrew Bartlett <abartlet@samba.org> | 2002-05-26 14:59:57 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2002-05-26 14:59:57 +0000 |
commit | 069e6fb9eb4a0bf6720cbbf493d0cb36baac9580 (patch) | |
tree | 27461d24724e16992e070157d7ff1e22d2b0e50f | |
parent | 34728ec659751f2e14cfb8502300f3fdb96d405a (diff) | |
download | samba-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.h | 13 | ||||
-rw-r--r-- | source3/libsmb/clispnego.c | 43 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 66 |
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); } |