Re: [ rdesktop-Bugs-2817779 ] Can't connect to WinServ 2008 SP2: "internal license error"

Thomas Uhle <[email protected]> Tue, 20 Sep 2011 23:25:37 +0200 (CEST)
Newsgroups gmane.network.rdesktop.devel
Message-ID <[email protected]>
Hi Peter,

I have done some more investigations on RDP licensing and believe that 
I understand now how it works. Indeed, the terminal server replies with 
a license error message with the error code STATUS_VALID_CLIENT after 
checking the presented CAL when rdesktop is running the second and third 
time. This behaviour corresponds to case 1 in [MS-RDPELE] section 3.2.5.3 
"Processing Client License Information" at http://msdn.microsoft.com/en-us/library/cc241955%28v=prot.10%29.aspx ,
ending the licensing protocol. Yet I wanted to know whether rdesktop 
behaves correctly, so I inserted some additional debug messages to 
licence.c (patch is attached to this e-mail) and realised that the 
licensing protocol is complete only the first time that rdesktop is 
called. The second time, a disconnect PDU is received right after the 
licensing PDU with the CAL was sent. I recognised that licence_process()
in licence.c has no implementation for the cases LICENCE_TAG_RESULT (that 
is if the PDU contains a license error message) and LICENCE_TAG_REISSUE 
(that is if the PDU contains an upgraded permanent license). But that was
not really a problem this time. Then I checked the License Information 
packet built in licence_present() according to [MS-RDPELE] section 2.2.2.3 
"Client License Information" at http://msdn.microsoft.com/en-us/library/cc241919%28v=prot.10%29.aspx ,
which has been almost correct except for the calculation of the packet 
length (which really was a hard job to find out) and the type id for the 
BLOB with the encrypted master secret. After applying these fixes, 
rdesktop again works like a charm (no more "work-arounds" needed). I have 
prepared a unidiff file providing all these patches, which is attached to 
this e-mail. Please feel free to commit these changes to the rdesktop 
repository for being able to close the pending bug #2817779.
Apart from that, I am not sure whether it makes sense to implement the 
missing function for the case LICENCE_TAG_RESULT in licence_process(). 
The information needed to parse a license error message packet can be 
found at http://msdn.microsoft.com/en-us/library/cc240482%28v=prot.10%29.aspx .

Best regards,


Thomas Uhle

------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2dcopy1

_______________________________________________
rdesktop-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rdesktop-devel
rdesktop-licence-patch.diff (text/x-patch, 2.9 KB)
--- licence.c~	2011-04-18 13:21:57 +0200
+++ licence.c	2011-09-20 20:51:03 +0200
@@ -2,6 +2,7 @@
    rdesktop: A Remote Desktop Protocol client.
    RDP licensing negotiation
    Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright (C) Thomas Uhle <[email protected]> 2011
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -60,11 +61,11 @@
 {
 	uint32 sec_flags = SEC_LICENCE_NEG;
 	uint16 length =
-		16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
+		24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
 		licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
 	STREAM s;
 
-	s = sec_init(sec_flags, length + 4);
+	s = sec_init(sec_flags, length + 2);
 
 	out_uint8(s, LICENCE_TAG_PRESENT);
 	out_uint8(s, 2);	/* version */
@@ -75,7 +76,7 @@
 	out_uint16_le(s, 0x0201);
 
 	out_uint8p(s, client_random, SEC_RANDOM_SIZE);
-	out_uint16(s, 0);
+	out_uint16_le(s, 2);
 	out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
 	out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
 	out_uint8s(s, SEC_PADDING_SIZE);
@@ -115,7 +116,7 @@
 	out_uint16_le(s, 0xff01);
 
 	out_uint8p(s, client_random, SEC_RANDOM_SIZE);
-	out_uint16(s, 0);
+	out_uint16_le(s, 2);
 	out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
 	out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
 	out_uint8s(s, SEC_PADDING_SIZE);
@@ -163,11 +164,18 @@
 		ssl_rc4_set_key(&crypt_key, g_licence_key, 16);
 		ssl_rc4_crypt(&crypt_key, hwid, hwid, sizeof(hwid));
 
+#if WITH_DEBUG
+		DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_PRESENT));
+#endif
 		licence_present(null_data, null_data, licence_data, licence_size, hwid, signature);
+
 		xfree(licence_data);
 		return;
 	}
 
+#if WITH_DEBUG
+	DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_REQUEST));
+#endif
 	licence_send_request(null_data, null_data, g_username, g_hostname);
 }
 
@@ -249,6 +257,9 @@
 	ssl_rc4_set_key(&crypt_key, g_licence_key, 16);
 	ssl_rc4_crypt(&crypt_key, hwid, crypt_hwid, LICENCE_HWID_SIZE);
 
+#if WITH_DEBUG
+	DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_AUTHRESP));
+#endif
 	licence_send_authresp(out_token, crypt_hwid, out_sig);
 }
 
@@ -300,6 +311,10 @@
 	in_uint8(s, tag);
 	in_uint8s(s, 3);	/* version, length */
 
+#if WITH_DEBUG
+	DEBUG(("Received licensing PDU (message type 0x%02x)\n", tag));
+#endif
+
 	switch (tag)
 	{
 		case LICENCE_TAG_DEMAND:
@@ -311,14 +326,14 @@
 			break;
 
 		case LICENCE_TAG_ISSUE:
+		case LICENCE_TAG_REISSUE:
 			licence_process_issue(s);
 			break;
 
-		case LICENCE_TAG_REISSUE:
 		case LICENCE_TAG_RESULT:
 			break;
 
 		default:
-			unimpl("licence tag 0x%x\n", tag);
+			unimpl("licence tag 0x%02x\n", tag);
 	}
 }