From 7a1fa41dcafc0f2c2ae1052ba7dced0c06632b72 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 12 Jun 2008 12:35:46 +0200 Subject: net_vampire: restructure internal code more. Guenther (This used to be commit 9557504d70fe57098914da131b39212faf4f0a7d) --- source3/utils/net.h | 30 ++ source3/utils/net_rpc_samsync.c | 738 +++++++++++++++++++++++----------------- 2 files changed, 456 insertions(+), 312 deletions(-) (limited to 'source3') diff --git a/source3/utils/net.h b/source3/utils/net.h index e5bd2ab692..627ac0aaa1 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -158,3 +158,33 @@ typedef struct _accountmap { uint32_t rid; const char *cn; } ACCOUNTMAP; + +enum net_samsync_mode { + NET_SAMSYNC_MODE_FETCH_PASSDB = 0, + NET_SAMSYNC_MODE_FETCH_LDIF = 1, + NET_SAMSYNC_MODE_DUMP = 2 +}; + +struct samsync_ldif_context { + GROUPMAP *groupmap; + ACCOUNTMAP *accountmap; + bool initialized; + const char *add_template; + const char *mod_template; + char *add_name; + char *mod_name; + FILE *add_file; + FILE *mod_file; + FILE *ldif_file; + const char *suffix; + int num_alloced; +}; + +struct samsync_context { + enum net_samsync_mode mode; + const struct dom_sid *domain_sid; + const char *domain_sid_str; + const char *ldif_filename; + + struct samsync_ldif_context *ldif; +}; diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index cdda0232d8..f6483bdba2 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -29,13 +29,6 @@ /* uid's and gid's for writing deltas to ldif */ static uint32 ldif_gid = 999; static uint32 ldif_uid = 999; -/* Keep track of ldap initialization */ -static int init_ldap = 1; - -enum net_samsync_mode { - NET_SAMSYNC_MODE_FETCH_PASSDB = 0, - NET_SAMSYNC_MODE_DUMP = 1 -}; static void display_group_mem_info(uint32_t rid, struct netr_DELTA_GROUP_MEMBER *r) @@ -177,8 +170,11 @@ static void display_group_info(uint32_t rid, struct netr_DELTA_GROUP *r) d_printf("desc='%s', rid=%u\n", r->description.string, rid); } -static NTSTATUS display_sam_entry(struct netr_DELTA_ENUM *r, - const DOM_SID *domain_sid) +static NTSTATUS display_sam_entry(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM *r, + NTSTATUS status, + struct samsync_context *ctx) { union netr_DELTA_UNION u = r->delta_union; union netr_DELTA_ID_UNION id = r->delta_id_union; @@ -332,13 +328,33 @@ static NTSTATUS display_sam_entry(struct netr_DELTA_ENUM *r, return NT_STATUS_OK; } +static NTSTATUS display_sam_entries(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + NTSTATUS status, + 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], status, ctx); + } + + return NT_STATUS_OK; +} + +typedef NTSTATUS (*samsync_fn_t)(TALLOC_CTX *, + enum netr_SamDatabaseID, + struct netr_DELTA_ENUM_ARRAY *, + NTSTATUS, + struct samsync_context *); + static NTSTATUS process_database(struct rpc_pipe_client *pipe_hnd, enum netr_SamDatabaseID database_id, - enum net_samsync_mode mode, - NTSTATUS (*callback_fn)(struct netr_DELTA_ENUM *, const DOM_SID *), const DOM_SID *domain_sid) + samsync_fn_t callback_fn, + struct samsync_context *ctx) { NTSTATUS result; - int i; TALLOC_CTX *mem_ctx; const char *logon_server = pipe_hnd->desthost; const char *computername = global_myname(); @@ -355,12 +371,15 @@ static NTSTATUS process_database(struct rpc_pipe_client *pipe_hnd, return NT_STATUS_NO_MEMORY; } - switch (mode) { + switch (ctx->mode) { case NET_SAMSYNC_MODE_DUMP: - action = "Dumping"; + action = "Dumping (to stdout)"; break; case NET_SAMSYNC_MODE_FETCH_PASSDB: - action = "Fetching"; + action = "Fetching (to passdb)"; + break; + case NET_SAMSYNC_MODE_FETCH_LDIF: + action = "Fetching (to ldif)"; break; default: action = "Unknown"; @@ -369,16 +388,16 @@ static NTSTATUS process_database(struct rpc_pipe_client *pipe_hnd, switch (database_id) { case SAM_DATABASE_DOMAIN: - d_printf("%s DOMAIN database\n", action); + d_fprintf(stderr, "%s DOMAIN database\n", action); break; case SAM_DATABASE_BUILTIN: - d_printf("%s BUILTIN database\n", action); + d_fprintf(stderr, "%s BUILTIN database\n", action); break; case SAM_DATABASE_PRIVS: - d_printf("%s PRIVS databases\n", action); + d_fprintf(stderr, "%s PRIVS databases\n", action); break; default: - d_printf("%s unknown database type %u\n", + d_fprintf(stderr, "%s unknown database type %u\n", action, database_id); break; } @@ -398,6 +417,9 @@ static NTSTATUS process_database(struct rpc_pipe_client *pipe_hnd, &sync_context, &delta_enum_array, 0xffff); + if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) { + return result; + } /* Check returned credentials. */ if (!netlogon_creds_client_check(pipe_hnd->dc, @@ -418,14 +440,14 @@ static NTSTATUS process_database(struct rpc_pipe_client *pipe_hnd, database_id, delta_enum_array); - /* Display results */ - for (i = 0; i < delta_enum_array->num_deltas; i++) { - callback_fn(&delta_enum_array->delta_enum[i], - domain_sid); - } + /* Process results */ + callback_fn(mem_ctx, database_id, delta_enum_array, result, ctx); TALLOC_FREE(delta_enum_array); + /* Increment sync_context */ + sync_context += 1; + } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); talloc_destroy(mem_ctx); @@ -443,17 +465,22 @@ NTSTATUS rpc_samdump_internals(struct net_context *c, int argc, const char **argv) { + struct samsync_context *ctx; + + ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context); + NT_STATUS_HAVE_NO_MEMORY(ctx); + + ctx->mode = NET_SAMSYNC_MODE_DUMP; + ctx->domain_sid = domain_sid; + process_database(pipe_hnd, SAM_DATABASE_DOMAIN, - NET_SAMSYNC_MODE_DUMP, - display_sam_entry, domain_sid); + display_sam_entries, ctx); process_database(pipe_hnd, SAM_DATABASE_BUILTIN, - NET_SAMSYNC_MODE_DUMP, - display_sam_entry, domain_sid); + display_sam_entries, ctx); process_database(pipe_hnd, SAM_DATABASE_PRIVS, - NET_SAMSYNC_MODE_DUMP, - display_sam_entry, domain_sid); + display_sam_entries, ctx); return NT_STATUS_OK; } @@ -1116,7 +1143,10 @@ static NTSTATUS fetch_domain_info(uint32_t rid, return NT_STATUS_OK; } -static NTSTATUS fetch_sam_entry(struct netr_DELTA_ENUM *r, const DOM_SID *dom_sid) +static NTSTATUS fetch_sam_entry(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM *r, + struct samsync_context *ctx) { switch(r->delta_type) { case NETR_DELTA_USER: @@ -1134,12 +1164,12 @@ static NTSTATUS fetch_sam_entry(struct netr_DELTA_ENUM *r, const DOM_SID *dom_si case NETR_DELTA_ALIAS: fetch_alias_info(r->delta_id_union.rid, r->delta_union.alias, - dom_sid); + ctx->domain_sid); break; case NETR_DELTA_ALIAS_MEMBER: fetch_alias_mem(r->delta_id_union.rid, r->delta_union.alias_member, - dom_sid); + ctx->domain_sid); break; case NETR_DELTA_DOMAIN: fetch_domain_info(r->delta_id_union.rid, @@ -1202,8 +1232,28 @@ static NTSTATUS fetch_sam_entry(struct netr_DELTA_ENUM *r, const DOM_SID *dom_si return NT_STATUS_OK; } -static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const char - *builtin_sid, FILE *add_fd) +static NTSTATUS fetch_sam_entries(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + NTSTATUS status, + struct samsync_context *ctx) +{ + int i; + + for (i = 0; i < r->num_deltas; i++) { + fetch_sam_entry(mem_ctx, database_id, &r->delta_enum[i], ctx); + } + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS populate_ldap_for_ldif(const char *sid, + const char *suffix, + const char *builtin_sid, + FILE *add_fd) { const char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix; char *user_attr=NULL, *group_attr=NULL; @@ -1459,10 +1509,13 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch return NT_STATUS_OK; } +/**************************************************************** +****************************************************************/ + static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx, GROUPMAP *groupmap, ACCOUNTMAP *accountmap, - fstring sid, + const char *sid, const char *suffix, const char *builtin_sid) { @@ -1631,20 +1684,20 @@ static int fprintf_attr(FILE *add_fd, const char *attr_name, return res; } +/**************************************************************** +****************************************************************/ + static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx, struct netr_DELTA_GROUP *r, GROUPMAP *groupmap, FILE *add_fd, - fstring sid, - char *suffix) + const char *sid, + const char *suffix) { - fstring groupname; + const char *groupname = r->group_name.string; uint32 grouptype = 0, g_rid = 0; char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ','); - /* Get the group name */ - fstrcpy(groupname, r->group_name.string); - /* Set up the group type (always 2 for group info) */ grouptype = 2; @@ -1694,12 +1747,16 @@ static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/**************************************************************** +****************************************************************/ + static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx, struct netr_DELTA_USER *r, GROUPMAP *groupmap, ACCOUNTMAP *accountmap, FILE *add_fd, - fstring sid, char *suffix, + const char *sid, + const char *suffix, int alloced) { fstring username, logonscript, homedrive, homepath = "", homedir = ""; @@ -1841,12 +1898,16 @@ static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/**************************************************************** +****************************************************************/ + static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx, struct netr_DELTA_ALIAS *r, GROUPMAP *groupmap, - FILE *add_fd, fstring sid, - char *suffix, - unsigned db_type) + FILE *add_fd, + const char *sid, + const char *suffix, + enum netr_SamDatabaseID database_id) { fstring aliasname, description; uint32 grouptype = 0, g_rid = 0; @@ -1859,7 +1920,7 @@ static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx, fstrcpy(description, r->description.string); /* Set up the group type */ - switch (db_type) { + switch (database_id) { case SAM_DATABASE_DOMAIN: grouptype = 4; break; @@ -1919,6 +1980,9 @@ static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +/**************************************************************** +****************************************************************/ + static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r, uint32_t id_rid, GROUPMAP *groupmap, @@ -1964,324 +2028,370 @@ static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r, return NT_STATUS_OK; } -static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd, - uint32 db_type, - const DOM_SID *dom_sid, - const char *user_file) +/**************************************************************** +****************************************************************/ + +static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id) { - char *suffix; - const char *builtin_sid = "S-1-5-32"; - char *add_name = NULL, *mod_name = NULL; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + struct samsync_ldif_context *r; const char *add_template = "/tmp/add.ldif.XXXXXX"; const char *mod_template = "/tmp/mod.ldif.XXXXXX"; - fstring sid, domainname; - NTSTATUS ret = NT_STATUS_OK, result; - int k; - TALLOC_CTX *mem_ctx; - uint32 num_deltas; - FILE *add_file = NULL, *mod_file = NULL, *ldif_file = NULL; - int num_alloced = 0, g_index = 0, a_index = 0; - const char *logon_server = pipe_hnd->desthost; - const char *computername = global_myname(); - struct netr_Authenticator credential; - struct netr_Authenticator return_authenticator; - enum netr_SamDatabaseID database_id = db_type; - uint16_t restart_state = 0; - uint32_t sync_context = 0; - DATA_BLOB session_key; + const char *builtin_sid = "S-1-5-32"; - /* Set up array for mapping accounts to groups */ - /* Array element is the group rid */ - GROUPMAP *groupmap = NULL; + if (ctx->ldif && ctx->ldif->initialized) { + return NT_STATUS_OK; + } - /* Set up array for mapping account rid's to cn's */ - /* Array element is the account rid */ - ACCOUNTMAP *accountmap = NULL; + r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context); + NT_STATUS_HAVE_NO_MEMORY(r); - if (!(mem_ctx = talloc_init("fetch_database"))) { - return NT_STATUS_NO_MEMORY; + /* Get other smb.conf data */ + if (!(lp_workgroup()) || !*(lp_workgroup())) { + DEBUG(0,("workgroup missing from smb.conf--exiting\n")); + exit(1); } + /* Get the ldap suffix */ + r->suffix = lp_ldap_suffix(); + if (r->suffix == NULL || strcmp(r->suffix, "") == 0) { + DEBUG(0,("ldap suffix missing from smb.conf--exiting\n")); + exit(1); + } + + /* Get the sid */ + ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid); + NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid_str); + /* Ensure we have an output file */ - if (user_file) - ldif_file = fopen(user_file, "a"); - else - ldif_file = stdout; + if (ctx->ldif_filename) { + r->ldif_file = fopen(ctx->ldif_filename, "a"); + } else { + r->ldif_file = stdout; + } - if (!ldif_file) { - fprintf(stderr, "Could not open %s\n", user_file); - DEBUG(1, ("Could not open %s\n", user_file)); - ret = NT_STATUS_UNSUCCESSFUL; + if (!r->ldif_file) { + fprintf(stderr, "Could not open %s\n", ctx->ldif_filename); + DEBUG(1, ("Could not open %s\n", ctx->ldif_filename)); + status = NT_STATUS_UNSUCCESSFUL; goto done; } - add_name = talloc_strdup(mem_ctx, add_template); - mod_name = talloc_strdup(mem_ctx, mod_template); - if (!add_name || !mod_name) { - ret = NT_STATUS_NO_MEMORY; + r->add_template = talloc_strdup(mem_ctx, add_template); + r->mod_template = talloc_strdup(mem_ctx, mod_template); + if (!r->add_template || !r->mod_template) { + status = NT_STATUS_NO_MEMORY; goto done; } - /* Open the add and mod ldif files */ - if (!(add_file = fdopen(smb_mkstemp(add_name),"w"))) { - DEBUG(1, ("Could not open %s\n", add_name)); - ret = NT_STATUS_UNSUCCESSFUL; + r->add_name = talloc_strdup(mem_ctx, add_template); + r->mod_name = talloc_strdup(mem_ctx, mod_template); + if (!r->add_name || !r->mod_name) { + status = NT_STATUS_NO_MEMORY; goto done; } - if (!(mod_file = fdopen(smb_mkstemp(mod_name),"w"))) { - DEBUG(1, ("Could not open %s\n", mod_name)); - ret = NT_STATUS_UNSUCCESSFUL; + + /* Open the add and mod ldif files */ + if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) { + DEBUG(1, ("Could not open %s\n", r->add_name)); + status = NT_STATUS_UNSUCCESSFUL; goto done; } - - /* Get the sid */ - sid_to_fstring(sid, dom_sid); - - /* Get the ldap suffix */ - suffix = lp_ldap_suffix(); - if (suffix == NULL || strcmp(suffix, "") == 0) { - DEBUG(0,("ldap suffix missing from smb.conf--exiting\n")); - exit(1); + if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) { + DEBUG(1, ("Could not open %s\n", r->mod_name)); + status = NT_STATUS_UNSUCCESSFUL; + goto done; } - /* Get other smb.conf data */ - if (!(lp_workgroup()) || !*(lp_workgroup())) { - DEBUG(0,("workgroup missing from smb.conf--exiting\n")); - exit(1); + /* Allocate initial memory for groupmap and accountmap arrays */ + r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8); + r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8); + if (r->groupmap == NULL || r->accountmap == NULL) { + DEBUG(1,("GROUPMAP talloc failed\n")); + status = NT_STATUS_NO_MEMORY; + goto done; } - /* Allocate initial memory for groupmap and accountmap arrays */ - if (init_ldap == 1) { - groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8); - accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8); - if (groupmap == NULL || accountmap == NULL) { - DEBUG(1,("GROUPMAP malloc failed\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } + /* Remember how many we malloced */ + r->num_alloced = 8; - /* Remember how many we malloced */ - num_alloced = 8; + /* Initial database population */ + if (database_id == SAM_DATABASE_DOMAIN) { - /* Initial database population */ - ret = populate_ldap_for_ldif(sid, suffix, builtin_sid, add_file); - if (!NT_STATUS_IS_OK(ret)) { + status = populate_ldap_for_ldif(ctx->domain_sid_str, + r->suffix, + builtin_sid, + r->add_file); + if (!NT_STATUS_IS_OK(status)) { goto done; } - ret = map_populate_groups(mem_ctx, groupmap, accountmap, sid, suffix, - builtin_sid); - if (!NT_STATUS_IS_OK(ret)) { + + status = map_populate_groups(mem_ctx, + r->groupmap, + r->accountmap, + ctx->domain_sid_str, + r->suffix, + builtin_sid); + if (!NT_STATUS_IS_OK(status)) { goto done; } - - /* Don't do this again */ - init_ldap = 0; } - /* Announce what we are doing */ - switch( db_type ) { - case SAM_DATABASE_DOMAIN: - d_fprintf(stderr, "Fetching DOMAIN database\n"); - break; - case SAM_DATABASE_BUILTIN: - d_fprintf(stderr, "Fetching BUILTIN database\n"); - break; - case SAM_DATABASE_PRIVS: - d_fprintf(stderr, "Fetching PRIVS databases\n"); - break; - default: - d_fprintf(stderr, - "Fetching unknown database type %u\n", - db_type ); - break; - } + r->initialized = true; - do { - struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; - - netlogon_creds_client_step(pipe_hnd->dc, &credential); + ctx->ldif = r; - result = rpccli_netr_DatabaseSync2(pipe_hnd, mem_ctx, - logon_server, - computername, - &credential, - &return_authenticator, - database_id, - restart_state, - &sync_context, - &delta_enum_array, - 0xffff); - - /* Check returned credentials. */ - if (!netlogon_creds_client_check(pipe_hnd->dc, - &return_authenticator.cred)) { - DEBUG(0,("credentials chain check failed\n")); - return NT_STATUS_ACCESS_DENIED; - } - - if (NT_STATUS_IS_ERR(result)) { - break; - } - - session_key = data_blob_const(pipe_hnd->dc->sess_key, 16); - - samsync_fix_delta_array(mem_ctx, - &session_key, - true, - database_id, - delta_enum_array); - - num_deltas = delta_enum_array->num_deltas; - - /* Re-allocate memory for groupmap and accountmap arrays */ - groupmap = TALLOC_REALLOC_ARRAY(mem_ctx, groupmap, GROUPMAP, - num_deltas+num_alloced); - accountmap = TALLOC_REALLOC_ARRAY(mem_ctx, accountmap, ACCOUNTMAP, - num_deltas+num_alloced); - if (groupmap == NULL || accountmap == NULL) { - DEBUG(1,("GROUPMAP talloc failed\n")); - ret = NT_STATUS_NO_MEMORY; - goto done; - } - - /* Initialize the new records */ - memset(&groupmap[num_alloced], 0, - sizeof(GROUPMAP)*num_deltas); - memset(&accountmap[num_alloced], 0, - sizeof(ACCOUNTMAP)*num_deltas); - - /* Remember how many we alloced this time */ - num_alloced += num_deltas; + return NT_STATUS_OK; + done: + TALLOC_FREE(r); + return status; +} - /* Loop through the deltas */ - for (k=0; kdelta_enum[k].delta_union; - union netr_DELTA_ID_UNION id = - delta_enum_array->delta_enum[k].delta_id_union; +static void ldif_free_context(struct samsync_ldif_context *r) +{ + if (!r) { + return; + } - switch(delta_enum_array->delta_enum[k].delta_type) { - case NETR_DELTA_DOMAIN: - /* Is this case needed? */ - fstrcpy(domainname, - u.domain->domain_name.string); - break; + /* Close and delete the ldif files */ + if (r->add_file) { + fclose(r->add_file); + } - case NETR_DELTA_GROUP: - fetch_group_info_to_ldif(mem_ctx, - u.group, - &groupmap[g_index], - add_file, sid, suffix); - g_index++; - break; + if ((r->add_name != NULL) && + strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) { + DEBUG(1,("unlink(%s) failed, error was (%s)\n", + r->add_name, strerror(errno))); + } - case NETR_DELTA_USER: - fetch_account_info_to_ldif(mem_ctx, - u.user, groupmap, - &accountmap[a_index], add_file, - sid, suffix, num_alloced); - a_index++; - break; + if (r->mod_file) { + fclose(r->mod_file); + } - case NETR_DELTA_ALIAS: - fetch_alias_info_to_ldif(mem_ctx, - u.alias, &groupmap[g_index], - add_file, sid, suffix, db_type); - g_index++; - break; + if ((r->mod_name != NULL) && + strcmp(r->mod_name, r->mod_template) && (unlink(r->mod_name))) { + DEBUG(1,("unlink(%s) failed, error was (%s)\n", + r->mod_name, strerror(errno))); + } - case NETR_DELTA_GROUP_MEMBER: - fetch_groupmem_info_to_ldif( - u.group_member, id.rid, - groupmap, accountmap, - mod_file, num_alloced); - break; + if (r->ldif_file && (r->ldif_file != stdout)) { + fclose(r->ldif_file); + } - case NETR_DELTA_ALIAS_MEMBER: - case NETR_DELTA_POLICY: - case NETR_DELTA_ACCOUNT: - case NETR_DELTA_TRUSTED_DOMAIN: - case NETR_DELTA_SECRET: - case NETR_DELTA_RENAME_GROUP: - case NETR_DELTA_RENAME_USER: - case NETR_DELTA_RENAME_ALIAS: - case NETR_DELTA_DELETE_GROUP: - case NETR_DELTA_DELETE_USER: - case NETR_DELTA_MODIFY_COUNT: - default: - break; - } /* end of switch */ - } /* end of for loop */ + TALLOC_FREE(r); +} - /* Increment sync_context */ - sync_context += 1; +/**************************************************************** +****************************************************************/ - } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); +static void ldif_write_output(enum netr_SamDatabaseID database_id, + struct samsync_context *ctx) +{ + struct samsync_ldif_context *l = ctx->ldif; /* Write ldif data to the user's file */ - if (db_type == SAM_DATABASE_DOMAIN) { - fprintf(ldif_file, + if (database_id == SAM_DATABASE_DOMAIN) { + fprintf(l->ldif_file, "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n"); - fprintf(ldif_file, + fprintf(l->ldif_file, "# =================================\n\n"); - fflush(ldif_file); - } else if (db_type == SAM_DATABASE_BUILTIN) { - fprintf(ldif_file, + fflush(l->ldif_file); + } else if (database_id == SAM_DATABASE_BUILTIN) { + fprintf(l->ldif_file, "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n"); - fprintf(ldif_file, + fprintf(l->ldif_file, "# ==================================\n\n"); - fflush(ldif_file); + fflush(l->ldif_file); } - fseek(add_file, 0, SEEK_SET); - transfer_file(fileno(add_file), fileno(ldif_file), (size_t) -1); + fseek(l->add_file, 0, SEEK_SET); + transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1); - if (db_type == SAM_DATABASE_DOMAIN) { - fprintf(ldif_file, + if (database_id == SAM_DATABASE_DOMAIN) { + fprintf(l->ldif_file, "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n"); - fprintf(ldif_file, + fprintf(l->ldif_file, "# ====================================\n\n"); - fflush(ldif_file); - } else if (db_type == SAM_DATABASE_BUILTIN) { - fprintf(ldif_file, + fflush(l->ldif_file); + } else if (database_id == SAM_DATABASE_BUILTIN) { + fprintf(l->ldif_file, "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n"); - fprintf(ldif_file, + fprintf(l->ldif_file, "# =====================================\n\n"); - fflush(ldif_file); + fflush(l->ldif_file); } - fseek(mod_file, 0, SEEK_SET); - transfer_file(fileno(mod_file), fileno(ldif_file), (size_t) -1); + fseek(l->mod_file, 0, SEEK_SET); + transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1); +} +/**************************************************************** +****************************************************************/ - done: - /* Close and delete the ldif files */ - if (add_file) { - fclose(add_file); +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) +{ + union netr_DELTA_UNION u = r->delta_union; + union netr_DELTA_ID_UNION id = r->delta_id_union; + struct samsync_ldif_context *l = ctx->ldif; + + switch (r->delta_type) { + case NETR_DELTA_DOMAIN: + break; + + case NETR_DELTA_GROUP: + fetch_group_info_to_ldif(mem_ctx, + u.group, + &l->groupmap[*g_index], + l->add_file, + ctx->domain_sid_str, + l->suffix); + (*g_index)++; + break; + + case NETR_DELTA_USER: + fetch_account_info_to_ldif(mem_ctx, + u.user, + l->groupmap, + &l->accountmap[*a_index], + l->add_file, + ctx->domain_sid_str, + l->suffix, + l->num_alloced); + (*a_index)++; + break; + + case NETR_DELTA_ALIAS: + fetch_alias_info_to_ldif(mem_ctx, + u.alias, + &l->groupmap[*g_index], + l->add_file, + ctx->domain_sid_str, + l->suffix, + database_id); + (*g_index)++; + break; + + case NETR_DELTA_GROUP_MEMBER: + fetch_groupmem_info_to_ldif(u.group_member, + id.rid, + l->groupmap, + l->accountmap, + l->mod_file, + l->num_alloced); + break; + + case NETR_DELTA_ALIAS_MEMBER: + case NETR_DELTA_POLICY: + case NETR_DELTA_ACCOUNT: + case NETR_DELTA_TRUSTED_DOMAIN: + case NETR_DELTA_SECRET: + case NETR_DELTA_RENAME_GROUP: + case NETR_DELTA_RENAME_USER: + case NETR_DELTA_RENAME_ALIAS: + case NETR_DELTA_DELETE_GROUP: + case NETR_DELTA_DELETE_USER: + case NETR_DELTA_MODIFY_COUNT: + default: + break; + } /* end of switch */ + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + uint32_t num_entries) +{ + struct samsync_ldif_context *l = ctx->ldif; + + if (!l) { + return NT_STATUS_INVALID_PARAMETER; } - if ((add_name != NULL) && - strcmp(add_name, add_template) && (unlink(add_name))) { - DEBUG(1,("unlink(%s) failed, error was (%s)\n", - add_name, strerror(errno))); + /* Re-allocate memory for groupmap and accountmap arrays */ + l->groupmap = TALLOC_REALLOC_ARRAY(mem_ctx, + l->groupmap, + GROUPMAP, + num_entries + l->num_alloced); + + l->accountmap = TALLOC_REALLOC_ARRAY(mem_ctx, + l->accountmap, + ACCOUNTMAP, + num_entries + l->num_alloced); + + if (l->groupmap == NULL || l->accountmap == NULL) { + DEBUG(1,("GROUPMAP talloc failed\n")); + return NT_STATUS_NO_MEMORY; } - if (mod_file) { - fclose(mod_file); + /* Initialize the new records */ + memset(&(l->groupmap[l->num_alloced]), 0, + sizeof(GROUPMAP) * num_entries); + memset(&(l->accountmap[l->num_alloced]), 0, + sizeof(ACCOUNTMAP) * num_entries); + + /* Remember how many we alloced this time */ + l->num_alloced += num_entries; + + 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, + NTSTATUS result, + struct samsync_context *ctx) +{ + NTSTATUS status; + int i; + uint32_t g_index = 0, a_index = 0; + + status = ldif_init_context(mem_ctx, ctx, database_id); + if (!NT_STATUS_IS_OK(status)) { + goto failed; } - if ((mod_name != NULL) && - strcmp(mod_name, mod_template) && (unlink(mod_name))) { - DEBUG(1,("unlink(%s) failed, error was (%s)\n", - mod_name, strerror(errno))); + status = ldif_realloc_maps(mem_ctx, ctx, r->num_deltas); + if (!NT_STATUS_IS_OK(status)) { + goto failed; } - if (ldif_file && (ldif_file != stdout)) { - fclose(ldif_file); + for (i = 0; i < r->num_deltas; i++) { + status = fetch_sam_entry_ldif(mem_ctx, database_id, + &r->delta_enum[i], ctx, + &g_index, &a_index); + if (!NT_STATUS_IS_OK(status)) { + goto failed; + } } - /* Return */ - talloc_destroy(mem_ctx); - return ret; + /* This was the last query */ + if (NT_STATUS_IS_OK(result)) { + ldif_write_output(database_id, ctx); + ldif_free_context(ctx->ldif); + ctx->ldif = NULL; + } + + return NT_STATUS_OK; + + failed: + ldif_free_context(ctx->ldif); + + return status; } /** @@ -2319,6 +2429,11 @@ NTSTATUS rpc_vampire_internals(struct net_context *c, NTSTATUS result; fstring my_dom_sid_str; fstring rem_dom_sid_str; + struct samsync_context *ctx; + samsync_fn_t *fn; + + ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context); + NT_STATUS_HAVE_NO_MEMORY(ctx); if (!sid_equal(domain_sid, get_global_sam_sid())) { d_printf("Cannot import users from %s at this time, " @@ -2337,14 +2452,18 @@ NTSTATUS rpc_vampire_internals(struct net_context *c, } if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) { - result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_DOMAIN, - domain_sid, argv[1]); - } else { - result = process_database(pipe_hnd, SAM_DATABASE_DOMAIN, - NET_SAMSYNC_MODE_FETCH_PASSDB, - fetch_sam_entry, domain_sid); - } + ctx->mode = NET_SAMSYNC_MODE_FETCH_LDIF; + ctx->ldif_filename = argv[1]; + fn = (samsync_fn_t *)fetch_sam_entries_ldif; + } else { + ctx->mode = NET_SAMSYNC_MODE_FETCH_PASSDB; + fn = (samsync_fn_t *)fetch_sam_entries; + } + /* fetch domain */ + ctx->domain_sid = domain_sid; + result = process_database(pipe_hnd, SAM_DATABASE_DOMAIN, + (samsync_fn_t)fn, ctx); if (!NT_STATUS_IS_OK(result)) { d_fprintf(stderr, "Failed to fetch domain database: %s\n", nt_errstr(result)); @@ -2354,15 +2473,10 @@ NTSTATUS rpc_vampire_internals(struct net_context *c, goto fail; } - if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) { - result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_BUILTIN, - &global_sid_Builtin, argv[1]); - } else { - result = process_database(pipe_hnd, SAM_DATABASE_BUILTIN, - NET_SAMSYNC_MODE_FETCH_PASSDB, - fetch_sam_entry, &global_sid_Builtin); - } - + /* fetch builtin */ + ctx->domain_sid = &global_sid_Builtin; + result = process_database(pipe_hnd, SAM_DATABASE_BUILTIN, + (samsync_fn_t)fn, ctx); if (!NT_STATUS_IS_OK(result)) { d_fprintf(stderr, "Failed to fetch builtin database: %s\n", nt_errstr(result)); -- cgit