#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
*/
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)
{
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)) {
*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;
* 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);
* 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;
+ NTSTATUS result, status;
NTSTATUS callback_status;
- TALLOC_CTX *mem_ctx;
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;
- uint64_t sequence_num = 0;
+ struct dcerpc_binding_handle *b = ctx->cli->binding_handle;
ZERO_STRUCT(return_authenticator);
- if (!ctx->ops) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!(mem_ctx = talloc_init("libnet_samsync"))) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (ctx->ops->startup) {
- result = ctx->ops->startup(mem_ctx, ctx,
- database_id, &sequence_num);
- if (!NT_STATUS_IS_OK(result)) {
- goto out;
- }
- }
-
- 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;
- 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,
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. */
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->ops->process_objects(mem_ctx, database_id,
delta_enum_array,
- &sequence_num,
+ sequence_num,
ctx);
if (!NT_STATUS_IS_OK(callback_status)) {
result = callback_status;
TALLOC_FREE(delta_enum_array);
- /* Increment sync_context */
- sync_context += 1;
-
} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
out:
- if (NT_STATUS_IS_OK(result) && ctx->ops->finish) {
- callback_status = ctx->ops->finish(mem_ctx, ctx,
- database_id, sequence_num);
- if (!NT_STATUS_IS_OK(callback_status)) {
- result = callback_status;
- }
- }
-
- 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;
}
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++) {
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;
}
*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)) {