diff options
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 244 |
1 files changed, 25 insertions, 219 deletions
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 017a2ebfeb..122432d95b 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -2749,16 +2749,8 @@ BOOL get_global_winbindd_state_offline(void) Validate functions for all possible cache tdb keys. ***********************************************************************/ -struct validation_status { - BOOL tdb_error; - BOOL bad_freelist; - BOOL bad_entry; - BOOL unknown_key; - BOOL success; -}; - static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA data, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry; @@ -2786,7 +2778,7 @@ static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA dat } static int validate_seqnum(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { if (dbuf.dsize != 8) { DEBUG(0,("validate_seqnum: Corrupt cache for key %s (len %u != 8) ?\n", @@ -2798,7 +2790,7 @@ static int validate_seqnum(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbu } static int validate_ns(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); if (!centry) { @@ -2821,7 +2813,7 @@ static int validate_ns(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_sn(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); if (!centry) { @@ -2844,7 +2836,7 @@ static int validate_sn(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_u(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); DOM_SID sid; @@ -2871,7 +2863,7 @@ static int validate_u(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_loc_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); @@ -2893,7 +2885,7 @@ static int validate_loc_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA db } static int validate_pwd_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); @@ -2917,7 +2909,7 @@ static int validate_pwd_pol(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA db } static int validate_cred(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); @@ -2943,7 +2935,7 @@ static int validate_cred(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_ul(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); int32 num_entries, i; @@ -2974,7 +2966,7 @@ static int validate_ul(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_gl(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); int32 num_entries, i; @@ -3001,7 +2993,7 @@ static int validate_gl(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_ug(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); int32 num_groups, i; @@ -3027,7 +3019,7 @@ static int validate_ug(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_ua(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); int32 num_aliases, i; @@ -3052,7 +3044,7 @@ static int validate_ua(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_gm(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); int32 num_names, i; @@ -3080,7 +3072,7 @@ static int validate_gm(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_dr(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { /* Can't say anything about this other than must be nonzero. */ if (dbuf.dsize == 0) { @@ -3096,7 +3088,7 @@ static int validate_dr(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_de(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { /* Can't say anything about this other than must be nonzero. */ if (dbuf.dsize == 0) { @@ -3112,7 +3104,7 @@ static int validate_de(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, } static int validate_trustdoms(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { struct cache_entry *centry = create_centry_validate(keystr, dbuf, state); int32 num_domains, i; @@ -3141,7 +3133,7 @@ static int validate_trustdoms(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA static int validate_trustdomcache(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { if (dbuf.dsize == 0) { DEBUG(0, ("validate_trustdomcache: Corrupt cache for " @@ -3157,7 +3149,7 @@ static int validate_trustdomcache(TALLOC_CTX *mem_ctx, const char *keystr, } static int validate_offline(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { if (dbuf.dsize != 4) { DEBUG(0,("validate_offline: Corrupt cache for key %s (len %u != 4) ?\n", @@ -3171,7 +3163,7 @@ static int validate_offline(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA db } static int validate_cache_version(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, - struct validation_status *state) + struct tdb_validation_status *state) { if (dbuf.dsize != 4) { DEBUG(0, ("validate_cache_version: Corrupt cache for " @@ -3193,7 +3185,7 @@ static int validate_cache_version(TALLOC_CTX *mem_ctx, const char *keystr, TDB_D struct key_val_struct { const char *keyname; - int (*validate_data_fn)(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, struct validation_status* state); + int (*validate_data_fn)(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf, struct tdb_validation_status* state); } key_val[] = { {"SEQNUM/", validate_seqnum}, {"NS/", validate_ns}, @@ -3224,7 +3216,7 @@ struct key_val_struct { static int cache_traverse_validate_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state) { int i; - struct validation_status *v_state = (struct validation_status *)state; + struct tdb_validation_status *v_state = (struct tdb_validation_status *)state; /* Paranoia check. */ if (kbuf.dsize > 1024) { @@ -3285,201 +3277,15 @@ static void validate_panic(const char *const why) function) will restart us as we don't know if we crashed or not. ***********************************************************************/ -/* - * internal validation function, executed by the child. - */ -static int winbindd_validate_cache_child(const char *cache_path, int pfd) -{ - int ret = -1; - int tfd = -1; - int num_entries = 0; - TDB_CONTEXT *tdb = NULL; - struct validation_status v_status; - - v_status.tdb_error = False; - v_status.bad_freelist = False; - v_status.bad_entry = False; - v_status.unknown_key = False; - v_status.success = True; - - tdb = tdb_open_log(cache_path, - WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, - lp_winbind_offline_logon() - ? TDB_DEFAULT - : (TDB_DEFAULT | TDB_CLEAR_IF_FIRST), - O_RDWR|O_CREAT, 0600); - if (!tdb) { - v_status.tdb_error = True; - v_status.success = False; - goto out; - } - - tfd = tdb_fd(tdb); - - /* Check the cache freelist is good. */ - if (tdb_validate_freelist(tdb, &num_entries) == -1) { - DEBUG(0,("winbindd_validate_cache_child: bad freelist in cache %s\n", - cache_path)); - v_status.bad_freelist = True; - v_status.success = False; - goto out; - } - - DEBUG(10,("winbindd_validate_cache_child: cache %s freelist has %d entries\n", - cache_path, num_entries)); - - /* Now traverse the cache to validate it. */ - num_entries = tdb_traverse(tdb, cache_traverse_validate_fn, (void *)&v_status); - if (num_entries == -1 || !(v_status.success)) { - DEBUG(0,("winbindd_validate_cache_child: cache %s traverse failed\n", - cache_path)); - if (!(v_status.success)) { - if (v_status.bad_entry) { - DEBUGADD(0, (" -> bad entry found\n")); - } - if (v_status.unknown_key) { - DEBUGADD(0, (" -> unknown key encountered\n")); - } - } - goto out; - } - - DEBUG(10,("winbindd_validate_cache_child: cache %s is good " - "with %d entries\n", cache_path, num_entries)); - ret = 0; /* Cache is good. */ - -out: - if (tdb) { - if (ret == 0) { - tdb_close(tdb); - } - else if (tfd != -1) { - close(tfd); - } - } - - DEBUG(10, ("winbindd_validate_cache_child: writing status to pipe\n")); - write (pfd, (const char *)&v_status, sizeof(v_status)); - close(pfd); - - return ret; -} - int winbindd_validate_cache(void) { - pid_t child_pid = -1; - int child_status = 0; - int wait_pid = 0; - int ret = -1; - int pipe_fds[2]; - struct validation_status v_status; - int bytes_read = 0; - const char *cache_path = lock_path("winbindd_cache.tdb"); - + int ret; + DEBUG(10, ("winbindd_validate_cache: replacing panic function\n")); smb_panic_fn = validate_panic; - /* fork and let the child do the validation. - * benefit: no need to twist signal handlers and panic functions. - * just let the child panic. we catch the signal. - * communicate the extended status struct over a pipe. */ - - if (pipe(pipe_fds) != 0) { - DEBUG(0, ("winbindd_validate_cache: unable to create pipe, " - "error %s", strerror(errno))); - smb_panic("winbind_validate_cache: unable to create pipe."); - } - - DEBUG(10, ("winbindd_validate_cache: forking to let child do validation.\n")); - child_pid = sys_fork(); - if (child_pid == 0) { - DEBUG(10, ("winbindd_validate_cache (validation child): created\n")); - close(pipe_fds[0]); /* close reading fd */ - DEBUG(10, ("winbindd_validate_cache (validation child): " - "calling winbindd_validate_cache_child\n")); - exit(winbindd_validate_cache_child(cache_path, pipe_fds[1])); - } - else if (child_pid < 0) { - smb_panic("winbindd_validate_cache: fork for validation failed."); - } - - /* parent */ - - DEBUG(10, ("winbindd_validate_cache: fork succeeded, child PID = %d\n", - child_pid)); - close(pipe_fds[1]); /* close writing fd */ - - v_status.success = True; - v_status.bad_entry = False; - v_status.unknown_key = False; - - DEBUG(10, ("winbindd_validate_cache: reading from pipe.\n")); - bytes_read = read(pipe_fds[0], (void *)&v_status, sizeof(v_status)); - close(pipe_fds[0]); - - if (bytes_read != sizeof(v_status)) { - DEBUG(10, ("winbindd_validate_cache: read %d bytes from pipe " - "but expected %d", bytes_read, (int)sizeof(v_status))); - DEBUGADD(10, (" -> assuming child crashed\n")); - v_status.success = False; - } - else { - DEBUG(10, ("winbindd_validate_cache: read status from child\n")); - DEBUGADD(10, (" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); - DEBUGADD(10, (" * bad freelist: %s\n", v_status.bad_freelist ? "yes" : "no")); - DEBUGADD(10, (" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); - DEBUGADD(10, (" * unknown key: %s\n", v_status.unknown_key ? "yes" : "no")); - DEBUGADD(10, (" => overall success: %s\n", v_status.success ? "yes" : "no")); - } - - if (!v_status.success) { - DEBUG(10, ("winbindd_validate_cache: validation not successful.\n")); - DEBUGADD(10, ("removing tdb %s.\n", cache_path)); - unlink(cache_path); - } - - DEBUG(10, ("winbindd_validate_cache: waiting for child to finish...\n")); - while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { - if (errno == EINTR) { - DEBUG(10, ("winbindd_validate_cache: got signal during " - "waitpid, retrying\n")); - errno = 0; - continue; - } - DEBUG(0, ("winbindd_validate_cache: waitpid failed with " - "errno %s\n", strerror(errno))); - smb_panic("winbindd_validate_cache: waitpid failed."); - } - if (wait_pid != child_pid) { - DEBUG(0, ("winbindd_validate_cache: waitpid returned pid %d, " - "but %d was expexted\n", wait_pid, child_pid)); - smb_panic("winbindd_validate_cache: waitpid returned " - "unexpected PID."); - } - - - DEBUG(10, ("winbindd_validate_cache: validating child returned.\n")); - if (WIFEXITED(child_status)) { - DEBUG(10, ("winbindd_validate_cache: child exited, code %d.\n", - WEXITSTATUS(child_status))); - ret = WEXITSTATUS(child_status); - } - if (WIFSIGNALED(child_status)) { - DEBUG(10, ("winbindd_validate_cache: child terminated " - "by signal %d\n", WTERMSIG(child_status))); -#ifdef WCOREDUMP - if (WCOREDUMP(child_status)) { - DEBUGADD(10, ("core dumped\n")); - } -#endif - ret = WTERMSIG(child_status); - } - if (WIFSTOPPED(child_status)) { - DEBUG(10, ("winbindd_validate_cache: child was stopped " - "by signal %d\n", - WSTOPSIG(child_status))); - ret = WSTOPSIG(child_status); - } + ret = tdb_validate(lock_path("winbindd_cache.tdb"), + cache_traverse_validate_fn); DEBUG(10, ("winbindd_validate_cache: restoring panic function\n")); smb_panic_fn = smb_panic; |