diff options
author | Andrew Tridgell <tridge@samba.org> | 2008-12-03 17:47:39 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2008-12-03 17:47:39 +1100 |
commit | a226d86dcec393b2cd657d5441c3041dfdf5cd8f (patch) | |
tree | 03ef7f3207607a4e5351bf50892b0a39dcf6f219 /source3/libnet | |
parent | 30eff4f31b497ac94d8ee02ee2ec24bc8865ce0d (diff) | |
parent | 85b8cccab072bab263061654b677bc84826646c9 (diff) | |
download | samba-a226d86dcec393b2cd657d5441c3041dfdf5cd8f.tar.gz samba-a226d86dcec393b2cd657d5441c3041dfdf5cd8f.tar.bz2 samba-a226d86dcec393b2cd657d5441c3041dfdf5cd8f.zip |
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3/libnet')
-rw-r--r-- | source3/libnet/libnet_dssync_keytab.c | 111 | ||||
-rw-r--r-- | source3/libnet/libnet_join.c | 114 | ||||
-rw-r--r-- | source3/libnet/libnet_keytab.c | 33 | ||||
-rw-r--r-- | source3/libnet/libnet_proto.h | 7 | ||||
-rw-r--r-- | source3/libnet/libnet_samsync.c | 200 | ||||
-rw-r--r-- | source3/libnet/libnet_samsync.h | 65 | ||||
-rw-r--r-- | source3/libnet/libnet_samsync_display.c | 17 | ||||
-rw-r--r-- | source3/libnet/libnet_samsync_keytab.c | 221 | ||||
-rw-r--r-- | source3/libnet/libnet_samsync_ldif.c | 119 | ||||
-rw-r--r-- | source3/libnet/libnet_samsync_passdb.c | 20 |
10 files changed, 642 insertions, 265 deletions
diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 6a3139d6ad..a05bfdcbe2 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -24,39 +24,6 @@ #if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) -/** - * Internal helper function to add data to the list - * of keytab entries. It builds the prefix from the input. - */ -static NTSTATUS add_to_keytab_entries(TALLOC_CTX *mem_ctx, - struct libnet_keytab_context *ctx, - uint32_t kvno, - const char *name, - const char *prefix, - const krb5_enctype enctype, - DATA_BLOB blob) -{ - struct libnet_keytab_entry entry; - - entry.kvno = kvno; - entry.name = talloc_strdup(mem_ctx, name); - entry.principal = talloc_asprintf(mem_ctx, "%s%s%s@%s", - prefix ? prefix : "", - prefix ? "/" : "", - name, ctx->dns_domain_name); - entry.enctype = enctype; - entry.password = blob; - NT_STATUS_HAVE_NO_MEMORY(entry.name); - NT_STATUS_HAVE_NO_MEMORY(entry.principal); - NT_STATUS_HAVE_NO_MEMORY(entry.password.data); - - ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, - &ctx->entries, &ctx->count); - NT_STATUS_HAVE_NO_MEMORY(ctx->entries); - - return NT_STATUS_OK; -} - static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, struct replUpToDateVectorBlob **pold_utdv) { @@ -134,10 +101,10 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, goto done; } - status = add_to_keytab_entries(mem_ctx, keytab_ctx, 0, - ctx->nc_dn, "UTDV", - ENCTYPE_NULL, - blob); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, keytab_ctx, 0, + ctx->nc_dn, "UTDV", + ENCTYPE_NULL, + blob); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -391,11 +358,11 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } if (name) { - status = add_to_keytab_entries(mem_ctx, ctx, 0, object_dn, - "SAMACCOUNTNAME", - ENCTYPE_NULL, - data_blob_talloc(mem_ctx, name, - strlen(name) + 1)); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, 0, object_dn, + "SAMACCOUNTNAME", + ENCTYPE_NULL, + data_blob_talloc(mem_ctx, name, + strlen(name) + 1)); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -454,9 +421,9 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } DEBUGADD(1,("\n")); - status = add_to_keytab_entries(mem_ctx, ctx, kvno, name, NULL, - ENCTYPE_ARCFOUR_HMAC, - data_blob_talloc(mem_ctx, nt_passwd, 16)); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno, name, NULL, + ENCTYPE_ARCFOUR_HMAC, + data_blob_talloc(mem_ctx, nt_passwd, 16)); if (!NT_STATUS_IS_OK(status)) { return status; @@ -469,11 +436,11 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, if (!pkb4->keys[i].value) { continue; } - status = add_to_keytab_entries(mem_ctx, ctx, kvno, - name, - NULL, - pkb4->keys[i].keytype, - *pkb4->keys[i].value); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno, + name, + NULL, + pkb4->keys[i].keytype, + *pkb4->keys[i].value); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -482,11 +449,11 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, if (!pkb4->old_keys[i].value) { continue; } - status = add_to_keytab_entries(mem_ctx, ctx, kvno - 1, - name, - NULL, - pkb4->old_keys[i].keytype, - *pkb4->old_keys[i].value); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno - 1, + name, + NULL, + pkb4->old_keys[i].keytype, + *pkb4->old_keys[i].value); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -495,11 +462,11 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, if (!pkb4->older_keys[i].value) { continue; } - status = add_to_keytab_entries(mem_ctx, ctx, kvno - 2, - name, - NULL, - pkb4->older_keys[i].keytype, - *pkb4->older_keys[i].value); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno - 2, + name, + NULL, + pkb4->older_keys[i].keytype, + *pkb4->older_keys[i].value); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -511,10 +478,10 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, if (!pkb3->keys[i].value) { continue; } - status = add_to_keytab_entries(mem_ctx, ctx, kvno, name, - NULL, - pkb3->keys[i].keytype, - *pkb3->keys[i].value); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno, name, + NULL, + pkb3->keys[i].keytype, + *pkb3->keys[i].value); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -523,11 +490,11 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, if (!pkb3->old_keys[i].value) { continue; } - status = add_to_keytab_entries(mem_ctx, ctx, kvno - 1, - name, - NULL, - pkb3->old_keys[i].keytype, - *pkb3->old_keys[i].value); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno - 1, + name, + NULL, + pkb3->old_keys[i].keytype, + *pkb3->old_keys[i].value); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -549,9 +516,9 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } for (; i<pwd_history_len; i++) { - status = add_to_keytab_entries(mem_ctx, ctx, kvno--, name, NULL, - ENCTYPE_ARCFOUR_HMAC, - data_blob_talloc(mem_ctx, &pwd_history[i*16], 16)); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno--, name, NULL, + ENCTYPE_ARCFOUR_HMAC, + data_blob_talloc(mem_ctx, &pwd_history[i*16], 16)); if (!NT_STATUS_IS_OK(status)) { break; } diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 6935e000dc..908fb78ab4 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -762,7 +762,6 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, struct lsa_String lsa_acct_name; uint32_t user_rid; uint32_t acct_flags = ACB_WSTRUST; - uchar md4_trust_password[16]; struct samr_Ids user_rids; struct samr_Ids name_types; union samr_UserInfo user_info; @@ -898,14 +897,6 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, goto done; } - /* Create a random machine account password and generate the hash */ - - E_md4hash(r->in.machine_password, md4_trust_password); - - init_samr_CryptPasswordEx(r->in.machine_password, - &cli->user_session_key, - &crypt_pwd_ex); - /* Fill in the additional account flags now */ acct_flags |= ACB_PWNOEXP; @@ -916,23 +907,40 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, ;; } - /* Set password and account flags on machine account */ - - ZERO_STRUCT(user_info.info25); - - user_info.info25.info.fields_present = ACCT_NT_PWD_SET | - ACCT_LM_PWD_SET | - SAMR_FIELD_ACCT_FLAGS; - - user_info.info25.info.acct_flags = acct_flags; - memcpy(&user_info.info25.password.data, crypt_pwd_ex.data, - sizeof(crypt_pwd_ex.data)); + /* Set account flags on machine account */ + ZERO_STRUCT(user_info.info16); + user_info.info16.acct_flags = acct_flags; status = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx, &user_pol, - 25, + 16, &user_info); + if (!NT_STATUS_IS_OK(status)) { + + rpccli_samr_DeleteUser(pipe_hnd, mem_ctx, + &user_pol); + + libnet_join_set_error_string(mem_ctx, r, + "Failed to set account flags for machine account (%s)\n", + nt_errstr(status)); + goto done; + } + + /* Set password on machine account - first try level 26 */ + + init_samr_CryptPasswordEx(r->in.machine_password, + &cli->user_session_key, + &crypt_pwd_ex); + + init_samr_user_info26(&user_info.info26, &crypt_pwd_ex, + PASS_DONT_CHANGE_AT_NEXT_LOGON); + + status = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx, + &user_pol, + 26, + &user_info); + if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) { /* retry with level 24 */ @@ -941,7 +949,8 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx, &cli->user_session_key, &crypt_pwd); - init_samr_user_info24(&user_info.info24, crypt_pwd.data, 24); + init_samr_user_info24(&user_info.info24, &crypt_pwd, + PASS_DONT_CHANGE_AT_NEXT_LOGON); status = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx, &user_pol, @@ -1638,24 +1647,31 @@ WERROR libnet_init_UnjoinCtx(TALLOC_CTX *mem_ctx, static WERROR libnet_join_check_config(TALLOC_CTX *mem_ctx, struct libnet_JoinCtx *r) { + bool valid_security = false; + bool valid_workgroup = false; + bool valid_realm = false; + /* check if configuration is already set correctly */ + valid_workgroup = strequal(lp_workgroup(), r->out.netbios_domain_name); + switch (r->out.domain_is_ad) { case false: - if ((strequal(lp_workgroup(), - r->out.netbios_domain_name)) && - (lp_security() == SEC_DOMAIN)) { + valid_security = (lp_security() == SEC_DOMAIN); + if (valid_workgroup && valid_security) { /* nothing to be done */ return WERR_OK; } break; case true: - if ((strequal(lp_workgroup(), - r->out.netbios_domain_name)) && - (strequal(lp_realm(), - r->out.dns_domain_name)) && - ((lp_security() == SEC_ADS) || - (lp_security() == SEC_DOMAIN))) { + valid_realm = strequal(lp_realm(), r->out.dns_domain_name); + switch (lp_security()) { + case SEC_DOMAIN: + case SEC_ADS: + valid_security = true; + } + + if (valid_workgroup && valid_realm && valid_security) { /* nothing to be done */ return WERR_OK; } @@ -1665,9 +1681,41 @@ static WERROR libnet_join_check_config(TALLOC_CTX *mem_ctx, /* check if we are supposed to manipulate configuration */ if (!r->in.modify_config) { + + char *wrong_conf = talloc_strdup(mem_ctx, ""); + + if (!valid_workgroup) { + wrong_conf = talloc_asprintf_append(wrong_conf, + "\"workgroup\" set to '%s', should be '%s'", + lp_workgroup(), r->out.netbios_domain_name); + W_ERROR_HAVE_NO_MEMORY(wrong_conf); + } + + if (!valid_realm) { + wrong_conf = talloc_asprintf_append(wrong_conf, + "\"realm\" set to '%s', should be '%s'", + lp_realm(), r->out.dns_domain_name); + W_ERROR_HAVE_NO_MEMORY(wrong_conf); + } + + if (!valid_security) { + const char *sec = NULL; + switch (lp_security()) { + case SEC_SHARE: sec = "share"; break; + case SEC_USER: sec = "user"; break; + case SEC_DOMAIN: sec = "domain"; break; + case SEC_ADS: sec = "ads"; break; + } + wrong_conf = talloc_asprintf_append(wrong_conf, + "\"security\" set to '%s', should be %s", + sec, r->out.domain_is_ad ? + "either 'domain' or 'ads'" : "'domain'"); + W_ERROR_HAVE_NO_MEMORY(wrong_conf); + } + libnet_join_set_error_string(mem_ctx, r, - "Invalid configuration and configuration modification " - "was not requested"); + "Invalid configuration (%s) and configuration modification " + "was not requested", wrong_conf); return WERR_CAN_NOT_COMPLETE; } diff --git a/source3/libnet/libnet_keytab.c b/source3/libnet/libnet_keytab.c index 46c17b219c..990f6f6a63 100644 --- a/source3/libnet/libnet_keytab.c +++ b/source3/libnet/libnet_keytab.c @@ -401,4 +401,37 @@ cont: return entry; } +/** + * Helper function to add data to the list + * of keytab entries. It builds the prefix from the input. + */ +NTSTATUS libnet_keytab_add_to_keytab_entries(TALLOC_CTX *mem_ctx, + struct libnet_keytab_context *ctx, + uint32_t kvno, + const char *name, + const char *prefix, + const krb5_enctype enctype, + DATA_BLOB blob) +{ + struct libnet_keytab_entry entry; + + entry.kvno = kvno; + entry.name = talloc_strdup(mem_ctx, name); + entry.principal = talloc_asprintf(mem_ctx, "%s%s%s@%s", + prefix ? prefix : "", + prefix ? "/" : "", + name, ctx->dns_domain_name); + entry.enctype = enctype; + entry.password = blob; + NT_STATUS_HAVE_NO_MEMORY(entry.name); + NT_STATUS_HAVE_NO_MEMORY(entry.principal); + NT_STATUS_HAVE_NO_MEMORY(entry.password.data); + + ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, + &ctx->entries, &ctx->count); + NT_STATUS_HAVE_NO_MEMORY(ctx->entries); + + return NT_STATUS_OK; +} + #endif /* HAVE_KRB5 */ diff --git a/source3/libnet/libnet_proto.h b/source3/libnet/libnet_proto.h index 69a16c1c7d..9a193b724d 100644 --- a/source3/libnet/libnet_proto.h +++ b/source3/libnet/libnet_proto.h @@ -55,6 +55,13 @@ struct libnet_keytab_entry *libnet_keytab_search(struct libnet_keytab_context *c const char *principal, int kvno, const krb5_enctype enctype, TALLOC_CTX *mem_ctx); +NTSTATUS libnet_keytab_add_to_keytab_entries(TALLOC_CTX *mem_ctx, + struct libnet_keytab_context *ctx, + uint32_t kvno, + const char *name, + const char *prefix, + const krb5_enctype enctype, + DATA_BLOB blob); #endif /* The following definitions come from libnet/libnet_samsync.c */ diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c index 00caf2b8c1..4351810169 100644 --- a/source3/libnet/libnet_samsync.c +++ b/source3/libnet/libnet_samsync.c @@ -282,47 +282,112 @@ static const char *samsync_debug_str(TALLOC_CTX *mem_ctx, * libnet_samsync */ -NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id, - struct samsync_context *ctx) +void libnet_init_netr_ChangeLogEntry(struct samsync_object *o, + struct netr_ChangeLogEntry *e) +{ + ZERO_STRUCTP(e); + + e->db_index = o->database_id; + e->delta_type = o->object_type; + + switch (e->delta_type) { + case NETR_DELTA_DOMAIN: + case NETR_DELTA_DELETE_GROUP: + case NETR_DELTA_RENAME_GROUP: + case NETR_DELTA_DELETE_USER: + case NETR_DELTA_RENAME_USER: + case NETR_DELTA_DELETE_ALIAS: + case NETR_DELTA_RENAME_ALIAS: + case NETR_DELTA_DELETE_TRUST: + case NETR_DELTA_DELETE_ACCOUNT: + case NETR_DELTA_DELETE_SECRET: + case NETR_DELTA_DELETE_GROUP2: + case NETR_DELTA_DELETE_USER2: + case NETR_DELTA_MODIFY_COUNT: + break; + case NETR_DELTA_USER: + case NETR_DELTA_GROUP: + case NETR_DELTA_GROUP_MEMBER: + case NETR_DELTA_ALIAS: + case NETR_DELTA_ALIAS_MEMBER: + e->object_rid = o->object_identifier.rid; + break; + case NETR_DELTA_SECRET: + e->object.object_name = o->object_identifier.name; + e->flags = NETR_CHANGELOG_NAME_INCLUDED; + break; + case NETR_DELTA_TRUSTED_DOMAIN: + case NETR_DELTA_ACCOUNT: + case NETR_DELTA_POLICY: + e->object.object_sid = o->object_identifier.sid; + e->flags = NETR_CHANGELOG_SID_INCLUDED; + break; + default: + break; + } +} + +/** + * libnet_samsync_delta + */ + +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 callback_status; const char *logon_server = ctx->cli->desthost; const char *computername = global_myname(); 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; 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); - result = rpccli_netr_DatabaseSync2(ctx->cli, mem_ctx, - logon_server, - computername, - &credential, - &return_authenticator, - database_id, - restart_state, - &sync_context, - &delta_enum_array, - 0xffff); + if (ctx->single_object_replication && + !ctx->force_full_replication) { + result = rpccli_netr_DatabaseRedo(ctx->cli, mem_ctx, + logon_server, + computername, + &credential, + &return_authenticator, + *e, + 0, + &delta_enum_array); + } else if (!ctx->force_full_replication && + sequence_num && (*sequence_num > 0)) { + result = rpccli_netr_DatabaseDeltas(ctx->cli, mem_ctx, + logon_server, + computername, + &credential, + &return_authenticator, + database_id, + sequence_num, + &delta_enum_array, + 0xffff); + } else { + result = rpccli_netr_DatabaseSync2(ctx->cli, mem_ctx, + logon_server, + computername, + &credential, + &return_authenticator, + database_id, + restart_state, + &sync_context, + &delta_enum_array, + 0xffff); + } + if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) { return result; } @@ -346,9 +411,10 @@ NTSTATUS libnet_samsync(enum netr_SamDatabaseID 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; @@ -362,14 +428,86 @@ NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id, } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); out: - if (NT_STATUS_IS_ERR(result) && !ctx->error_message) { + + return result; +} + +/** + * libnet_samsync + */ + +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) { + status = libnet_samsync_delta(mem_ctx, database_id, + &sequence_num, ctx, NULL); + goto done; + } + + for (i=0; i<ctx->num_objects; i++) { + + struct netr_ChangeLogEntry e; + + if (ctx->objects[i].database_id != database_id) { + continue; + } + + libnet_init_netr_ChangeLogEntry(&ctx->objects[i], &e); + + status = libnet_samsync_delta(mem_ctx, database_id, + &sequence_num, ctx, &e); + if (!NT_STATUS_IS_OK(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(result)); + nt_errstr(status)); - if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { ctx->error_message = talloc_asprintf_append(ctx->error_message, @@ -380,7 +518,7 @@ NTSTATUS libnet_samsync(enum netr_SamDatabaseID database_id, talloc_destroy(mem_ctx); - return result; + return status; } /** diff --git a/source3/libnet/libnet_samsync.h b/source3/libnet/libnet_samsync.h index 1f10d2c1c0..3a686a7f45 100644 --- a/source3/libnet/libnet_samsync.h +++ b/source3/libnet/libnet_samsync.h @@ -27,11 +27,31 @@ enum net_samsync_mode { struct samsync_context; -typedef NTSTATUS (*samsync_delta_fn_t)(TALLOC_CTX *, - enum netr_SamDatabaseID, - struct netr_DELTA_ENUM_ARRAY *, - bool, - struct samsync_context *); +struct samsync_ops { + NTSTATUS (*startup)(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID id, + uint64_t *sequence_num); + NTSTATUS (*process_objects)(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID id, + struct netr_DELTA_ENUM_ARRAY *array, + uint64_t *sequence_num, + struct samsync_context *ctx); + NTSTATUS (*finish)(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID id, + uint64_t sequence_num); +}; + +struct samsync_object { + uint16_t database_id; + uint16_t object_type; + union { + uint32_t rid; + const char *name; + struct dom_sid sid; + } object_identifier; +}; struct samsync_context { enum net_samsync_mode mode; @@ -46,28 +66,21 @@ struct samsync_context { char *result_message; char *error_message; + bool single_object_replication; + bool force_full_replication; + bool clean_old_entries; + + uint32_t num_objects; + struct samsync_object *objects; + struct rpc_pipe_client *cli; - samsync_delta_fn_t delta_fn; + + const struct samsync_ops *ops; + void *private_data; }; -NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx); -NTSTATUS fetch_sam_entries(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx); -NTSTATUS display_sam_entries(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx); -NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx); +extern const struct samsync_ops libnet_samsync_ldif_ops; +extern const struct samsync_ops libnet_samsync_keytab_ops; +extern const struct samsync_ops libnet_samsync_display_ops; +extern const struct samsync_ops libnet_samsync_passdb_ops; diff --git a/source3/libnet/libnet_samsync_display.c b/source3/libnet/libnet_samsync_display.c index 1dd9a1add5..c8d9ec6f09 100644 --- a/source3/libnet/libnet_samsync_display.c +++ b/source3/libnet/libnet_samsync_display.c @@ -163,7 +163,6 @@ static void display_rename_alias(uint32_t rid, struct netr_DELTA_RENAME *r) static NTSTATUS display_sam_entry(TALLOC_CTX *mem_ctx, enum netr_SamDatabaseID database_id, struct netr_DELTA_ENUM *r, - bool last_query, struct samsync_context *ctx) { union netr_DELTA_UNION u = r->delta_union; @@ -285,18 +284,22 @@ static NTSTATUS display_sam_entry(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -NTSTATUS display_sam_entries(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx) +static NTSTATUS display_sam_entries(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + uint64_t *sequence_num, + struct samsync_context *ctx) { int i; for (i = 0; i < r->num_deltas; i++) { display_sam_entry(mem_ctx, database_id, &r->delta_enum[i], - last_query, ctx); + ctx); } return NT_STATUS_OK; } + +const struct samsync_ops libnet_samsync_display_ops = { + .process_objects = display_sam_entries, +}; diff --git a/source3/libnet/libnet_samsync_keytab.c b/source3/libnet/libnet_samsync_keytab.c index 4b0cc06d94..cdb344604d 100644 --- a/source3/libnet/libnet_samsync_keytab.c +++ b/source3/libnet/libnet_samsync_keytab.c @@ -75,30 +75,28 @@ static NTSTATUS fetch_sam_entry_keytab(TALLOC_CTX *mem_ctx, enum netr_SamDatabaseID database_id, uint32_t rid, struct netr_DELTA_USER *r, - bool last_query, struct libnet_keytab_context *ctx) { - struct libnet_keytab_entry entry; + NTSTATUS status; + uint32_t kvno = 0; + DATA_BLOB blob; if (memcmp(r->ntpassword.hash, ctx->zero_buf, 16) == 0) { return NT_STATUS_OK; } - entry.name = talloc_strdup(mem_ctx, r->account_name.string); - entry.principal = talloc_asprintf(mem_ctx, "%s@%s", - r->account_name.string, - ctx->dns_domain_name); - entry.password = data_blob_talloc(mem_ctx, r->ntpassword.hash, 16); - entry.kvno = ads_get_kvno(ctx->ads, entry.name); - entry.enctype = ENCTYPE_NULL; - - NT_STATUS_HAVE_NO_MEMORY(entry.name); - NT_STATUS_HAVE_NO_MEMORY(entry.principal); - NT_STATUS_HAVE_NO_MEMORY(entry.password.data); - + kvno = ads_get_kvno(ctx->ads, r->account_name.string); + blob = data_blob_const(r->ntpassword.hash, 16); - ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, - &ctx->entries, &ctx->count); + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, + kvno, + r->account_name.string, + NULL, + ENCTYPE_ARCFOUR_HMAC, + blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } return NT_STATUS_OK; } @@ -106,72 +104,163 @@ static NTSTATUS fetch_sam_entry_keytab(TALLOC_CTX *mem_ctx, /**************************************************************** ****************************************************************/ -NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx) +static NTSTATUS init_keytab(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t *sequence_num) { - NTSTATUS status = NT_STATUS_OK; krb5_error_code ret = 0; - static struct libnet_keytab_context *keytab_ctx = NULL; - int i; - - if (!keytab_ctx) { - ret = libnet_keytab_init(mem_ctx, ctx->output_filename, - &keytab_ctx); - if (ret) { - status = krb5_to_nt_status(ret); - goto out; - } + NTSTATUS status; + struct libnet_keytab_context *keytab_ctx; + struct libnet_keytab_entry *entry; + uint64_t old_sequence_num = 0; + const char *principal = NULL; + + ret = libnet_keytab_init(mem_ctx, ctx->output_filename, &keytab_ctx); + if (ret) { + return krb5_to_nt_status(ret); } + keytab_ctx->clean_old_entries = ctx->clean_old_entries; + ctx->private_data = keytab_ctx; + status = keytab_ad_connect(mem_ctx, ctx->domain_name, ctx->username, ctx->password, keytab_ctx); if (!NT_STATUS_IS_OK(status)) { - goto out; + TALLOC_FREE(keytab_ctx); + return status; } + principal = talloc_asprintf(mem_ctx, "SEQUENCE_NUM@%s", + keytab_ctx->dns_domain_name); + NT_STATUS_HAVE_NO_MEMORY(principal); + + entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL, + mem_ctx); + if (entry && (entry->password.length == 8)) { + old_sequence_num = BVAL(entry->password.data, 0); + } + + if (sequence_num) { + *sequence_num = old_sequence_num; + } + + return status; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + uint64_t *sequence_num, + struct samsync_context *ctx) +{ + struct libnet_keytab_context *keytab_ctx = + (struct libnet_keytab_context *)ctx->private_data; + + NTSTATUS status = NT_STATUS_OK; + int i; + for (i = 0; i < r->num_deltas; i++) { - if (r->delta_enum[i].delta_type != NETR_DELTA_USER) { + switch (r->delta_enum[i].delta_type) { + case NETR_DELTA_USER: + break; + case NETR_DELTA_DOMAIN: + if (sequence_num) { + *sequence_num = + r->delta_enum[i].delta_union.domain->sequence_num; + } + continue; + case NETR_DELTA_MODIFY_COUNT: + if (sequence_num) { + *sequence_num = + *r->delta_enum[i].delta_union.modified_count; + } + continue; + default: continue; } status = fetch_sam_entry_keytab(mem_ctx, database_id, r->delta_enum[i].delta_id_union.rid, r->delta_enum[i].delta_union.user, - last_query, keytab_ctx); if (!NT_STATUS_IS_OK(status)) { goto out; } } + out: + return status; +} - if (last_query) { +/**************************************************************** +****************************************************************/ + +static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t sequence_num) +{ + struct libnet_keytab_context *keytab_ctx = + (struct libnet_keytab_context *)ctx->private_data; + krb5_error_code ret; + NTSTATUS status; + struct libnet_keytab_entry *entry; + uint64_t old_sequence_num = 0; + const char *principal = NULL; + + principal = talloc_asprintf(mem_ctx, "SEQUENCE_NUM@%s", + keytab_ctx->dns_domain_name); + NT_STATUS_HAVE_NO_MEMORY(principal); + + + entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL, + mem_ctx); + if (entry && (entry->password.length == 8)) { + old_sequence_num = BVAL(entry->password.data, 0); + } - ret = libnet_keytab_add(keytab_ctx); - if (ret) { - status = krb5_to_nt_status(ret); - ctx->error_message = talloc_asprintf(mem_ctx, - "Failed to add entries to keytab %s: %s", - keytab_ctx->keytab_name, error_message(ret)); - goto out; - } - ctx->result_message = talloc_asprintf(mem_ctx, - "Vampired %d accounts to keytab %s", - keytab_ctx->count, - keytab_ctx->keytab_name); + if (sequence_num > old_sequence_num) { + DATA_BLOB blob; + blob = data_blob_talloc_zero(mem_ctx, 8); + SBVAL(blob.data, 0, sequence_num); + + status = libnet_keytab_add_to_keytab_entries(mem_ctx, keytab_ctx, + 0, + "SEQUENCE_NUM", + NULL, + ENCTYPE_NULL, + blob); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } + ret = libnet_keytab_add(keytab_ctx); + if (ret) { + status = krb5_to_nt_status(ret); + ctx->error_message = talloc_asprintf(ctx, + "Failed to add entries to keytab %s: %s", + keytab_ctx->keytab_name, error_message(ret)); TALLOC_FREE(keytab_ctx); + return status; } - return NT_STATUS_OK; - out: + ctx->result_message = talloc_asprintf(ctx, + "Vampired %d accounts to keytab %s", + keytab_ctx->count, + keytab_ctx->keytab_name); + + status = NT_STATUS_OK; + + done: TALLOC_FREE(keytab_ctx); return status; @@ -179,13 +268,35 @@ NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx, #else -NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx) +static NTSTATUS init_keytab(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t *sequence_num) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + uint64_t *sequence_num, + struct samsync_context *ctx) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t sequence_num) { return NT_STATUS_NOT_SUPPORTED; } #endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */ + +const struct samsync_ops libnet_samsync_keytab_ops = { + .startup = init_keytab, + .process_objects = fetch_sam_entries_keytab, + .finish = close_keytab +}; diff --git a/source3/libnet/libnet_samsync_ldif.c b/source3/libnet/libnet_samsync_ldif.c index dd5380b6b8..c72eadf03f 100644 --- a/source3/libnet/libnet_samsync_ldif.c +++ b/source3/libnet/libnet_samsync_ldif.c @@ -32,6 +32,10 @@ static uint32 ldif_gid = 999; static uint32 ldif_uid = 999; +/* global counters */ +static uint32_t g_index = 0; +static uint32_t a_index = 0; + /* Structure for mapping accounts to groups */ /* Array element is the group rid */ typedef struct _groupmap { @@ -1046,8 +1050,8 @@ static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx, enum netr_SamDatabaseID database_id, struct netr_DELTA_ENUM *r, struct samsync_context *ctx, - uint32_t *a_index, - uint32_t *g_index) + uint32_t *a_index_p, + uint32_t *g_index_p) { union netr_DELTA_UNION u = r->delta_union; union netr_DELTA_ID_UNION id = r->delta_id_union; @@ -1061,34 +1065,34 @@ static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx, case NETR_DELTA_GROUP: fetch_group_info_to_ldif(mem_ctx, u.group, - &l->groupmap[*g_index], + &l->groupmap[*g_index_p], l->add_file, ctx->domain_sid_str, l->suffix); - (*g_index)++; + (*g_index_p)++; break; case NETR_DELTA_USER: fetch_account_info_to_ldif(mem_ctx, u.user, l->groupmap, - &l->accountmap[*a_index], + &l->accountmap[*a_index_p], l->add_file, ctx->domain_sid_str, l->suffix, l->num_alloced); - (*a_index)++; + (*a_index_p)++; break; case NETR_DELTA_ALIAS: fetch_alias_info_to_ldif(mem_ctx, u.alias, - &l->groupmap[*g_index], + &l->groupmap[*g_index_p], l->add_file, ctx->domain_sid_str, l->suffix, database_id); - (*g_index)++; + (*g_index_p)++; break; case NETR_DELTA_GROUP_MEMBER: @@ -1156,15 +1160,12 @@ static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx, /**************************************************************** ****************************************************************/ -NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx) +static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t *sequence_num) { NTSTATUS status; - int i; - uint32_t g_index = 0, a_index = 0; struct samsync_ldif_context *ldif_ctx = (struct samsync_ldif_context *)ctx->private_data; @@ -1174,11 +1175,28 @@ NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx, ctx->domain_sid_str, &ldif_ctx); if (!NT_STATUS_IS_OK(status)) { - goto failed; + return status; } ctx->private_data = ldif_ctx; + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + uint64_t *sequence_num, + struct samsync_context *ctx) +{ + NTSTATUS status; + int i; + struct samsync_ldif_context *ldif_ctx = + (struct samsync_ldif_context *)ctx->private_data; + status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas); if (!NT_STATUS_IS_OK(status)) { goto failed; @@ -1193,18 +1211,6 @@ NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx, } } - /* This was the last query */ - if (last_query) { - ldif_write_output(database_id, ldif_ctx); - if (ldif_ctx->ldif_file != stdout) { - ctx->result_message = talloc_asprintf(mem_ctx, - "Vampired %d accounts and %d groups to %s", - a_index, g_index, ctx->output_filename); - } - ldif_free_context(ldif_ctx); - ctx->private_data = NULL; - } - return NT_STATUS_OK; failed: @@ -1214,15 +1220,62 @@ NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx, return status; } +/**************************************************************** +****************************************************************/ + +static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t sequence_num) +{ + struct samsync_ldif_context *ldif_ctx = + (struct samsync_ldif_context *)ctx->private_data; + + /* This was the last query */ + ldif_write_output(database_id, ldif_ctx); + if (ldif_ctx->ldif_file != stdout) { + ctx->result_message = talloc_asprintf(ctx, + "Vampired %d accounts and %d groups to %s", + a_index, g_index, ctx->output_filename); + } + + ldif_free_context(ldif_ctx); + ctx->private_data = NULL; + + return NT_STATUS_OK; +} + #else /* HAVE_LDAP */ -NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx) +static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t *sequence_num) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + uint64_t *sequence_num, + struct samsync_context *ctx) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t sequence_num) { return NT_STATUS_NOT_SUPPORTED; } #endif + +const struct samsync_ops libnet_samsync_ldif_ops = { + .startup = init_ldif, + .process_objects = fetch_sam_entries_ldif, + .finish = close_ldif, +}; diff --git a/source3/libnet/libnet_samsync_passdb.c b/source3/libnet/libnet_samsync_passdb.c index 1faef7b3eb..388b10a0fa 100644 --- a/source3/libnet/libnet_samsync_passdb.c +++ b/source3/libnet/libnet_samsync_passdb.c @@ -118,12 +118,12 @@ static NTSTATUS sam_account_from_delta(struct samu *account, pdb_set_profile_path(account, new_string, PDB_CHANGED); } - if (r->parameters.string) { + if (r->parameters.array) { DATA_BLOB mung; char *newstr; old_string = pdb_get_munged_dial(account); - mung.length = r->parameters.length; - mung.data = (uint8 *) r->parameters.string; + mung.length = r->parameters.length * 2; + mung.data = (uint8_t *) r->parameters.array; newstr = (mung.length == 0) ? NULL : base64_encode_data_blob(talloc_tos(), mung); @@ -772,11 +772,11 @@ static NTSTATUS fetch_sam_entry(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -NTSTATUS fetch_sam_entries(TALLOC_CTX *mem_ctx, - enum netr_SamDatabaseID database_id, - struct netr_DELTA_ENUM_ARRAY *r, - bool last_query, - struct samsync_context *ctx) +static NTSTATUS fetch_sam_entries(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + uint64_t *sequence_num, + struct samsync_context *ctx) { int i; @@ -786,3 +786,7 @@ NTSTATUS fetch_sam_entries(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } + +const struct samsync_ops libnet_samsync_passdb_ops = { + .process_objects = fetch_sam_entries, +}; |