Use common samsync delta decryption functions in libnet_samsync.c
authorAndrew Bartlett <abartlet@samba.org>
Fri, 27 Mar 2009 01:16:17 +0000 (12:16 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 14 Apr 2009 06:23:43 +0000 (16:23 +1000)
Andrew Bartlett

libcli/samsync/decrypt.c [new file with mode: 0644]
libcli/samsync/samsync.h [new file with mode: 0644]
source3/libnet/libnet_samsync.c
source4/libnet/libnet_samsync.c

diff --git a/libcli/samsync/decrypt.c b/libcli/samsync/decrypt.c
new file mode 100644 (file)
index 0000000..2181c6f
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Extract the user/system database from a remote SamSync server
+
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+   Copyright (C) Guenther Deschner <gd@samba.org> 2008
+
+   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 "libnet/libnet.h"
+#include "../lib/crypto/crypto.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "../libcli/samsync/samsync.h"
+
+/**
+ * Decrypt and extract the user's passwords.
+ *
+ * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted)
+ * passwords back into the structure
+ */
+
+static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
+                        struct creds_CredentialState *creds,
+                        enum netr_SamDatabaseID database_id,
+                        struct netr_DELTA_ENUM *delta)
+{
+
+       uint32_t rid = delta->delta_id_union.rid;
+       struct netr_DELTA_USER *user = delta->delta_union.user;
+       struct samr_Password lm_hash;
+       struct samr_Password nt_hash;
+       unsigned char zero_buf[16];
+
+       memset(zero_buf, '\0', sizeof(zero_buf));
+
+       /* Note that win2000 may send us all zeros
+        * for the hashes if it doesn't
+        * think this channel is secure enough. */
+       if (user->lm_password_present) {
+               if (memcmp(user->lmpassword.hash, zero_buf, 16) != 0) {
+                       sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0);
+               } else {
+                       memset(lm_hash.hash, '\0', sizeof(lm_hash.hash));
+               }
+               user->lmpassword = lm_hash;
+       }
+
+       if (user->nt_password_present) {
+               if (memcmp(user->ntpassword.hash, zero_buf, 16) != 0) {
+                       sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0);
+               } else {
+                       memset(nt_hash.hash, '\0', sizeof(nt_hash.hash));
+               }
+               user->ntpassword = nt_hash;
+       }
+
+       if (user->user_private_info.SensitiveData) {
+               DATA_BLOB data;
+               struct netr_USER_KEYS keys;
+               enum ndr_err_code ndr_err;
+               data.data = user->user_private_info.SensitiveData;
+               data.length = user->user_private_info.DataLength;
+               creds_arcfour_crypt(creds, data.data, data.length);
+               user->user_private_info.SensitiveData = data.data;
+               user->user_private_info.DataLength = data.length;
+
+               ndr_err = ndr_pull_struct_blob(&data, mem_ctx, NULL, &keys,
+                       (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
+               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       dump_data(10, data.data, data.length);
+                       return ndr_map_error2ntstatus(ndr_err);
+               }
+
+               /* Note that win2000 may send us all zeros
+                * for the hashes if it doesn't
+                * think this channel is secure enough. */
+               if (keys.keys.keys2.lmpassword.length == 16) {
+                       if (memcmp(keys.keys.keys2.lmpassword.pwd.hash,
+                                       zero_buf, 16) != 0) {
+                               sam_rid_crypt(rid,
+                                             keys.keys.keys2.lmpassword.pwd.hash,
+                                             lm_hash.hash, 0);
+                       } else {
+                               memset(lm_hash.hash, '\0', sizeof(lm_hash.hash));
+                       }
+                       user->lmpassword = lm_hash;
+                       user->lm_password_present = true;
+               }
+               if (keys.keys.keys2.ntpassword.length == 16) {
+                       if (memcmp(keys.keys.keys2.ntpassword.pwd.hash,
+                                               zero_buf, 16) != 0) {
+                               sam_rid_crypt(rid,
+                                             keys.keys.keys2.ntpassword.pwd.hash,
+                                             nt_hash.hash, 0);
+                       } else {
+                               memset(nt_hash.hash, '\0', sizeof(nt_hash.hash));
+                       }
+                       user->ntpassword = nt_hash;
+                       user->nt_password_present = true;
+               }
+               /* TODO: rid decrypt history fields */
+       }
+       return NT_STATUS_OK;
+}
+
+/**
+ * Decrypt and extract the secrets
+ * 
+ * The writes decrypted secrets back into the structure
+ */
+static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx,
+                          struct creds_CredentialState *creds,
+                          enum netr_SamDatabaseID database,
+                          struct netr_DELTA_ENUM *delta) 
+{
+       struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
+       creds_arcfour_crypt(creds, secret->current_cipher.cipher_data, 
+                           secret->current_cipher.maxlen); 
+
+       creds_arcfour_crypt(creds, secret->old_cipher.cipher_data, 
+                           secret->old_cipher.maxlen); 
+
+       return NT_STATUS_OK;
+}
+
+/**
+ * Fix up the delta, dealing with encryption issues so that the final
+ * callback need only do the printing or application logic
+ */
+
+NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx,
+                          struct creds_CredentialState *creds,
+                          enum netr_SamDatabaseID database_id,
+                          struct netr_DELTA_ENUM *delta)
+{
+       NTSTATUS status = NT_STATUS_OK;
+
+       switch (delta->delta_type) {
+               case NETR_DELTA_USER:
+
+                       status = fix_user(mem_ctx,
+                                         creds,
+                                         database_id,
+                                         delta);
+                       break;
+               case NETR_DELTA_SECRET:
+
+                       status = fix_secret(mem_ctx,
+                                           creds,
+                                           database_id,
+                                           delta);
+                       break;
+               default:
+                       break;
+       }
+
+       return status;
+}
+
diff --git a/libcli/samsync/samsync.h b/libcli/samsync/samsync.h
new file mode 100644 (file)
index 0000000..19c7978
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Extract the user/system database from a remote SamSync server
+
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+   Copyright (C) Guenther Deschner <gd@samba.org> 2008
+
+   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/>.
+*/
+
+NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx,
+                          struct creds_CredentialState *creds,
+                          enum netr_SamDatabaseID database_id,
+                          struct netr_DELTA_ENUM *delta);
index b89f4efaf571f2e7c0fcee5c5c8d0a7f7e1a504b..8928f1c0529a7e9af29fb82f8b4b394a4e9716b7 100644 (file)
 #include "includes.h"
 #include "libnet/libnet.h"
 #include "../lib/crypto/crypto.h"
+#include "../libcli/samsync/samsync.h"
 #include "../libcli/auth/libcli_auth.h"
 
-/**
- * Decrypt and extract the user's passwords.
- *
- * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted)
- * passwords back into the structure
- */
-
-static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
-                        DATA_BLOB *session_key,
-                        enum netr_SamDatabaseID database_id,
-                        struct netr_DELTA_ENUM *delta)
-{
-
-       uint32_t rid = delta->delta_id_union.rid;
-       struct netr_DELTA_USER *user = delta->delta_union.user;
-       struct samr_Password lm_hash;
-       struct samr_Password nt_hash;
-       unsigned char zero_buf[16];
-
-       memset(zero_buf, '\0', sizeof(zero_buf));
-
-       /* Note that win2000 may send us all zeros
-        * for the hashes if it doesn't
-        * think this channel is secure enough. */
-       if (user->lm_password_present) {
-               if (memcmp(user->lmpassword.hash, zero_buf, 16) != 0) {
-                       sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0);
-               } else {
-                       memset(lm_hash.hash, '\0', sizeof(lm_hash.hash));
-               }
-               user->lmpassword = lm_hash;
-       }
-
-       if (user->nt_password_present) {
-               if (memcmp(user->ntpassword.hash, zero_buf, 16) != 0) {
-                       sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0);
-               } else {
-                       memset(nt_hash.hash, '\0', sizeof(nt_hash.hash));
-               }
-               user->ntpassword = nt_hash;
-       }
-
-       if (user->user_private_info.SensitiveData) {
-               DATA_BLOB data;
-               struct netr_USER_KEYS keys;
-               enum ndr_err_code ndr_err;
-               data.data = user->user_private_info.SensitiveData;
-               data.length = user->user_private_info.DataLength;
-               arcfour_crypt_blob(data.data, data.length, session_key);
-               user->user_private_info.SensitiveData = data.data;
-               user->user_private_info.DataLength = data.length;
-
-               ndr_err = ndr_pull_struct_blob(&data, mem_ctx, NULL, &keys,
-                       (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       dump_data(10, data.data, data.length);
-                       return ndr_map_error2ntstatus(ndr_err);
-               }
-
-               /* Note that win2000 may send us all zeros
-                * for the hashes if it doesn't
-                * think this channel is secure enough. */
-               if (keys.keys.keys2.lmpassword.length == 16) {
-                       if (memcmp(keys.keys.keys2.lmpassword.pwd.hash,
-                                       zero_buf, 16) != 0) {
-                               sam_rid_crypt(rid,
-                                             keys.keys.keys2.lmpassword.pwd.hash,
-                                             lm_hash.hash, 0);
-                       } else {
-                               memset(lm_hash.hash, '\0', sizeof(lm_hash.hash));
-                       }
-                       user->lmpassword = lm_hash;
-                       user->lm_password_present = true;
-               }
-               if (keys.keys.keys2.ntpassword.length == 16) {
-                       if (memcmp(keys.keys.keys2.ntpassword.pwd.hash,
-                                               zero_buf, 16) != 0) {
-                               sam_rid_crypt(rid,
-                                             keys.keys.keys2.ntpassword.pwd.hash,
-                                             nt_hash.hash, 0);
-                       } else {
-                               memset(nt_hash.hash, '\0', sizeof(nt_hash.hash));
-                       }
-                       user->ntpassword = nt_hash;
-                       user->nt_password_present = true;
-               }
-               /* TODO: rid decrypt history fields */
-       }
-       return NT_STATUS_OK;
-}
-
-/**
- * Decrypt and extract the secrets
- *
- * The writes decrypted secrets back into the structure
- */
-static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx,
-                          DATA_BLOB *session_key,
-                          enum netr_SamDatabaseID database_id,
-                          struct netr_DELTA_ENUM *delta)
-{
-       struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
-
-       arcfour_crypt_blob(secret->current_cipher.cipher_data,
-                          secret->current_cipher.maxlen,
-                          session_key);
-       
-       arcfour_crypt_blob(secret->old_cipher.cipher_data,
-                          secret->old_cipher.maxlen,
-                          session_key);
-
-       return NT_STATUS_OK;
-}
-
-/**
- * Fix up the delta, dealing with encryption issues so that the final
- * callback need only do the printing or application logic
- */
-
-static NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx,
-                                 DATA_BLOB *session_key,
-                                 enum netr_SamDatabaseID database_id,
-                                 struct netr_DELTA_ENUM *delta)
-{
-       NTSTATUS status = NT_STATUS_OK;
-
-       switch (delta->delta_type) {
-               case NETR_DELTA_USER:
-
-                       status = fix_user(mem_ctx,
-                                         session_key,
-                                         database_id,
-                                         delta);
-                       break;
-               case NETR_DELTA_SECRET:
-
-                       status = fix_secret(mem_ctx,
-                                           session_key,
-                                           database_id,
-                                           delta);
-                       break;
-               default:
-                       break;
-       }
-
-       return status;
-}
-
 /**
  * Fix up the delta, dealing with encryption issues so that the final
  * callback need only do the printing or application logic
  */
 
 static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx,
-                                       DATA_BLOB *session_key,
+                                       struct creds_CredentialState *creds,
                                        enum netr_SamDatabaseID database_id,
                                        struct netr_DELTA_ENUM_ARRAY *r)
 {
@@ -190,7 +43,7 @@ static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx,
        for (i = 0; i < r->num_deltas; i++) {
 
                status = samsync_fix_delta(mem_ctx,
-                                          session_key,
+                                          creds,
                                           database_id,
                                           &r->delta_enum[i]);
                if (!NT_STATUS_IS_OK(status)) {
@@ -347,14 +200,13 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
        struct netr_Authenticator return_authenticator;
        uint16_t restart_state = 0;
        uint32_t sync_context = 0;
-       DATA_BLOB session_key;
 
        ZERO_STRUCT(return_authenticator);
 
        do {
                struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
 
-               netlogon_creds_client_step(ctx->cli->dc, &credential);
+               creds_client_authenticator(ctx->cli->dc, &credential);
 
                if (ctx->single_object_replication &&
                    !ctx->force_full_replication) {
@@ -395,8 +247,8 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
                }
 
                /* Check returned credentials. */
-               if (!netlogon_creds_client_check(ctx->cli->dc,
-                                                &return_authenticator.cred)) {
+               if (!creds_client_check(ctx->cli->dc,
+                                       &return_authenticator.cred)) {
                        DEBUG(0,("credentials chain check failed\n"));
                        return NT_STATUS_ACCESS_DENIED;
                }
@@ -405,10 +257,8 @@ static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
                        break;
                }
 
-               session_key = data_blob_const(ctx->cli->dc->sess_key, 16);
-
                samsync_fix_delta_array(mem_ctx,
-                                       &session_key,
+                                       ctx->cli->dc,
                                        database_id,
                                        delta_enum_array);
 
index 51e49e94a0d3080504cbef793e759a801d169f4e..80111fe757dcc3bb0a37bd05e8400c43d37eaf5f 100644 (file)
@@ -23,6 +23,7 @@
 #include "includes.h"
 #include "libnet/libnet.h"
 #include "libcli/auth/libcli_auth.h"
+#include "../libcli/samsync/samsync.h"
 #include "auth/gensec/gensec.h"
 #include "auth/credentials/credentials.h"
 #include "auth/gensec/schannel_proto.h"
 #include "librpc/gen_ndr/ndr_netlogon_c.h"
 #include "param/param.h"
 
-
-/**
- * Decrypt and extract the user's passwords.  
- * 
- * The writes decrypted (no longer 'RID encrypted' or arcfour encrypted) passwords back into the structure
- */
-static NTSTATUS fix_user(TALLOC_CTX *mem_ctx,
-                        struct creds_CredentialState *creds,
-                        bool rid_crypt,
-                        enum netr_SamDatabaseID database,
-                        struct netr_DELTA_ENUM *delta,
-                        char **error_string) 
-{
-
-       uint32_t rid = delta->delta_id_union.rid;
-       struct netr_DELTA_USER *user = delta->delta_union.user;
-       struct samr_Password lm_hash;
-       struct samr_Password nt_hash;
-       const char *username = user->account_name.string;
-
-       if (rid_crypt) {
-               if (user->lm_password_present) {
-                       sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0);
-                       user->lmpassword = lm_hash;
-               }
-               
-               if (user->nt_password_present) {
-                       sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0);
-                       user->ntpassword = nt_hash;
-               }
-       }
-
-       if (user->user_private_info.SensitiveData) {
-               DATA_BLOB data;
-               struct netr_USER_KEYS keys;
-               enum ndr_err_code ndr_err;
-               data.data = user->user_private_info.SensitiveData;
-               data.length = user->user_private_info.DataLength;
-               creds_arcfour_crypt(creds, data.data, data.length);
-               user->user_private_info.SensitiveData = data.data;
-               user->user_private_info.DataLength = data.length;
-
-               ndr_err = ndr_pull_struct_blob(&data, mem_ctx, NULL, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       *error_string = talloc_asprintf(mem_ctx, "Failed to parse Sensitive Data for %s:", username);
-                       dump_data(10, data.data, data.length);
-                       return ndr_map_error2ntstatus(ndr_err);
-               }
-
-               if (keys.keys.keys2.lmpassword.length == 16) {
-                       if (rid_crypt) {
-                               sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0);
-                               user->lmpassword = lm_hash;
-                       } else {
-                               user->lmpassword = keys.keys.keys2.lmpassword.pwd;
-                       }
-                       user->lm_password_present = true;
-               }
-               if (keys.keys.keys2.ntpassword.length == 16) {
-                       if (rid_crypt) {
-                               sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0);
-                               user->ntpassword = nt_hash;
-                       } else {
-                               user->ntpassword = keys.keys.keys2.ntpassword.pwd;
-                       }
-                       user->nt_password_present = true;
-               }
-               /* TODO: rid decrypt history fields */
-       }
-       return NT_STATUS_OK;
-}
-
-/**
- * Decrypt and extract the secrets
- * 
- * The writes decrypted secrets back into the structure
- */
-static NTSTATUS fix_secret(TALLOC_CTX *mem_ctx,
-                          struct creds_CredentialState *creds,
-                          enum netr_SamDatabaseID database,
-                          struct netr_DELTA_ENUM *delta,
-                          char **error_string) 
-{
-       struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
-       creds_arcfour_crypt(creds, secret->current_cipher.cipher_data, 
-                           secret->current_cipher.maxlen); 
-
-       creds_arcfour_crypt(creds, secret->old_cipher.cipher_data, 
-                           secret->old_cipher.maxlen); 
-
-       return NT_STATUS_OK;
-}
-
-/**
- * Fix up the delta, dealing with encryption issues so that the final
- * callback need only do the printing or application logic
- */
-
-static NTSTATUS fix_delta(TALLOC_CTX *mem_ctx,                 
-                         struct creds_CredentialState *creds,
-                         bool rid_crypt,
-                         enum netr_SamDatabaseID database,
-                         struct netr_DELTA_ENUM *delta,
-                         char **error_string)
-{
-       NTSTATUS nt_status = NT_STATUS_OK;
-       *error_string = NULL;
-       switch (delta->delta_type) {
-       case NETR_DELTA_USER:
-       {
-               nt_status = fix_user(mem_ctx, 
-                                    creds,
-                                    rid_crypt,
-                                    database,
-                                    delta,
-                                    error_string);
-               break;
-       }
-       case NETR_DELTA_SECRET:
-       {
-               nt_status = fix_secret(mem_ctx, 
-                                      creds,
-                                      database,
-                                      delta,
-                                      error_string);
-               break;
-       }
-       default:
-               break;
-       }
-       return nt_status;
-}
-
 NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamSync *r)
 {
        NTSTATUS nt_status, dbsync_nt_status;
@@ -177,7 +45,7 @@ NTSTATUS libnet_SamSync_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx
        struct libnet_RpcConnect *c;
        struct libnet_SamSync_state *state;
        const enum netr_SamDatabaseID database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS}; 
-       int i;
+f      int i;
 
        samsync_ctx = talloc_named(mem_ctx, 0, "SamSync top context");