[OT] Digest authentication session key with ADS

Luke Howard lukeh at PADL.COM
Wed Feb 25 12:26:15 GMT 2004


>In ADS 2003 they added the option to store Digest MD5 hashes which are not
>reverseable. This improves security, but limits the number of Digest
>realms the directory can support to one (per user group) as the realm is
>included in the hash MD5(login:realm:password). How this works in
>combination with domain trusts is still a mystery but I suppose all the
>domains needs to use the same Digest realm for this to make sense.

Presumably there is one realm for one domain.

>The two modes apparently requires different SSP (Digest SSP or Advanced
>Digest SSP) but I honestly can not understand why as the operations
>required by the two SSP is identical and should only require a minor
>difference when the DC is verifying a Digest response (calculate the
>digest hash, or use already calculated digest hash), but I guess this will
>remain a mystery until the internal domain calls have been decoded. Maybe
>there is some subtle reason as to why they have done this not immediately
>apparent. As two different SSP is used there is quite likely two different
>calls to the DC involved.

I suspect that the same RPC is used (NetrLogonSamLogon or NetrLogonSamLogonEx
with a generic information level), but that the package name is different
(perhaps WDigest for the new SSP rather than Digest).

Suggest that you turn off sealing the secure channel for your test web 
server and domain controller, and enable Net Logon debugging on both
machines (nltest /dbflag:1fffffff - output in \windows\debug\netlogon.log).
The latter debug log will include the decrypted logon information, as it
is protected by the secure channel session key (even when sealing the
secure channel is disabled; this is done at the application layer). Search
for NlDecryptRC4 in the debug log.

You may also find the following patch to Ethereal useful; I'm afraid it
is against a rather old revision of packet-dcerpc-netlogon.c, and I 
have not had time to update it.

regards,

-- Luke

-------------- next part --------------
Index: packet-dcerpc-netlogon.c
===================================================================
RCS file: /cvsroot/ethereal/packet-dcerpc-netlogon.c,v
retrieving revision 1.93
diff -u -r1.93 packet-dcerpc-netlogon.c
--- packet-dcerpc-netlogon.c	27 Sep 2003 23:48:04 -0000	1.93
+++ packet-dcerpc-netlogon.c	25 Feb 2004 12:24:23 -0000
@@ -122,6 +122,7 @@
 static int hf_netlogon_logon_srv = -1;
 static int hf_netlogon_principal = -1;
 static int hf_netlogon_logon_dom = -1;
+static int hf_netlogon_logon_pkg_name = -1;
 static int hf_netlogon_downlevel_domain_name = -1;
 static int hf_netlogon_dns_domain_name = -1;
 static int hf_netlogon_domain_name = -1;
@@ -713,6 +714,23 @@
 	return offset;
 }
 
+static int
+netlogon_dissect_GENERIC_INFO(tvbuff_t *tvb, int offset,
+		packet_info *pinfo, proto_tree *tree,
+		char *drep)
+{
+	offset = netlogon_dissect_LOGON_IDENTITY_INFO(tvb, offset,
+		pinfo, tree, drep);
+
+	offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+		hf_netlogon_logon_pkg_name, 0);
+
+	offset = netlogon_dissect_BLOB(tvb, offset,
+		pinfo, tree, drep);
+
+	return offset;
+}
+
 /*
  * IDL typedef [switch_type(short)] union {
  * IDL    [case(1)][unique] INTERACTIVE_INFO *iinfo;
@@ -733,20 +751,28 @@
 	ALIGN_TO_4_BYTES;
 	switch(level){
 	case 1:
+	case 5:
 		offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
 			netlogon_dissect_INTERACTIVE_INFO, NDR_POINTER_UNIQUE,
 			"INTERACTIVE_INFO:", -1);
 		break;
 	case 2:
+	case 6:
 		offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
 			netlogon_dissect_NETWORK_INFO, NDR_POINTER_UNIQUE,
 			"NETWORK_INFO:", -1);
 		break;
 	case 3:
+	case 7:
 		offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
 			netlogon_dissect_SERVICE_INFO, NDR_POINTER_UNIQUE,
 			"SERVICE_INFO:", -1);
 		break;
+	case 4:
+		offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+			netlogon_dissect_GENERIC_INFO, NDR_POINTER_UNIQUE,
+			"GENERIC_INFO:", -1);
+		break;
 	}
 
 	return offset;
@@ -1352,6 +1378,41 @@
 	return offset;
 }
 
+static int
+netlogon_dissect_netrlogonsamlogonwithflags_rqst(tvbuff_t *tvb, int offset,
+	packet_info *pinfo, proto_tree *tree, char *drep)
+{
+	offset = netlogon_dissect_netrlogonsamlogon_rqst(tvb, offset, pinfo, tree, drep);
+
+	offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+		hf_netlogon_reserved, NULL);
+
+	return offset;
+}
+
+static int
+netlogon_dissect_netrlogonsamlogonwithflags_reply(tvbuff_t *tvb, int offset,
+	packet_info *pinfo, proto_tree *tree, char *drep)
+{
+	offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+		netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+		"AUTHENTICATOR: return_authenticator", -1);
+
+	offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+		netlogon_dissect_VALIDATION, NDR_POINTER_REF,
+		"VALIDATION:", -1);
+
+	offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+		hf_netlogon_authoritative, NULL);
+
+	offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+		hf_netlogon_reserved, NULL);
+
+	offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+				  hf_netlogon_rc, NULL);
+
+	return offset;
+}
 
 /*
  * IDL long NetrLogonSamLogoff(
@@ -5823,27 +5884,25 @@
 netlogon_dissect_netrlogonsamlogonex_rqst(tvbuff_t *tvb, int offset,
 	packet_info *pinfo, proto_tree *tree, char *drep)
 {
-	offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
-		NDR_POINTER_UNIQUE, "unknown string", 
-	        hf_netlogon_unknown_string, 0);
+	offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset, pinfo, tree, drep);
 
 	offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
-		NDR_POINTER_UNIQUE, "unknown string", 
-		hf_netlogon_unknown_string, 0);
+		NDR_POINTER_UNIQUE, "Computer Name",
+		hf_netlogon_computer_name, 0);
 
 	offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
-		hf_netlogon_unknown_short, NULL);
+		hf_netlogon_level16, NULL);
 
 	offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-		netlogon_dissect_LEVEL, NDR_POINTER_UNIQUE,
-		"LEVEL pointer: unknown_NETLOGON_LEVEL", -1);
+		netlogon_dissect_LEVEL, NDR_POINTER_REF,
+		"LEVEL: LogonLevel", -1);
 
 	offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
-		hf_netlogon_unknown_short, NULL);
+		hf_netlogon_validation_level, NULL);
+
+	offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+		hf_netlogon_unknown_long, NULL);
 
-	offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-		netlogon_dissect_pointer_long, NDR_POINTER_UNIQUE,
-		"ULONG pointer: unknown_ULONG", hf_netlogon_unknown_long);
 	return offset;
 }
 
@@ -5853,16 +5912,14 @@
 	packet_info *pinfo, proto_tree *tree, char *drep)
 {
 	offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-		netlogon_dissect_VALIDATION, NDR_POINTER_UNIQUE,
-		"VALIDATION: unknown_NETLOGON_VALIDATION", -1);
+		netlogon_dissect_VALIDATION, NDR_POINTER_REF,
+		"VALIDATION:", -1);
 
-	offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-		netlogon_dissect_pointer_char, NDR_POINTER_UNIQUE,
-		"BOOLEAN pointer: unknown_BOOLEAN", hf_netlogon_unknown_char);
+	offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+		hf_netlogon_authoritative, NULL);
 
-	offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
-		netlogon_dissect_pointer_long, NDR_POINTER_UNIQUE,
-		"ULONG pointer: unknown_ULONG", hf_netlogon_unknown_long);
+	offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+		hf_netlogon_unknown_long, NULL);
 
 	offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
 				  hf_netlogon_rc, NULL);
@@ -6164,7 +6221,8 @@
 	{ NETLOGON_NETRGETFORESTTRUSTINFORMATION, "NetrGetForestTrustInformation",
 		NULL, NULL },
 	{ NETLOGON_NETRLOGONSAMLOGONWITHFLAGS, "NetrLogonSamLogonWithFlags", 
-		NULL, NULL },
+		netlogon_dissect_netrlogonsamlogonwithflags_rqst,
+		netlogon_dissect_netrlogonsamlogonwithflags_reply },
 	{ NETLOGON_NETRSERVERGETTRUSTINFO, "NetrServerGetTrustInfo",
 		NULL, NULL },
         {0, NULL, NULL,  NULL }
@@ -6460,6 +6518,10 @@
 		{ "Domain", "netlogon.domain", FT_STRING, BASE_NONE,
 		NULL, 0, "Domain", HFILL }},
 
+	{ &hf_netlogon_logon_pkg_name,
+		{ "Package", "netlogon.package_name", FT_STRING, BASE_NONE,
+		NULL, 0, "Package", HFILL }},
+
 	{ &hf_netlogon_computer_name,
 		{ "Computer Name", "netlogon.computer_name", FT_STRING, BASE_NONE,
 		NULL, 0, "Computer Name", HFILL }},


More information about the samba-technical mailing list