s3-param Remove special case for global_myname(), rename to lp_netbios_name()
[gd/samba-autobuild/.git] / source3 / libnet / libnet_samsync.c
index 2e7063e4eaaa3335460360c25193eb2079ddfa0b..75fc329e0af6b69617d6b5b516af340218a4b6a7 100644 (file)
 
 
 #include "includes.h"
-#include "libnet/libnet.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_pwd_hash(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_pwd_hash(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;
-               SamOEMhashBlob(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_pwd_hash(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_pwd_hash(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;
-
-       SamOEMhashBlob(secret->current_cipher.cipher_data,
-                      secret->current_cipher.maxlen,
-                      session_key);
-
-       SamOEMhashBlob(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;
-}
+#include "libnet/libnet_samsync.h"
+#include "../libcli/samsync/samsync.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "rpc_client/rpc_client.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
+#include "../librpc/gen_ndr/ndr_netlogon_c.h"
+#include "../libcli/security/security.h"
+#include "messages.h"
 
 /**
  * Fix up the delta, dealing with encryption issues so that the final
@@ -178,7 +37,7 @@ static NTSTATUS samsync_fix_delta(TALLOC_CTX *mem_ctx,
  */
 
 static NTSTATUS samsync_fix_delta_array(TALLOC_CTX *mem_ctx,
-                                       DATA_BLOB *session_key,
+                                       struct netlogon_creds_CredentialState *creds,
                                        enum netr_SamDatabaseID database_id,
                                        struct netr_DELTA_ENUM_ARRAY *r)
 {
@@ -188,7 +47,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)) {
@@ -211,17 +70,21 @@ NTSTATUS libnet_samsync_init_context(TALLOC_CTX *mem_ctx,
 
        *ctx_p = NULL;
 
-       ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context);
+       ctx = talloc_zero(mem_ctx, struct samsync_context);
        NT_STATUS_HAVE_NO_MEMORY(ctx);
 
        if (domain_sid) {
-               ctx->domain_sid = sid_dup_talloc(mem_ctx, domain_sid);
+               ctx->domain_sid = dom_sid_dup(mem_ctx, domain_sid);
                NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid);
 
                ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
                NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid_str);
        }
 
+       ctx->msg_ctx = messaging_init(ctx, procid_self(),
+                                     event_context_init(ctx));
+       NT_STATUS_HAVE_NO_MEMORY(ctx->msg_ctx);
+
        *ctx_p = ctx;
 
        return NT_STATUS_OK;
@@ -282,8 +145,8 @@ static const char *samsync_debug_str(TALLOC_CTX *mem_ctx,
  * libnet_samsync
  */
 
-void libnet_init_netr_ChangeLogEntry(struct samsync_object *o,
-                                    struct netr_ChangeLogEntry *e)
+static void libnet_init_netr_ChangeLogEntry(struct samsync_object *o,
+                                           struct netr_ChangeLogEntry *e)
 {
        ZERO_STRUCTP(e);
 
@@ -331,49 +194,54 @@ void libnet_init_netr_ChangeLogEntry(struct samsync_object *o,
  * libnet_samsync_delta
  */
 
-static NTSTATUS libnet_samsync_delta(enum netr_SamDatabaseID database_id,
+static NTSTATUS libnet_samsync_delta(TALLOC_CTX *mem_ctx,
+                                    enum netr_SamDatabaseID database_id,
+                                    uint64_t *sequence_num,
                                     struct samsync_context *ctx,
                                     struct netr_ChangeLogEntry *e)
 {
-       NTSTATUS result;
-       TALLOC_CTX *mem_ctx;
+       NTSTATUS result, status;
+       NTSTATUS callback_status;
        const char *logon_server = ctx->cli->desthost;
-       const char *computername = global_myname();
+       const char *computername = lp_netbios_name();
        struct netr_Authenticator credential;
        struct netr_Authenticator return_authenticator;
        uint16_t restart_state = 0;
        uint32_t sync_context = 0;
-       const char *debug_str;
-       DATA_BLOB session_key;
+       struct dcerpc_binding_handle *b = ctx->cli->binding_handle;
 
        ZERO_STRUCT(return_authenticator);
 
-       if (!(mem_ctx = talloc_init("libnet_samsync"))) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       debug_str = samsync_debug_str(mem_ctx, ctx->mode, database_id);
-       if (debug_str) {
-               d_fprintf(stderr, "%s\n", debug_str);
-       }
-
        do {
                struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
-               NTSTATUS callback_status;
 
-               netlogon_creds_client_step(ctx->cli->dc, &credential);
+               netlogon_creds_client_authenticator(ctx->cli->dc, &credential);
 
-               if (ctx->single_object_replication) {
-                       result = rpccli_netr_DatabaseRedo(ctx->cli, mem_ctx,
+               if (ctx->single_object_replication &&
+                   !ctx->force_full_replication) {
+                       status = dcerpc_netr_DatabaseRedo(b, mem_ctx,
                                                          logon_server,
                                                          computername,
                                                          &credential,
                                                          &return_authenticator,
                                                          *e,
                                                          0,
-                                                         &delta_enum_array);
+                                                         &delta_enum_array,
+                                                         &result);
+               } else if (!ctx->force_full_replication &&
+                          sequence_num && (*sequence_num > 0)) {
+                       status = dcerpc_netr_DatabaseDeltas(b, mem_ctx,
+                                                           logon_server,
+                                                           computername,
+                                                           &credential,
+                                                           &return_authenticator,
+                                                           database_id,
+                                                           sequence_num,
+                                                           &delta_enum_array,
+                                                           0xffff,
+                                                           &result);
                } else {
-                       result = rpccli_netr_DatabaseSync2(ctx->cli, mem_ctx,
+                       status = dcerpc_netr_DatabaseSync2(b, mem_ctx,
                                                           logon_server,
                                                           computername,
                                                           &credential,
@@ -382,11 +250,12 @@ static NTSTATUS libnet_samsync_delta(enum netr_SamDatabaseID database_id,
                                                           restart_state,
                                                           &sync_context,
                                                           &delta_enum_array,
-                                                          0xffff);
+                                                          0xffff,
+                                                          &result);
                }
 
-               if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
-                       return result;
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
                }
 
                /* Check returned credentials. */
@@ -396,21 +265,24 @@ static NTSTATUS libnet_samsync_delta(enum netr_SamDatabaseID database_id,
                        return NT_STATUS_ACCESS_DENIED;
                }
 
+               if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
+                       return result;
+               }
+
                if (NT_STATUS_IS_ERR(result)) {
                        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);
 
                /* Process results */
-               callback_status = ctx->delta_fn(mem_ctx, database_id,
-                                               delta_enum_array,
-                                               NT_STATUS_IS_OK(result), ctx);
+               callback_status = ctx->ops->process_objects(mem_ctx, database_id,
+                                                           delta_enum_array,
+                                                           sequence_num,
+                                                           ctx);
                if (!NT_STATUS_IS_OK(callback_status)) {
                        result = callback_status;
                        goto out;
@@ -418,29 +290,9 @@ static NTSTATUS libnet_samsync_delta(enum netr_SamDatabaseID database_id,
 
                TALLOC_FREE(delta_enum_array);
 
-               /* Increment sync_context */
-               sync_context += 1;
-
        } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
 
  out:
-       if (NT_STATUS_IS_ERR(result) && !ctx->error_message) {
-
-               ctx->error_message = talloc_asprintf(ctx,
-                       "Failed to fetch %s database: %s",
-                       samsync_database_str(database_id),
-                       nt_errstr(result));
-
-               if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
-
-                       ctx->error_message =
-                               talloc_asprintf_append(ctx->error_message,
-                                       "\nPerhaps %s is a Windows native mode domain?",
-                                       ctx->domain_name);
-               }
-       }
-
-       talloc_destroy(mem_ctx);
 
        return result;
 }
@@ -453,10 +305,37 @@ NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id,
                        struct samsync_context *ctx)
 {
        NTSTATUS status = NT_STATUS_OK;
+       NTSTATUS callback_status;
+       TALLOC_CTX *mem_ctx;
+       const char *debug_str;
+       uint64_t sequence_num = 0;
        int i = 0;
 
+       if (!(mem_ctx = talloc_new(ctx))) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!ctx->ops) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (ctx->ops->startup) {
+               status = ctx->ops->startup(mem_ctx, ctx,
+                                          database_id, &sequence_num);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto done;
+               }
+       }
+
+       debug_str = samsync_debug_str(mem_ctx, ctx->mode, database_id);
+       if (debug_str) {
+               d_fprintf(stderr, "%s\n", debug_str);
+       }
+
        if (!ctx->single_object_replication) {
-               return libnet_samsync_delta(database_id, ctx, NULL);
+               status = libnet_samsync_delta(mem_ctx, database_id,
+                                             &sequence_num, ctx, NULL);
+               goto done;
        }
 
        for (i=0; i<ctx->num_objects; i++) {
@@ -469,12 +348,41 @@ NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id,
 
                libnet_init_netr_ChangeLogEntry(&ctx->objects[i], &e);
 
-               status = libnet_samsync_delta(database_id, ctx, &e);
+               status = libnet_samsync_delta(mem_ctx, database_id,
+                                             &sequence_num, ctx, &e);
                if (!NT_STATUS_IS_OK(status)) {
-                       return status;
+                       goto done;
+               }
+       }
+
+ done:
+
+       if (NT_STATUS_IS_OK(status) && ctx->ops->finish) {
+               callback_status = ctx->ops->finish(mem_ctx, ctx,
+                                                  database_id, sequence_num);
+               if (!NT_STATUS_IS_OK(callback_status)) {
+                       status = callback_status;
+               }
+       }
+
+       if (NT_STATUS_IS_ERR(status) && !ctx->error_message) {
+
+               ctx->error_message = talloc_asprintf(ctx,
+                       "Failed to fetch %s database: %s",
+                       samsync_database_str(database_id),
+                       nt_errstr(status));
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
+
+                       ctx->error_message =
+                               talloc_asprintf_append(ctx->error_message,
+                                       "\nPerhaps %s is a Windows native mode domain?",
+                                       ctx->domain_name);
                }
        }
 
+       talloc_destroy(mem_ctx);
+
        return status;
 }
 
@@ -496,14 +404,14 @@ NTSTATUS pull_netr_AcctLockStr(TALLOC_CTX *mem_ctx,
 
        *str_p = NULL;
 
-       str = TALLOC_ZERO_P(mem_ctx, struct netr_AcctLockStr);
+       str = talloc_zero(mem_ctx, struct netr_AcctLockStr);
        if (!str) {
                return NT_STATUS_NO_MEMORY;
        }
 
        blob = data_blob_const(r->array, r->length);
 
-       ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, str,
+       ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, str,
                       (ndr_pull_flags_fn_t)ndr_pull_netr_AcctLockStr);
 
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {