crypto: add decrypt_drsuapi_blob from samba4.
authorGünther Deschner <gd@samba.org>
Mon, 23 Jun 2008 14:02:04 +0000 (16:02 +0200)
committerGünther Deschner <gd@samba.org>
Tue, 24 Jun 2008 21:44:20 +0000 (23:44 +0200)
Guenther
(This used to be commit 3b6352a60e6683963af1641786f9c230d49ebfb5)

source3/include/proto.h
source3/libsmb/smbencrypt.c

index 75b616b300f8e61b2de9876bb4af0bb9c5b45f05..79a9251194fef023b1c69686b2cfba7ae80df7ee 100644 (file)
@@ -5134,6 +5134,11 @@ WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
                                          struct wkssvc_PasswordBuffer *pwd_buf,
                                          DATA_BLOB *session_key,
                                          char **pwd);
+DATA_BLOB decrypt_drsuapi_blob(TALLOC_CTX *mem_ctx,
+                              const DATA_BLOB *session_key,
+                              bool rcrypt,
+                              uint32_t rid,
+                              const DATA_BLOB *buffer);
 
 /* The following definitions come from libsmb/smberr.c  */
 
index a8a88a8a7e452d6a8432a9b78d2905c049282186..0742976635307b09df68238220c4557028fd1dc4 100644 (file)
@@ -782,3 +782,117 @@ WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
 
        return WERR_OK;
 }
+
+DATA_BLOB decrypt_drsuapi_blob(TALLOC_CTX *mem_ctx,
+                              const DATA_BLOB *session_key,
+                              bool rcrypt,
+                              uint32_t rid,
+                              const DATA_BLOB *buffer)
+{
+       DATA_BLOB confounder;
+       DATA_BLOB enc_buffer;
+
+       struct MD5Context md5;
+       uint8_t _enc_key[16];
+       DATA_BLOB enc_key;
+
+       DATA_BLOB dec_buffer;
+
+       uint32_t crc32_given;
+       uint32_t crc32_calc;
+       DATA_BLOB checked_buffer;
+
+       DATA_BLOB plain_buffer;
+
+       /*
+        * the combination "c[3] s[1] e[1] d[0]..."
+        * was successful!!!!!!!!!!!!!!!!!!!!!!!!!!
+        */
+
+       /*
+        * the first 16 bytes at the beginning are the confounder
+        * followed by the 4 byte crc32 checksum
+        */
+       if (buffer->length < 20) {
+               return data_blob_const(NULL, 0);
+       }
+       confounder = data_blob_const(buffer->data, 16);
+       enc_buffer = data_blob_const(buffer->data + 16, buffer->length - 16);
+
+       /*
+        * build the encryption key md5 over the session key followed
+        * by the confounder
+        *
+        * here the gensec session key is used and
+        * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key!
+        */
+       enc_key = data_blob_const(_enc_key, sizeof(_enc_key));
+       MD5Init(&md5);
+       MD5Update(&md5, session_key->data, session_key->length);
+       MD5Update(&md5, confounder.data, confounder.length);
+       MD5Final(enc_key.data, &md5);
+
+       /*
+        * copy the encrypted buffer part and
+        * decrypt it using the created encryption key using arcfour
+        */
+       dec_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length);
+       if (!dec_buffer.data) {
+               return data_blob_const(NULL, 0);
+       }
+       SamOEMhashBlob(dec_buffer.data, dec_buffer.length, &enc_key);
+
+       /*
+        * the first 4 byte are the crc32 checksum
+        * of the remaining bytes
+        */
+       crc32_given = IVAL(dec_buffer.data, 0);
+       crc32_calc = crc32_calc_buffer((const char *)dec_buffer.data + 4 , dec_buffer.length - 4);
+       if (crc32_given != crc32_calc) {
+               DEBUG(1,("CRC32: given[0x%08X] calc[0x%08X]\n",
+                     crc32_given, crc32_calc));
+               return data_blob_const(NULL, 0);
+       }
+       checked_buffer = data_blob_talloc(mem_ctx, dec_buffer.data + 4, dec_buffer.length - 4);
+       if (!checked_buffer.data) {
+               return data_blob_const(NULL, 0);
+       }
+
+       /*
+        * some attributes seem to be in a usable form after this decryption
+        * (supplementalCredentials, priorValue, currentValue, trustAuthOutgoing,
+        *  trustAuthIncoming, initialAuthOutgoing, initialAuthIncoming)
+        * At least supplementalCredentials contains plaintext
+        * like "Primary:Kerberos" (in unicode form)
+        *
+        * some attributes seem to have some additional encryption
+        * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory
+        *
+        * it's the sam_rid_crypt() function, as the value is constant,
+        * so it doesn't depend on sessionkeys.
+        */
+       if (rcrypt) {
+               uint32_t i, num_hashes;
+
+               if ((checked_buffer.length % 16) != 0) {
+                       return data_blob_const(NULL, 0);
+               }
+
+               plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length);
+               if (!plain_buffer.data) {
+                       return data_blob_const(NULL, 0);
+               }
+
+               num_hashes = plain_buffer.length / 16;
+               for (i = 0; i < num_hashes; i++) {
+                       uint32_t offset = i * 16;
+                       sam_pwd_hash(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0);
+               }
+       } else {
+               plain_buffer = checked_buffer;
+       }
+
+       return plain_buffer;
+}
+
+