diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2009-03-20 01:30:36 +0100 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2009-03-20 01:30:36 +0100 |
commit | 5fe2b28f45289dc5578cdd536600f0d30a14d820 (patch) | |
tree | 4bdf36d0d4d8bdddcb3d618b4b01839370ed57c3 /source3/passdb | |
parent | ec9aeeab00584f4d3dfe9afb83dc1a77b8463b81 (diff) | |
parent | 3a4638db0351368d3b148bf547546f28fa0b1479 (diff) | |
download | samba-5fe2b28f45289dc5578cdd536600f0d30a14d820.tar.gz samba-5fe2b28f45289dc5578cdd536600f0d30a14d820.tar.bz2 samba-5fe2b28f45289dc5578cdd536600f0d30a14d820.zip |
Merge branch 'master' of git://git.samba.org/samba into minschema
Diffstat (limited to 'source3/passdb')
-rw-r--r-- | source3/passdb/lookup_sid.c | 38 | ||||
-rw-r--r-- | source3/passdb/pdb_interface.c | 63 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 20 | ||||
-rw-r--r-- | source3/passdb/pdb_smbpasswd.c | 9 | ||||
-rw-r--r-- | source3/passdb/pdb_tdb.c | 227 | ||||
-rw-r--r-- | source3/passdb/pdb_wbc_sam.c | 12 |
6 files changed, 281 insertions, 88 deletions
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 53845117e2..9c20042a62 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -1308,13 +1308,20 @@ void uid_to_sid(DOM_SID *psid, uid_t uid) if (!ret || expired) { /* Not in cache. Ask winbindd. */ if (!winbind_uid_to_sid(psid, uid)) { - if (!winbind_ping()) { - legacy_uid_to_sid(psid, uid); - return; - } + /* + * We shouldn't return the NULL SID + * here if winbind was running and + * couldn't map, as winbind will have + * added a negative entry that will + * cause us to go though the + * legacy_uid_to_sid() + * function anyway in the case above + * the next time we ask. + */ + DEBUG(5, ("uid_to_sid: winbind failed to find a sid " + "for uid %u\n", uid)); - DEBUG(5, ("uid_to_sid: winbind failed to find a sid for uid %u\n", - uid)); + legacy_uid_to_sid(psid, uid); return; } } @@ -1354,13 +1361,20 @@ void gid_to_sid(DOM_SID *psid, gid_t gid) if (!ret || expired) { /* Not in cache. Ask winbindd. */ if (!winbind_gid_to_sid(psid, gid)) { - if (!winbind_ping()) { - legacy_gid_to_sid(psid, gid); - return; - } + /* + * We shouldn't return the NULL SID + * here if winbind was running and + * couldn't map, as winbind will have + * added a negative entry that will + * cause us to go though the + * legacy_gid_to_sid() + * function anyway in the case above + * the next time we ask. + */ + DEBUG(5, ("gid_to_sid: winbind failed to find a sid " + "for gid %u\n", gid)); - DEBUG(5, ("gid_to_sid: winbind failed to find a sid for gid %u\n", - gid)); + legacy_gid_to_sid(psid, gid); return; } } diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index e618b425e0..1909bd0da4 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -1709,24 +1709,25 @@ static NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods, } #endif -struct pdb_search *pdb_search_init(enum pdb_search_type type) +static int pdb_search_destructor(struct pdb_search *search) { - TALLOC_CTX *mem_ctx; - struct pdb_search *result; - - mem_ctx = talloc_init("pdb_search"); - if (mem_ctx == NULL) { - DEBUG(0, ("talloc_init failed\n")); - return NULL; + if (!search->search_ended) { + search->search_end(search); } + return 0; +} - result = TALLOC_P(mem_ctx, struct pdb_search); +struct pdb_search *pdb_search_init(TALLOC_CTX *mem_ctx, + enum pdb_search_type type) +{ + struct pdb_search *result; + + result = talloc(mem_ctx, struct pdb_search); if (result == NULL) { DEBUG(0, ("talloc failed\n")); return NULL; } - result->mem_ctx = mem_ctx; result->type = type; result->cache = NULL; result->num_entries = 0; @@ -1737,6 +1738,8 @@ struct pdb_search *pdb_search_init(enum pdb_search_type type) result->next_entry = NULL; result->search_end = NULL; + talloc_set_destructor(result, pdb_search_destructor); + return result; } @@ -1783,8 +1786,7 @@ static bool next_entry_groups(struct pdb_search *s, sid_peek_rid(&map->sid, &rid); - fill_displayentry(s->mem_ctx, rid, 0, map->nt_name, NULL, map->comment, - entry); + fill_displayentry(s, rid, 0, map->nt_name, NULL, map->comment, entry); state->current_group += 1; return True; @@ -1802,7 +1804,7 @@ static bool pdb_search_grouptype(struct pdb_search *search, { struct group_search *state; - state = TALLOC_P(search->mem_ctx, struct group_search); + state = talloc(search, struct group_search); if (state == NULL) { DEBUG(0, ("talloc failed\n")); return False; @@ -1853,7 +1855,7 @@ static struct samr_displayentry *pdb_search_getentry(struct pdb_search *search, break; } - ADD_TO_LARGE_ARRAY(search->mem_ctx, struct samr_displayentry, + ADD_TO_LARGE_ARRAY(search, struct samr_displayentry, entry, &search->cache, &search->num_entries, &search->cache_size); } @@ -1861,52 +1863,54 @@ static struct samr_displayentry *pdb_search_getentry(struct pdb_search *search, return (search->num_entries > idx) ? &search->cache[idx] : NULL; } -struct pdb_search *pdb_search_users(uint32 acct_flags) +struct pdb_search *pdb_search_users(TALLOC_CTX *mem_ctx, uint32 acct_flags) { struct pdb_methods *pdb = pdb_get_methods(); struct pdb_search *result; - result = pdb_search_init(PDB_USER_SEARCH); + result = pdb_search_init(mem_ctx, PDB_USER_SEARCH); if (result == NULL) { return NULL; } if (!pdb->search_users(pdb, result, acct_flags)) { - talloc_destroy(result->mem_ctx); + TALLOC_FREE(result); return NULL; } return result; } -struct pdb_search *pdb_search_groups(void) +struct pdb_search *pdb_search_groups(TALLOC_CTX *mem_ctx) { struct pdb_methods *pdb = pdb_get_methods(); struct pdb_search *result; - result = pdb_search_init(PDB_GROUP_SEARCH); + result = pdb_search_init(mem_ctx, PDB_GROUP_SEARCH); if (result == NULL) { return NULL; } if (!pdb->search_groups(pdb, result)) { - talloc_destroy(result->mem_ctx); + TALLOC_FREE(result); return NULL; } return result; } -struct pdb_search *pdb_search_aliases(const DOM_SID *sid) +struct pdb_search *pdb_search_aliases(TALLOC_CTX *mem_ctx, const DOM_SID *sid) { struct pdb_methods *pdb = pdb_get_methods(); struct pdb_search *result; if (pdb == NULL) return NULL; - result = pdb_search_init(PDB_ALIAS_SEARCH); - if (result == NULL) return NULL; + result = pdb_search_init(mem_ctx, PDB_ALIAS_SEARCH); + if (result == NULL) { + return NULL; + } if (!pdb->search_aliases(pdb, result, sid)) { - talloc_destroy(result->mem_ctx); + TALLOC_FREE(result); return NULL; } return result; @@ -1935,17 +1939,6 @@ uint32 pdb_search_entries(struct pdb_search *search, return search->num_entries - start_idx; } -void pdb_search_destroy(struct pdb_search *search) -{ - if (search == NULL) - return; - - if (!search->search_ended) - search->search_end(search); - - talloc_destroy(search->mem_ctx); -} - /******************************************************************* trustdom methods *******************************************************************/ diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 70a1c62bef..77b19e3de9 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -4349,7 +4349,8 @@ static bool ldapsam_search_next_entry(struct pdb_search *search, !ldapsam_search_nextpage(search)) return False; - result = state->ldap2displayentry(state, search->mem_ctx, state->connection->ldap_struct, + result = state->ldap2displayentry(state, search, + state->connection->ldap_struct, state->current_entry, entry); if (!result) { @@ -4508,7 +4509,7 @@ static bool ldapsam_search_users(struct pdb_methods *methods, (struct ldapsam_privates *)methods->private_data; struct ldap_search_state *state; - state = TALLOC_P(search->mem_ctx, struct ldap_search_state); + state = talloc(search, struct ldap_search_state); if (state == NULL) { DEBUG(0, ("talloc failed\n")); return False; @@ -4525,10 +4526,10 @@ static bool ldapsam_search_users(struct pdb_methods *methods, state->base = lp_ldap_suffix(); state->acct_flags = acct_flags; - state->base = talloc_strdup(search->mem_ctx, state->base); + state->base = talloc_strdup(search, state->base); state->scope = LDAP_SCOPE_SUBTREE; - state->filter = get_ldap_filter(search->mem_ctx, "*"); - state->attrs = talloc_attrs(search->mem_ctx, "uid", "sambaSid", + state->filter = get_ldap_filter(search, "*"); + state->attrs = talloc_attrs(search, "uid", "sambaSid", "displayName", "description", "sambaAcctFlags", NULL); state->attrsonly = 0; @@ -4682,7 +4683,7 @@ static bool ldapsam_search_grouptype(struct pdb_methods *methods, struct ldap_search_state *state; fstring tmp; - state = TALLOC_P(search->mem_ctx, struct ldap_search_state); + state = talloc(search, struct ldap_search_state); if (state == NULL) { DEBUG(0, ("talloc failed\n")); return False; @@ -4690,15 +4691,14 @@ static bool ldapsam_search_grouptype(struct pdb_methods *methods, state->connection = ldap_state->smbldap_state; - state->base = talloc_strdup(search->mem_ctx, lp_ldap_group_suffix()); + state->base = talloc_strdup(search, lp_ldap_group_suffix()); state->connection = ldap_state->smbldap_state; state->scope = LDAP_SCOPE_SUBTREE; - state->filter = talloc_asprintf(search->mem_ctx, - "(&(objectclass=%s)" + state->filter = talloc_asprintf(search, "(&(objectclass=%s)" "(sambaGroupType=%d)(sambaSID=%s*))", LDAP_OBJ_GROUPMAP, type, sid_to_fstring(tmp, sid)); - state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid", + state->attrs = talloc_attrs(search, "cn", "sambaSid", "displayName", "description", "sambaGroupType", NULL); state->attrsonly = 0; diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index b72e0f2cba..d663c7f0b2 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -1566,11 +1566,11 @@ static bool smbpasswd_search_next_entry(struct pdb_search *search, entry->acct_flags = state->entries[state->current].acct_flags; entry->account_name = talloc_strdup( - search->mem_ctx, state->entries[state->current].account_name); + search, state->entries[state->current].account_name); entry->fullname = talloc_strdup( - search->mem_ctx, state->entries[state->current].fullname); + search, state->entries[state->current].fullname); entry->description = talloc_strdup( - search->mem_ctx, state->entries[state->current].description); + search, state->entries[state->current].description); if ((entry->account_name == NULL) || (entry->fullname == NULL) || (entry->description == NULL)) { @@ -1593,8 +1593,7 @@ static bool smbpasswd_search_users(struct pdb_methods *methods, struct smb_passwd *pwd; FILE *fp; - search_state = TALLOC_ZERO_P(search->mem_ctx, - struct smbpasswd_search_state); + search_state = talloc_zero(search, struct smbpasswd_search_state); if (search_state == NULL) { DEBUG(0, ("talloc failed\n")); return false; diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index 143a2e2390..73fcfee4b3 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -102,6 +102,7 @@ static int tdbsam_convert_one(struct db_record *rec, void *priv) ret = init_samu_from_buffer(user, SAMU_BUFFER_V3, (uint8 *)rec->value.dptr, rec->value.dsize); + break; case 4: ret = init_samu_from_buffer(user, SAMU_BUFFER_V4, (uint8 *)rec->value.dptr, @@ -141,6 +142,149 @@ static int tdbsam_convert_one(struct db_record *rec, void *priv) return 0; } +/********************************************************************** + Struct and function to backup an old record. + *********************************************************************/ + +struct tdbsam_backup_state { + struct db_context *new_db; + bool success; +}; + +static int backup_copy_fn(struct db_record *orig_rec, void *state) +{ + struct tdbsam_backup_state *bs = (struct tdbsam_backup_state *)state; + struct db_record *new_rec; + NTSTATUS status; + + new_rec = bs->new_db->fetch_locked(bs->new_db, talloc_tos(), orig_rec->key); + if (new_rec == NULL) { + bs->success = false; + return 1; + } + + status = new_rec->store(new_rec, orig_rec->value, TDB_INSERT); + + TALLOC_FREE(new_rec); + + if (!NT_STATUS_IS_OK(status)) { + bs->success = false; + return 1; + } + return 0; +} + +/********************************************************************** + Make a backup of an old passdb and replace the new one with it. We + have to do this as between 3.0.x and 3.2.x the hash function changed + by mistake (used unsigned char * instead of char *). This means the + previous simple update code will fail due to not being able to find + existing records to replace in the tdbsam_convert_one() function. JRA. + *********************************************************************/ + +static bool tdbsam_convert_backup(const char *dbname, struct db_context **pp_db) +{ + TALLOC_CTX *frame = talloc_stackframe(); + const char *tmp_fname = NULL; + struct db_context *tmp_db = NULL; + struct db_context *orig_db = *pp_db; + struct tdbsam_backup_state bs; + int ret; + + tmp_fname = talloc_asprintf(frame, "%s.tmp", dbname); + if (!tmp_fname) { + TALLOC_FREE(frame); + return false; + } + + unlink(tmp_fname); + + /* Remember to open this on the NULL context. We need + * it to stay around after we return from here. */ + + tmp_db = db_open(NULL, tmp_fname, 0, + TDB_DEFAULT, O_CREAT|O_RDWR, 0600); + if (tmp_db == NULL) { + DEBUG(0, ("tdbsam_convert_backup: Failed to create backup TDB passwd " + "[%s]\n", tmp_fname)); + TALLOC_FREE(frame); + return false; + } + + if (orig_db->transaction_start(orig_db) != 0) { + DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (1)\n")); + unlink(tmp_fname); + TALLOC_FREE(tmp_db); + TALLOC_FREE(frame); + return false; + } + if (tmp_db->transaction_start(tmp_db) != 0) { + DEBUG(0, ("tdbsam_convert_backup: Could not start transaction (2)\n")); + orig_db->transaction_cancel(orig_db); + unlink(tmp_fname); + TALLOC_FREE(tmp_db); + TALLOC_FREE(frame); + return false; + } + + bs.new_db = tmp_db; + bs.success = true; + + ret = orig_db->traverse(orig_db, backup_copy_fn, (void *)&bs); + if (ret < 0) { + DEBUG(0, ("tdbsam_convert_backup: traverse failed\n")); + goto cancel; + } + + if (!bs.success) { + DEBUG(0, ("tdbsam_convert_backup: Rewriting records failed\n")); + goto cancel; + } + + if (orig_db->transaction_commit(orig_db) != 0) { + smb_panic("tdbsam_convert_backup: orig commit failed\n"); + } + if (tmp_db->transaction_commit(tmp_db) != 0) { + smb_panic("tdbsam_convert_backup: orig commit failed\n"); + } + + /* This is safe from other users as we know we're + * under a mutex here. */ + + if (rename(tmp_fname, dbname) == -1) { + DEBUG(0, ("tdbsam_convert_backup: rename of %s to %s failed %s\n", + tmp_fname, + dbname, + strerror(errno))); + smb_panic("tdbsam_convert_backup: replace passdb failed\n"); + } + + TALLOC_FREE(frame); + TALLOC_FREE(orig_db); + + DEBUG(1, ("tdbsam_convert_backup: updated %s file.\n", + dbname )); + + /* Replace the global db pointer. */ + *pp_db = tmp_db; + return true; + + cancel: + + if (orig_db->transaction_cancel(orig_db) != 0) { + smb_panic("tdbsam_convert: transaction_cancel failed"); + } + + if (tmp_db->transaction_cancel(tmp_db) != 0) { + smb_panic("tdbsam_convert: transaction_cancel failed"); + } + + unlink(tmp_fname); + TALLOC_FREE(tmp_db); + TALLOC_FREE(frame); + return false; +} + static bool tdbsam_upgrade_next_rid(struct db_context *db) { TDB_CONTEXT *tdb; @@ -172,43 +316,50 @@ static bool tdbsam_upgrade_next_rid(struct db_context *db) return true; } -static bool tdbsam_convert(struct db_context *db, int32 from) +static bool tdbsam_convert(struct db_context **pp_db, const char *name, int32 from) { struct tdbsam_convert_state state; + struct db_context *db = NULL; int ret; + if (!tdbsam_convert_backup(name, pp_db)) { + DEBUG(0, ("tdbsam_convert: Could not backup %s\n", name)); + return false; + } + + db = *pp_db; state.from = from; state.success = true; if (db->transaction_start(db) != 0) { - DEBUG(0, ("Could not start transaction\n")); + DEBUG(0, ("tdbsam_convert: Could not start transaction\n")); return false; } if (!tdbsam_upgrade_next_rid(db)) { - DEBUG(0, ("tdbsam_upgrade_next_rid failed\n")); + DEBUG(0, ("tdbsam_convert: tdbsam_upgrade_next_rid failed\n")); goto cancel; } ret = db->traverse(db, tdbsam_convert_one, &state); if (ret < 0) { - DEBUG(0, ("traverse failed\n")); + DEBUG(0, ("tdbsam_convert: traverse failed\n")); goto cancel; } if (!state.success) { - DEBUG(0, ("Converting records failed\n")); + DEBUG(0, ("tdbsam_convert: Converting records failed\n")); goto cancel; } if (dbwrap_store_int32(db, TDBSAM_VERSION_STRING, TDBSAM_VERSION) != 0) { - DEBUG(0, ("Could not store tdbsam version\n")); + DEBUG(0, ("tdbsam_convert: Could not store tdbsam version\n")); goto cancel; } if (db->transaction_commit(db) != 0) { - DEBUG(0, ("Could not commit transaction\n")); + DEBUG(0, ("tdbsam_convert: Could not commit transaction\n")); return false; } @@ -216,7 +367,7 @@ static bool tdbsam_convert(struct db_context *db, int32 from) cancel: if (db->transaction_cancel(db) != 0) { - smb_panic("transaction_cancel failed"); + smb_panic("tdbsam_convert: transaction_cancel failed"); } return false; @@ -261,17 +412,54 @@ static bool tdbsam_open( const char *name ) } if ( version < TDBSAM_VERSION ) { - DEBUG(1, ("tdbsam_open: Converting version %d database to " - "version %d.\n", version, TDBSAM_VERSION)); + /* + * Ok - we think we're going to have to convert. + * Due to the backup process we now must do to + * upgrade we have to get a mutex and re-check + * the version. Someone else may have upgraded + * whilst we were checking. + */ + + struct named_mutex *mtx = grab_named_mutex(NULL, + "tdbsam_upgrade_mutex", + 600); - if ( !tdbsam_convert(db_sam, version) ) { - DEBUG(0, ("tdbsam_open: Error when trying to convert " - "tdbsam [%s]\n",name)); + if (!mtx) { + DEBUG(0, ("tdbsam_open: failed to grab mutex.\n")); TALLOC_FREE(db_sam); return false; } - DEBUG(3, ("TDBSAM converted successfully.\n")); + /* Re-check the version */ + version = dbwrap_fetch_int32(db_sam, TDBSAM_VERSION_STRING); + if (version == -1) { + version = 0; /* Version not found, assume version 0 */ + } + + /* Compare the version */ + if (version > TDBSAM_VERSION) { + /* Version more recent than the latest known */ + DEBUG(0, ("tdbsam_open: unknown version => %d\n", version)); + TALLOC_FREE(db_sam); + TALLOC_FREE(mtx); + return false; + } + + if ( version < TDBSAM_VERSION ) { + DEBUG(1, ("tdbsam_open: Converting version %d database to " + "version %d.\n", version, TDBSAM_VERSION)); + + if ( !tdbsam_convert(&db_sam, name, version) ) { + DEBUG(0, ("tdbsam_open: Error when trying to convert " + "tdbsam [%s]\n",name)); + TALLOC_FREE(db_sam); + TALLOC_FREE(mtx); + return false; + } + + DEBUG(3, ("TDBSAM converted successfully.\n")); + } + TALLOC_FREE(mtx); } DEBUG(4,("tdbsam_open: successfully opened %s\n", name )); @@ -882,12 +1070,9 @@ static bool tdbsam_search_next_entry(struct pdb_search *search, entry->acct_flags = pdb_get_acct_ctrl(user); entry->rid = rid; - entry->account_name = talloc_strdup( - search->mem_ctx, pdb_get_username(user)); - entry->fullname = talloc_strdup( - search->mem_ctx, pdb_get_fullname(user)); - entry->description = talloc_strdup( - search->mem_ctx, pdb_get_acct_desc(user)); + entry->account_name = talloc_strdup(search, pdb_get_username(user)); + entry->fullname = talloc_strdup(search, pdb_get_fullname(user)); + entry->description = talloc_strdup(search, pdb_get_acct_desc(user)); TALLOC_FREE(user); @@ -912,7 +1097,7 @@ static bool tdbsam_search_users(struct pdb_methods *methods, return false; } - state = TALLOC_ZERO_P(search->mem_ctx, struct tdbsam_search_state); + state = talloc_zero(search, struct tdbsam_search_state); if (state == NULL) { DEBUG(0, ("talloc failed\n")); return false; diff --git a/source3/passdb/pdb_wbc_sam.c b/source3/passdb/pdb_wbc_sam.c index d2c7fda293..e8116d0995 100644 --- a/source3/passdb/pdb_wbc_sam.c +++ b/source3/passdb/pdb_wbc_sam.c @@ -150,7 +150,6 @@ static NTSTATUS pdb_wbc_sam_lookup_rids(struct pdb_methods *methods, NTSTATUS result = NT_STATUS_OK; char *domain = NULL; char **account_names = NULL; - char name[256]; enum lsa_SidType *attr_list = NULL; int i; @@ -168,16 +167,19 @@ static NTSTATUS pdb_wbc_sam_lookup_rids(struct pdb_methods *methods, if (attrs[i] == SID_NAME_UNKNOWN) { names[i] = NULL; } else { - snprintf(name, sizeof(name), "%s%c%s", domain, - *lp_winbind_separator(), account_names[i]); - names[i] = talloc_strdup(names, name); + names[i] = talloc_strdup(names, account_names[i]); + if (names[i] == NULL) { + result = NT_STATUS_NO_MEMORY; + goto done; + } + } } done: TALLOC_FREE(account_names); TALLOC_FREE(domain); - TALLOC_FREE(attrs); + TALLOC_FREE(attr_list); return result; } |