summaryrefslogtreecommitdiff
path: root/source3/passdb/pdb_tdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/passdb/pdb_tdb.c')
-rw-r--r--source3/passdb/pdb_tdb.c156
1 files changed, 103 insertions, 53 deletions
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index 1d8fb9b7ec..d9d946ffc8 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -46,12 +46,18 @@ static int tdbsam_debug_level = DBGC_ALL;
struct tdbsam_privates {
TDB_CONTEXT *passwd_tdb;
- TDB_DATA key;
/* retrive-once info */
const char *tdbsam_location;
};
+struct pwent_list {
+ struct pwent_list *prev, *next;
+ TDB_DATA key;
+};
+static struct pwent_list *tdbsam_pwent_list;
+
+
/**
* Convert old TDBSAM to the latest version.
* @param pdb_tdb A pointer to the opened TDBSAM file which must be converted.
@@ -222,33 +228,75 @@ static TDB_CONTEXT * tdbsam_tdbopen (const char *name, int open_flags)
return pdb_tdb;
}
+/*****************************************************************************
+ Utility functions to open the tdb sam database
+ ****************************************************************************/
+
+static void tdbsam_tdbclose ( struct tdbsam_privates *state )
+{
+ if ( !state )
+ return;
+
+ if ( state->passwd_tdb ) {
+ tdb_close( state->passwd_tdb );
+ state->passwd_tdb = NULL;
+ }
+
+ return;
+
+}
+
+/****************************************************************************
+ creates a list of user keys
+****************************************************************************/
+
+static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
+{
+ const char *prefix = USERPREFIX;
+ int prefixlen = strlen (prefix);
+ struct pwent_list *ptr;
+
+ if ( strncmp(key.dptr, prefix, prefixlen) == 0 ) {
+ if ( !(ptr=(struct pwent_list*)malloc(sizeof(struct pwent_list))) ) {
+ DEBUG(0,("tdbsam_traverse_setpwent: Failed to malloc new entry for list\n"));
+
+ /* just return 0 and let the traversal continue */
+ return 0;
+ }
+ ZERO_STRUCTP(ptr);
+
+ /* save a copy of the key */
+
+ ptr->key.dptr = memdup( key.dptr, key.dsize );
+ ptr->key.dsize = key.dsize;
+
+ DLIST_ADD( tdbsam_pwent_list, ptr );
+
+ }
+
+
+ return 0;
+}
+
/***************************************************************
Open the TDB passwd database for SAM account enumeration.
+ Save a list of user keys for iteration.
****************************************************************/
static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
{
+ uint32 flags = update ? (O_RDWR|O_CREAT) : O_RDONLY;
+
struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
- /* Open tdb passwd */
- if (!(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, update?(O_RDWR|O_CREAT):O_RDONLY)))
- {
- DEBUG(0, ("Unable to open/create TDB passwd\n"));
+ if ( !(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, flags )) )
return NT_STATUS_UNSUCCESSFUL;
- }
-
- tdb_state->key = tdb_firstkey(tdb_state->passwd_tdb);
+ tdb_traverse( tdb_state->passwd_tdb, tdbsam_traverse_setpwent, NULL );
+
return NT_STATUS_OK;
}
-static void close_tdb(struct tdbsam_privates *tdb_state)
-{
- if (tdb_state->passwd_tdb) {
- tdb_close(tdb_state->passwd_tdb);
- tdb_state->passwd_tdb = NULL;
- }
-}
/***************************************************************
End enumeration of the TDB passwd list.
@@ -257,8 +305,18 @@ static void close_tdb(struct tdbsam_privates *tdb_state)
static void tdbsam_endsampwent(struct pdb_methods *my_methods)
{
struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
- SAFE_FREE(tdb_state->key.dptr);
- close_tdb(tdb_state);
+ struct pwent_list *ptr, *ptr_next;
+
+ tdbsam_tdbclose( tdb_state );
+
+ /* clear out any remaining entries in the list */
+
+ for ( ptr=tdbsam_pwent_list; ptr; ptr = ptr_next ) {
+ ptr_next = ptr->next;
+ DLIST_REMOVE( tdbsam_pwent_list, ptr );
+ SAFE_FREE( ptr->key.dptr);
+ SAFE_FREE( ptr );
+ }
DEBUG(7, ("endtdbpwent: closed sam database.\n"));
}
@@ -269,55 +327,48 @@ static void tdbsam_endsampwent(struct pdb_methods *my_methods)
static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
- TDB_DATA data, old_key;
- const char *prefix = USERPREFIX;
- int prefixlen = strlen (prefix);
-
+ TDB_DATA data;
+ struct pwent_list *pkey;
- if (user==NULL) {
- DEBUG(0,("pdb_get_sampwent: SAM_ACCOUNT is NULL.\n"));
+ if ( !user ) {
+ DEBUG(0,("tdbsam_getsampwent: SAM_ACCOUNT is NULL.\n"));
return nt_status;
}
- /* skip all non-USER entries (eg. RIDs) */
- while ((tdb_state->key.dsize != 0) && (strncmp(tdb_state->key.dptr, prefix, prefixlen))) {
-
- old_key = tdb_state->key;
-
- /* increment to next in line */
- tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
-
- SAFE_FREE(old_key.dptr);
- }
-
- /* do we have an valid iteration pointer? */
- if(tdb_state->passwd_tdb == NULL) {
- DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n"));
+ if ( !tdbsam_pwent_list ) {
+ DEBUG(4,("tdbsam_getsampwent: end of list\n"));
+ tdbsam_tdbclose( tdb_state );
return nt_status;
}
+
+ if ( !tdb_state->passwd_tdb ) {
+ if ( !(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY)) )
+ return nt_status;
+ }
+
+ /* pull the next entry */
+
+ pkey = tdbsam_pwent_list;
+ DLIST_REMOVE( tdbsam_pwent_list, pkey );
+
+ data = tdb_fetch(tdb_state->passwd_tdb, pkey->key);
- data = tdb_fetch(tdb_state->passwd_tdb, tdb_state->key);
+ SAFE_FREE( pkey->key.dptr);
+ SAFE_FREE( pkey);
+
if (!data.dptr) {
- DEBUG(5,("pdb_getsampwent: database entry not found.\n"));
+ DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
return nt_status;
}
- /* unpack the buffer */
if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
- SAFE_FREE(data.dptr);
- return nt_status;
}
- SAFE_FREE(data.dptr);
- old_key = tdb_state->key;
+ SAFE_FREE( data.dptr );
- /* increment to next in line */
- tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
-
- SAFE_FREE(old_key.dptr);
return NT_STATUS_OK;
}
@@ -335,12 +386,11 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT
fstring keystr;
fstring name;
- if (user==NULL) {
+ if ( !user ) {
DEBUG(0,("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
return nt_status;
}
-
/* Data is stored in all lower-case */
fstrcpy(name, sname);
strlower_m(name);
@@ -358,7 +408,7 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT
* TDB file doesn't exist, so try to create new one. This is useful to avoid
* confusing error msg when adding user account first time
*/
- if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_CREAT, 0600))) {
+ if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_CREAT ))) {
DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) did not exist. File successfully created.\n",
tdb_state->tdbsam_location));
} else {
@@ -637,7 +687,7 @@ static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCO
static void free_private_data(void **vp)
{
struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
- close_tdb(*tdb_state);
+ tdbsam_tdbclose(*tdb_state);
*tdb_state = NULL;
/* No need to free any further, as it is talloc()ed */