svn commit: samba r21261 - in branches/SAMBA_4_0/source/torture/rpc: .

metze at samba.org metze at samba.org
Fri Feb 9 17:35:32 GMT 2007


Author: metze
Date: 2007-02-09 17:35:32 +0000 (Fri, 09 Feb 2007)
New Revision: 21261

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=21261

Log:
add support for getting to the plain nthash (and I assume others too)

I wonder what the first 4 bytes are, but the last 16 bytes of the 20 bytes
are the rid crypted hash. The lmhash and the history fields are not verified
yet. But I get the administrators nthash in plain.

metze

Modified:
   branches/SAMBA_4_0/source/torture/rpc/dssync.c


Changeset:
Modified: branches/SAMBA_4_0/source/torture/rpc/dssync.c
===================================================================
--- branches/SAMBA_4_0/source/torture/rpc/dssync.c	2007-02-09 09:44:11 UTC (rev 21260)
+++ branches/SAMBA_4_0/source/torture/rpc/dssync.c	2007-02-09 17:35:32 UTC (rev 21261)
@@ -300,8 +300,39 @@
 	return ret;
 }
 
+static void sam_rid_crypt_len(uint_t rid, uint32_t len, const uint8_t *in, uint8_t *out, int forw)
+{
+	uint8_t s[14];
+	uint8_t in_pad[8], out_pad[8];
+	uint32_t b_off, s_off = 0;
+
+	s[0] = s[4] = s[8] = s[12] = (uint8_t)(rid & 0xFF);
+	s[1] = s[5] = s[9] = s[13] = (uint8_t)((rid >> 8) & 0xFF);
+	s[2] = s[6] = s[10]        = (uint8_t)((rid >> 16) & 0xFF);
+	s[3] = s[7] = s[11]        = (uint8_t)((rid >> 24) & 0xFF);
+
+	for (b_off=0; b_off < len; b_off += 8) {
+		uint32_t left = len - b_off;
+		if (left >= 8) {
+			des_crypt56(out + b_off, in + b_off, s + s_off, forw);
+		} else {
+			ZERO_STRUCT(in_pad);
+			memcpy(in_pad, in + b_off, left);
+			des_crypt56(out_pad, in + b_off, s + s_off, forw);
+			memcpy(out + b_off, out_pad, left);
+			ZERO_STRUCT(out_pad);
+		}
+		if (s_off == 0) {
+			s_off = 7;
+		} else {
+			s_off--;
+		}
+	}
+}
+
 static DATA_BLOB decrypt_blob(TALLOC_CTX *mem_ctx,
 			      const DATA_BLOB *gensec_skey,
+			      bool rcrypt,
 			      struct drsuapi_DsReplicaObjectIdentifier *id,
 			      uint32_t rid,
 			      const DATA_BLOB *buffer)
@@ -313,6 +344,7 @@
 	uint8_t _enc_key[16];
 	DATA_BLOB enc_key;
 
+	DATA_BLOB dec_buffer;
 	DATA_BLOB plain_buffer;
 
 	/*
@@ -344,11 +376,11 @@
 	 * copy the encrypted buffer part and 
 	 * decrypt it using the created encryption key using arcfour
 	 */
-	plain_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length);
-	if (!plain_buffer.data) {
+	dec_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length);
+	if (!dec_buffer.data) {
 		return data_blob_const(NULL, 0);
 	}
-	arcfour_crypt_blob(plain_buffer.data, plain_buffer.length, &enc_key);
+	arcfour_crypt_blob(dec_buffer.data, dec_buffer.length, &enc_key);
 
 	/*
 	 * some attributes seem to be in a usable form after this decryption
@@ -360,15 +392,32 @@
 	 * some attributes seem to have some additional encryption
 	 * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory
 	 *
-	 * it's assumed it's something like this sam_rid_crypt()
-	 * function, as the value is constant, so it doesn't depend
-	 * on sessionkeys. But for the unicodePwd attribute which contains
-	 * the nthash be have 20 bytes at this point, but the ntnash only
-	 * is 16 bytes long, so using the current sam_rid_crypt() function
-	 * doesn't work.
-	 *
-	 * sam_rid_crypt(rid, crypt_nt_hash.hash, plain_nt_hash.hash, 0);
+	 * it's the sam_rid_crypt() function, as the value is constant,
+	 * so it doesn't depend on sessionkeys. But for the unicodePwd attribute
+	 * which contains the nthash has 20 bytes at this point.
+	 * 
+	 * the first 4 byte are unknown yet, but the last 16 byte are the
+	 * rid crypted hash.
 	 */
+	if (rcrypt) {
+		plain_buffer = data_blob_talloc(mem_ctx, dec_buffer.data, dec_buffer.length);
+		if (!plain_buffer.data) {
+			return data_blob_const(NULL, 0);
+		}
+		if (plain_buffer.length < 20) {
+			return data_blob_const(NULL, 0);
+		}
+		/*
+		 * TODO: check if that's correct for the history fields,
+		 *       which can be larger than 16 bytes (but in 16 byte steps)
+		 *       maybe we need to call the 16 byte sam_rid_crypt() function
+		 *       for each hash, but here we assume the rid des key is shifted
+		 *	 by one for each 8 byte block.
+		 */
+		sam_rid_crypt_len(rid, dec_buffer.length - 4, dec_buffer.data + 4, plain_buffer.data + 4, 0);
+	} else {
+		plain_buffer = dec_buffer;
+	}
 
 	return plain_buffer;
 }
@@ -398,6 +447,7 @@
 
 		for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
 			const char *name = NULL;
+			bool rcrypt = false;
 			DATA_BLOB *enc_data = NULL;
 			DATA_BLOB plain_data;
 			struct drsuapi_DsReplicaAttribute *attr;
@@ -406,15 +456,19 @@
 			switch (attr->attid) {
 			case DRSUAPI_ATTRIBUTE_dBCSPwd:
 				name	= "dBCSPwd";
+				rcrypt	= true;
 				break;
 			case DRSUAPI_ATTRIBUTE_unicodePwd:
 				name	= "unicodePwd";
+				rcrypt	= true;
 				break;
 			case DRSUAPI_ATTRIBUTE_ntPwdHistory:
 				name	= "ntPwdHistory";
+				rcrypt	= true;
 				break;
 			case DRSUAPI_ATTRIBUTE_lmPwdHistory:
 				name	= "lmPwdHistory";
+				rcrypt	= true;
 				break;
 			case DRSUAPI_ATTRIBUTE_supplementalCredentials:
 				name	= "supplementalCredentials";
@@ -448,7 +502,7 @@
 			enc_data = attr->value_ctr.values[0].blob;
 			ZERO_STRUCT(plain_data);
 
-			plain_data = decrypt_blob(ctx, gensec_skey,
+			plain_data = decrypt_blob(ctx, gensec_skey, rcrypt,
 						  cur->object.identifier, rid,
 						  enc_data);
 			if (!dn_printed) {
@@ -503,6 +557,14 @@
 
 	highest_usn = lp_parm_int(-1, "dssync", "highest_usn", 0);
 
+	if (lp_parm_bool(-1,"dssync","print_pwd_blobs",False)) {
+		const struct samr_Password *nthash;
+		nthash = cli_credentials_get_nt_hash(ctx->new_dc.credentials, ctx);
+		if (nthash) {
+			DEBUG(0,("CREDENTIALS nthash:\n"));
+			dump_data(0, nthash->hash, sizeof(nthash->hash));
+		}
+	}
 	status = gensec_session_key(ctx->new_dc.drsuapi.pipe->conn->security_state.generic_state,
 				    &gensec_skey);
 	if (!NT_STATUS_IS_OK(status)) {



More information about the samba-cvs mailing list