Move DRSUAPI per-attribute decryption into a common file
authorAndrew Bartlett <abartlet@samba.org>
Mon, 16 Mar 2009 04:20:28 +0000 (15:20 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 14 Apr 2009 04:19:39 +0000 (14:19 +1000)
This file (contining metze's decryption routines) is now also be used by
Samba3's DRSUAPI implementation

Andrew Bartlett

libcli/drsuapi/config.mk [new file with mode: 0644]
libcli/drsuapi/drsuapi.h [new file with mode: 0644]
libcli/drsuapi/repl_decrypt.c [new file with mode: 0644]
source3/libnet/libnet_dssync.c
source4/dsdb/config.mk
source4/dsdb/repl/replicated_objects.c
source4/main.mk
source4/torture/config.mk
source4/torture/rpc/dssync.c

diff --git a/libcli/drsuapi/config.mk b/libcli/drsuapi/config.mk
new file mode 100644 (file)
index 0000000..cb002ca
--- /dev/null
@@ -0,0 +1,8 @@
+[SUBSYSTEM::LIBCLI_DRSUAPI]
+PUBLIC_DEPENDENCIES = \
+               LIBCLI_AUTH
+
+LIBCLI_DRSUAPI_OBJ_FILES = $(addprefix $(libclicommonsrcdir)/drsuapi/, \
+               repl_decrypt.o)
+
+PUBLIC_HEADERS += ../libcli/drsuapi/drsuapi.h
diff --git a/libcli/drsuapi/drsuapi.h b/libcli/drsuapi/drsuapi.h
new file mode 100644 (file)
index 0000000..b953507
--- /dev/null
@@ -0,0 +1,33 @@
+/* 
+   Unix SMB/CIFS mplementation.
+   Helper functions for applying replicated objects
+   
+   Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
+    
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   
+*/
+
+WERROR drsuapi_decrypt_attribute_value(TALLOC_CTX *mem_ctx,
+                                      const DATA_BLOB *gensec_skey,
+                                      bool rid_crypt,
+                                      uint32_t rid,
+                                      DATA_BLOB *in,
+                                      DATA_BLOB *out);
+
+WERROR drsuapi_decrypt_attribute(TALLOC_CTX *mem_ctx, 
+                                const DATA_BLOB *gensec_skey,
+                                uint32_t rid,
+                                struct drsuapi_DsReplicaAttribute *attr);
+
diff --git a/libcli/drsuapi/repl_decrypt.c b/libcli/drsuapi/repl_decrypt.c
new file mode 100644 (file)
index 0000000..9d7c1b6
--- /dev/null
@@ -0,0 +1,188 @@
+/* 
+   Unix SMB/CIFS mplementation.
+   Helper functions for applying replicated objects
+   
+   Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
+    
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+   
+*/
+
+#include "includes.h"
+#include "../lib/util/dlinklist.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "librpc/gen_ndr/ndr_drsuapi.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "../lib/crypto/crypto.h"
+#include "../libcli/drsuapi/drsuapi.h"
+#include "libcli/auth/libcli_auth.h"
+
+WERROR drsuapi_decrypt_attribute_value(TALLOC_CTX *mem_ctx,
+                                      const DATA_BLOB *gensec_skey,
+                                      bool rid_crypt,
+                                      uint32_t rid,
+                                      DATA_BLOB *in,
+                                      DATA_BLOB *out)
+{
+       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;
+
+       /*
+        * users with rid == 0 should not exist
+        */
+       if (rid_crypt && rid == 0) {
+               return WERR_DS_DRA_INVALID_PARAMETER;
+       }
+
+       /* 
+        * the first 16 bytes at the beginning are the confounder
+        * followed by the 4 byte crc32 checksum
+        */
+       if (in->length < 20) {
+               return WERR_DS_DRA_INVALID_PARAMETER;
+       }
+       confounder = data_blob_const(in->data, 16);
+       enc_buffer = data_blob_const(in->data + 16, in->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, gensec_skey->data, gensec_skey->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_const(enc_buffer.data, enc_buffer.length);
+       arcfour_crypt_blob(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(dec_buffer.data + 4 , dec_buffer.length - 4);
+       if (crc32_given != crc32_calc) {
+               return WERR_SEC_E_DECRYPT_FAILURE;
+       }
+       checked_buffer = data_blob_const(dec_buffer.data + 4, dec_buffer.length - 4);
+
+       plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length);
+       W_ERROR_HAVE_NO_MEMORY(plain_buffer.data);
+
+       /*
+        * The following rid_crypt obfuscation isn't session specific
+        * and not really needed here, because we allways know the rid of the
+        * user account.
+        *
+        * some attributes with this 'additional encryption' include
+        * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory
+        *
+        * But for the rest of samba it's easier when we remove this static
+        * obfuscation here
+        */
+       if (rid_crypt) {
+               uint32_t i, num_hashes;
+
+               if ((checked_buffer.length % 16) != 0) {
+                       return WERR_DS_DRA_INVALID_PARAMETER;
+               }
+
+               num_hashes = plain_buffer.length / 16;
+               for (i = 0; i < num_hashes; i++) {
+                       uint32_t offset = i * 16;
+                       sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0);
+               }
+       }
+
+       *out = plain_buffer;
+       return WERR_OK;
+}
+
+WERROR drsuapi_decrypt_attribute(TALLOC_CTX *mem_ctx, 
+                                const DATA_BLOB *gensec_skey,
+                                uint32_t rid,
+                                struct drsuapi_DsReplicaAttribute *attr)
+{
+       WERROR status;
+       DATA_BLOB *enc_data;
+       DATA_BLOB plain_data;
+       bool rid_crypt = false;
+
+       if (attr->value_ctr.num_values == 0) {
+               return WERR_OK;
+       }
+
+       switch (attr->attid) {
+       case DRSUAPI_ATTRIBUTE_dBCSPwd:
+       case DRSUAPI_ATTRIBUTE_unicodePwd:
+       case DRSUAPI_ATTRIBUTE_ntPwdHistory:
+       case DRSUAPI_ATTRIBUTE_lmPwdHistory:
+               rid_crypt = true;
+               break;
+       case DRSUAPI_ATTRIBUTE_supplementalCredentials:
+       case DRSUAPI_ATTRIBUTE_priorValue:
+       case DRSUAPI_ATTRIBUTE_currentValue:
+       case DRSUAPI_ATTRIBUTE_trustAuthOutgoing:
+       case DRSUAPI_ATTRIBUTE_trustAuthIncoming:
+       case DRSUAPI_ATTRIBUTE_initialAuthOutgoing:
+       case DRSUAPI_ATTRIBUTE_initialAuthIncoming:
+               break;
+       default:
+               return WERR_OK;
+       }
+
+       if (attr->value_ctr.num_values > 1) {
+               return WERR_DS_DRA_INVALID_PARAMETER;
+       }
+
+       if (!attr->value_ctr.values[0].blob) {
+               return WERR_DS_DRA_INVALID_PARAMETER;
+       }
+
+       enc_data        = attr->value_ctr.values[0].blob;
+
+       status = drsuapi_decrypt_attribute_value(mem_ctx,
+                                                gensec_skey,
+                                                rid_crypt,
+                                                rid,
+                                                enc_data,
+                                                &plain_data);
+       W_ERROR_NOT_OK_RETURN(status);
+
+       talloc_free(attr->value_ctr.values[0].blob->data);
+       *attr->value_ctr.values[0].blob = plain_data;
+
+       return WERR_OK;
+}
index 746b09635dc673403353a3edc5899fb7f768ec41..59feac249569e41d7b397bc51f498248904c75dc 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "includes.h"
 #include "libnet/libnet.h"
+#include "../libcli/drsuapi/drsuapi.h"
 
 /****************************************************************
 ****************************************************************/
@@ -61,49 +62,6 @@ NTSTATUS libnet_dssync_init_context(TALLOC_CTX *mem_ctx,
 /****************************************************************
 ****************************************************************/
 
-static DATA_BLOB *decrypt_attr_val(TALLOC_CTX *mem_ctx,
-                                  DATA_BLOB *session_key,
-                                  uint32_t rid,
-                                  enum drsuapi_DsAttributeId id,
-                                  DATA_BLOB *raw_data)
-{
-       bool rcrypt = false;
-       DATA_BLOB out_data;
-
-       ZERO_STRUCT(out_data);
-
-       switch (id) {
-               case DRSUAPI_ATTRIBUTE_dBCSPwd:
-               case DRSUAPI_ATTRIBUTE_unicodePwd:
-               case DRSUAPI_ATTRIBUTE_ntPwdHistory:
-               case DRSUAPI_ATTRIBUTE_lmPwdHistory:
-                       rcrypt  = true;
-                       break;
-               case DRSUAPI_ATTRIBUTE_supplementalCredentials:
-               case DRSUAPI_ATTRIBUTE_priorValue:
-               case DRSUAPI_ATTRIBUTE_currentValue:
-               case DRSUAPI_ATTRIBUTE_trustAuthOutgoing:
-               case DRSUAPI_ATTRIBUTE_trustAuthIncoming:
-               case DRSUAPI_ATTRIBUTE_initialAuthOutgoing:
-               case DRSUAPI_ATTRIBUTE_initialAuthIncoming:
-                       break;
-               default:
-                       return raw_data;
-       }
-
-       out_data = decrypt_drsuapi_blob(mem_ctx, session_key, rcrypt,
-                                         rid, raw_data);
-
-       if (out_data.length) {
-               return (DATA_BLOB *)talloc_memdup(mem_ctx, &out_data, sizeof(DATA_BLOB));
-       }
-
-       return raw_data;
-}
-
-/****************************************************************
-****************************************************************/
-
 static void parse_obj_identifier(struct drsuapi_DsReplicaObjectIdentifier *id,
                                 uint32_t *rid)
 {
@@ -121,30 +79,6 @@ static void parse_obj_identifier(struct drsuapi_DsReplicaObjectIdentifier *id,
 /****************************************************************
 ****************************************************************/
 
-static void parse_obj_attribute(TALLOC_CTX *mem_ctx,
-                               DATA_BLOB *session_key,
-                               uint32_t rid,
-                               struct drsuapi_DsReplicaAttribute *attr)
-{
-       int i = 0;
-
-       for (i=0; i<attr->value_ctr.num_values; i++) {
-
-               DATA_BLOB *plain_data = NULL;
-
-               plain_data = decrypt_attr_val(mem_ctx,
-                                             session_key,
-                                             rid,
-                                             attr->attid,
-                                             attr->value_ctr.values[i].blob);
-
-               attr->value_ctr.values[i].blob = plain_data;
-       }
-}
-
-/****************************************************************
-****************************************************************/
-
 static void libnet_dssync_decrypt_attributes(TALLOC_CTX *mem_ctx,
                                             DATA_BLOB *session_key,
                                             struct drsuapi_DsReplicaObjectListItemEx *cur)
@@ -170,10 +104,10 @@ static void libnet_dssync_decrypt_attributes(TALLOC_CTX *mem_ctx,
                                continue;
                        }
 
-                       parse_obj_attribute(mem_ctx,
-                                           session_key,
-                                           rid,
-                                           attr);
+                       drsuapi_decrypt_attribute(mem_ctx,
+                                                 session_key,
+                                                 rid,
+                                                 attr);
                }
        }
 }
index 8d1647953f8799141c1634a191ea9d9e8938335f..0895a1dd86696c5bb23c364b1f79363242df6935 100644 (file)
@@ -8,7 +8,8 @@ mkinclude samdb/ldb_modules/config.mk
 PUBLIC_DEPENDENCIES = HEIMDAL_KRB5 
 PRIVATE_DEPENDENCIES = LIBNDR NDR_DRSUAPI NDR_DRSBLOBS NSS_WRAPPER \
                                           auth_system_session LDAP_ENCODE LIBCLI_AUTH LIBNDR \
-                                          SAMDB_SCHEMA LDB_WRAP SAMDB_COMMON
+                                          SAMDB_SCHEMA LDB_WRAP SAMDB_COMMON \
+                                               LIBCLI_DRSUAPI
 
 
 SAMDB_OBJ_FILES = $(addprefix $(dsdbsrcdir)/, \
index 560f75da7a15272e11958d7536e60215dd12961e..78af3c8f6df35c530146c713c16bd027501e255e 100644 (file)
 #include "librpc/gen_ndr/ndr_drsuapi.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
 #include "../lib/crypto/crypto.h"
+#include "../libcli/drsuapi/drsuapi.h"
 #include "libcli/auth/libcli_auth.h"
 #include "param/param.h"
 
-static WERROR dsdb_decrypt_attribute_value(TALLOC_CTX *mem_ctx,
-                                          const DATA_BLOB *gensec_skey,
-                                          bool rid_crypt,
-                                          uint32_t rid,
-                                          DATA_BLOB *in,
-                                          DATA_BLOB *out)
-{
-       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;
-
-       /*
-        * users with rid == 0 should not exist
-        */
-       if (rid_crypt && rid == 0) {
-               return WERR_DS_DRA_INVALID_PARAMETER;
-       }
-
-       /* 
-        * the first 16 bytes at the beginning are the confounder
-        * followed by the 4 byte crc32 checksum
-        */
-       if (in->length < 20) {
-               return WERR_DS_DRA_INVALID_PARAMETER;
-       }
-       confounder = data_blob_const(in->data, 16);
-       enc_buffer = data_blob_const(in->data + 16, in->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, gensec_skey->data, gensec_skey->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_const(enc_buffer.data, enc_buffer.length);
-       arcfour_crypt_blob(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(dec_buffer.data + 4 , dec_buffer.length - 4);
-       if (crc32_given != crc32_calc) {
-               return WERR_SEC_E_DECRYPT_FAILURE;
-       }
-       checked_buffer = data_blob_const(dec_buffer.data + 4, dec_buffer.length - 4);
-
-       plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length);
-       W_ERROR_HAVE_NO_MEMORY(plain_buffer.data);
-
-       /*
-        * The following rid_crypt obfuscation isn't session specific
-        * and not really needed here, because we allways know the rid of the
-        * user account.
-        *
-        * But for the rest of samba it's easier when we remove this static
-        * obfuscation here
-        */
-       if (rid_crypt) {
-               uint32_t i, num_hashes;
-
-               if ((checked_buffer.length % 16) != 0) {
-                       return WERR_DS_DRA_INVALID_PARAMETER;
-               }
-
-               num_hashes = plain_buffer.length / 16;
-               for (i = 0; i < num_hashes; i++) {
-                       uint32_t offset = i * 16;
-                       sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0);
-               }
-       }
-
-       *out = plain_buffer;
-       return WERR_OK;
-}
-
-static WERROR dsdb_decrypt_attribute(const DATA_BLOB *gensec_skey,
-                                    uint32_t rid,
-                                    struct drsuapi_DsReplicaAttribute *attr)
-{
-       WERROR status;
-       TALLOC_CTX *mem_ctx;
-       DATA_BLOB *enc_data;
-       DATA_BLOB plain_data;
-       bool rid_crypt = false;
-
-       if (attr->value_ctr.num_values == 0) {
-               return WERR_OK;
-       }
-
-       switch (attr->attid) {
-       case DRSUAPI_ATTRIBUTE_dBCSPwd:
-       case DRSUAPI_ATTRIBUTE_unicodePwd:
-       case DRSUAPI_ATTRIBUTE_ntPwdHistory:
-       case DRSUAPI_ATTRIBUTE_lmPwdHistory:
-               rid_crypt = true;
-               break;
-       case DRSUAPI_ATTRIBUTE_supplementalCredentials:
-       case DRSUAPI_ATTRIBUTE_priorValue:
-       case DRSUAPI_ATTRIBUTE_currentValue:
-       case DRSUAPI_ATTRIBUTE_trustAuthOutgoing:
-       case DRSUAPI_ATTRIBUTE_trustAuthIncoming:
-       case DRSUAPI_ATTRIBUTE_initialAuthOutgoing:
-       case DRSUAPI_ATTRIBUTE_initialAuthIncoming:
-               break;
-       default:
-               return WERR_OK;
-       }
-
-       if (attr->value_ctr.num_values > 1) {
-               return WERR_DS_DRA_INVALID_PARAMETER;
-       }
-
-       if (!attr->value_ctr.values[0].blob) {
-               return WERR_DS_DRA_INVALID_PARAMETER;
-       }
-
-       mem_ctx         = attr->value_ctr.values[0].blob;
-       enc_data        = attr->value_ctr.values[0].blob;
-
-       status = dsdb_decrypt_attribute_value(mem_ctx,
-                                             gensec_skey,
-                                             rid_crypt,
-                                             rid,
-                                             enc_data,
-                                             &plain_data);
-       W_ERROR_NOT_OK_RETURN(status);
-
-       talloc_free(attr->value_ctr.values[0].blob->data);
-       *attr->value_ctr.values[0].blob = plain_data;
-
-       return WERR_OK;
-}
-
 static WERROR dsdb_convert_object(struct ldb_context *ldb,
                                  const struct dsdb_schema *schema,
                                  struct dsdb_extended_replicated_objects *ctr,
@@ -279,7 +123,7 @@ static WERROR dsdb_convert_object(struct ldb_context *ldb,
                m = &md->ctr.ctr1.array[i];
                e = &msg->elements[i];
 
-               status = dsdb_decrypt_attribute(gensec_skey, rid, a);
+               status = drsuapi_decrypt_attribute(a->value_ctr.values[0].blob, gensec_skey, rid, a);
                W_ERROR_NOT_OK_RETURN(status);
 
                status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, a, msg->elements, e);
index f4314e37422dbd20779f7f88daeed424d5759ef6..c62aba742ea2d0f95284c67e1cfcfa2ac14ff52b 100644 (file)
@@ -54,4 +54,5 @@ mkinclude ../lib/async_req/config.mk
 mkinclude ../libcli/security/config.mk
 mkinclude ../libcli/ldap/config.mk
 mkinclude ../libcli/auth/config.mk
+mkinclude ../libcli/drsuapi/config.mk
 
index 895fef617452aa24a8a9486510c87e9227b911c9..bec2a064dc1227eb5fa107129f675f8f5a67bc7f 100644 (file)
@@ -111,7 +111,7 @@ PRIVATE_DEPENDENCIES = \
                RPC_NDR_SRVSVC RPC_NDR_WKSSVC RPC_NDR_ROT RPC_NDR_DSSETUP \
                RPC_NDR_REMACT RPC_NDR_OXIDRESOLVER RPC_NDR_NTSVCS WB_HELPER LIBSAMBA-NET \
                LIBCLI_AUTH POPT_CREDENTIALS TORTURE_LDAP TORTURE_LDB TORTURE_UTIL TORTURE_RAP \
-               dcerpc_server service process_model ntvfs SERVICE_SMB RPC_NDR_BROWSER
+               dcerpc_server service process_model ntvfs SERVICE_SMB RPC_NDR_BROWSER LIBCLI_DRSUAPI
 
 torture_rpc_OBJ_FILES = $(addprefix $(torturesrcdir)/rpc/, \
                join.o lsa.o lsa_lookup.o session_key.o echo.o dfs.o drsuapi.o \
index 1aaf914ceb8af7e7e790eb10717e5e410be81682..b47564cc91dc09bd8afc09c2ffaea709a41eb06d 100644 (file)
@@ -30,6 +30,7 @@
 #include "torture/ldap/proto.h"
 #include "libcli/auth/libcli_auth.h"
 #include "../lib/crypto/crypto.h"
+#include "../libcli/drsuapi/drsuapi.h"
 #include "auth/credentials/credentials.h"
 #include "libcli/auth/libcli_auth.h"
 #include "auth/gensec/gensec.h"
@@ -338,119 +339,6 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx)
        return ret;
 }
 
-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)
-{
-       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, gensec_skey->data, gensec_skey->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);
-       }
-       arcfour_crypt_blob(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(dec_buffer.data + 4 , dec_buffer.length - 4);
-       if (crc32_given != crc32_calc) {
-               DEBUG(0,("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_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0);
-               }
-       } else {
-               plain_buffer = checked_buffer;
-       }
-
-       return plain_buffer;
-}
-
 static void test_analyse_objects(struct torture_context *tctx, 
                                 struct DsSyncTest *ctx,
                                 const DATA_BLOB *gensec_skey,
@@ -481,6 +369,7 @@ static void test_analyse_objects(struct torture_context *tctx,
                }
 
                for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
+                       WERROR werr;
                        const char *name = NULL;
                        bool rcrypt = false;
                        DATA_BLOB *enc_data = NULL;
@@ -549,9 +438,13 @@ static void test_analyse_objects(struct torture_context *tctx,
                        enc_data = attr->value_ctr.values[0].blob;
                        ZERO_STRUCT(plain_data);
 
-                       plain_data = decrypt_blob(ctx, gensec_skey, rcrypt,
-                                                 cur->object.identifier, rid,
-                                                 enc_data);
+                       werr = drsuapi_decrypt_attribute_value(ctx, gensec_skey, rcrypt,
+                                                              rid,
+                                                              enc_data, &plain_data);
+                       if (!W_ERROR_IS_OK(werr)) {
+                               DEBUG(0, ("Failed to decrypt %s\n", name));
+                               continue;
+                       }
                        if (!dn_printed) {
                                object_id++;
                                DEBUG(0,("DN[%u] %s\n", object_id, dn));