diff options
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/winbindd.c | 108 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 7 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_dual.c | 3 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_group.c | 37 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_idmap.c | 194 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_idmap_tdb.c | 459 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_sid.c | 13 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_user.c | 19 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 9 |
9 files changed, 755 insertions, 94 deletions
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index da2540f5d9..fb6f67625c 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -128,6 +128,7 @@ static void winbindd_status(void) static void print_winbindd_status(void) { winbindd_status(); + winbindd_idmap_status(); winbindd_cm_status(); } @@ -145,7 +146,7 @@ static void terminate(void) { pstring path; - idmap_close(); + winbindd_idmap_close(); /* Remove socket file */ snprintf(path, sizeof(path), "%s/%s", @@ -729,62 +730,6 @@ static void process_loop(void) } } - -/* - these are split out from the main winbindd for use by the background daemon - */ -BOOL winbind_setup_common(void) -{ - load_interfaces(); - - if (!secrets_init()) { - - DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n")); - return False; - } - - namecache_enable(); /* Enable netbios namecache */ - - /* Check winbindd parameters are valid */ - - ZERO_STRUCT(server_state); - - if (!winbindd_param_init()) - return False; - - /* Winbind daemon initialisation */ - - if (!idmap_init()) - return False; - - if (!idmap_init_wellknown_sids()) - return False; - - /* Unblock all signals we are interested in as they may have been - blocked by the parent process. */ - - BlockSignals(False, SIGINT); - BlockSignals(False, SIGQUIT); - BlockSignals(False, SIGTERM); - BlockSignals(False, SIGUSR1); - BlockSignals(False, SIGUSR2); - BlockSignals(False, SIGHUP); - - /* Setup signal handlers */ - - CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ - CatchSignal(SIGQUIT, termination_handler); - CatchSignal(SIGTERM, termination_handler); - - CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ - - CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ - CatchSignal(SIGHUP, sighup_handler); - - return True; -} - - /* Main function */ struct winbindd_state server_state; /* Server state information */ @@ -868,6 +813,51 @@ int main(int argc, char **argv) if (!init_names()) exit(1); + load_interfaces(); + + if (!secrets_init()) { + + DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n")); + return False; + } + + /* Enable netbios namecache */ + + namecache_enable(); + + /* Check winbindd parameters are valid */ + + ZERO_STRUCT(server_state); + + if (!winbindd_param_init()) + return 1; + + /* Winbind daemon initialisation */ + + if (!winbindd_idmap_init()) + return 1; + + /* Unblock all signals we are interested in as they may have been + blocked by the parent process. */ + + BlockSignals(False, SIGINT); + BlockSignals(False, SIGQUIT); + BlockSignals(False, SIGTERM); + BlockSignals(False, SIGUSR1); + BlockSignals(False, SIGUSR2); + BlockSignals(False, SIGHUP); + + /* Setup signal handlers */ + + CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ + CatchSignal(SIGQUIT, termination_handler); + CatchSignal(SIGTERM, termination_handler); + + CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ + + CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ + CatchSignal(SIGHUP, sighup_handler); + if (!interactive) become_daemon(Fork); @@ -882,10 +872,6 @@ int main(int argc, char **argv) setpgid( (pid_t)0, (pid_t)0); #endif - if (!winbind_setup_common()) { - return 1; - } - if (opt_dual_daemon) { do_dual_daemon(); } diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 27e168b6f9..5eabcfca20 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -100,12 +100,7 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) ret = smb_xmalloc(sizeof(*ret)); ZERO_STRUCTP(ret); - - if (!strcmp(domain->name, lp_workgroup()) && (lp_security() == SEC_USER)) { - extern struct winbindd_methods passdb_methods; - ret->backend = &passdb_methods; - - } else switch (lp_security()) { + switch (lp_security()) { #ifdef HAVE_ADS case SEC_ADS: { extern struct winbindd_methods ads_methods; diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index 3597171005..167630b0e1 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/nsswitch/winbindd_dual.c @@ -166,9 +166,6 @@ void do_dual_daemon(void) _exit(0); } - if (!winbind_setup_common()) - _exit(0); - dual_daemon_pipe = -1; opt_dual_daemon = False; diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 14ebb78466..b3ded2a2f4 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -193,8 +193,8 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) enum SID_NAME_USE name_type; fstring name_domain, name_group; char *tmp, *gr_mem; - int gr_mem_len; gid_t gid; + int gr_mem_len; /* Ensure null termination */ state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0'; @@ -210,6 +210,11 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) if (!parse_domain_user(tmp, name_domain, name_group)) return WINBINDD_ERROR; + /* fail if we are a PDC and this is our domain; should be done by passdb */ + + if ( lp_server_role() == ROLE_DOMAIN_PDC && 0==StrCaseCmp( domain->name, lp_workgroup()) ) + return WINBINDD_ERROR; + /* Get info for the domain */ if ((domain = find_domain_from_name(name_domain)) == NULL) { @@ -233,7 +238,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - if (NT_STATUS_IS_ERR(sid_to_gid(&group_sid, &gid))) { + if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) { DEBUG(1, ("error converting unix gid to sid\n")); return WINBINDD_ERROR; } @@ -278,7 +283,8 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) return WINBINDD_ERROR; /* Get rid from gid */ - if (NT_STATUS_IS_ERR(uid_to_sid(&group_sid, state->request.data.gid))) { + + if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &group_sid)) { DEBUG(1, ("could not convert gid %d to rid\n", state->request.data.gid)); return WINBINDD_ERROR; @@ -404,6 +410,9 @@ static BOOL get_sam_group_entries(struct getent_state *ent) if (ent->got_sam_entries) return False; + + if ( lp_server_role() == ROLE_DOMAIN_PDC && 0==StrCaseCmp(lp_workgroup(), ent->domain_name)) + return False; if (!(mem_ctx = talloc_init("get_sam_group_entries(%s)", ent->domain_name))) { @@ -589,7 +598,9 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) sid_copy(&group_sid, &domain->sid); sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); - if (NT_STATUS_IS_ERR(sid_to_gid(&group_sid, &group_gid))) { + if (!winbindd_idmap_get_gid_from_sid( + &group_sid, + &group_gid)) { DEBUG(1, ("could not look up gid for group %s\n", name_list[ent->sam_entry_index].acct_name)); @@ -738,6 +749,11 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) for (domain = domain_list(); domain; domain = domain->next) { struct getent_state groups; + + /* fail if we are a PDC and this is our domain; should be done by passdb */ + + if ( lp_server_role() == ROLE_DOMAIN_PDC && 0==StrCaseCmp( domain->name, lp_workgroup()) ) + continue; ZERO_STRUCT(groups); @@ -830,6 +846,11 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) name_user)) goto done; + /* fail if we are a PDC and this is our domain; should be done by passdb */ + + if ( lp_server_role() == ROLE_DOMAIN_PDC && 0==StrCaseCmp( name_domain, lp_workgroup()) ) + return WINBINDD_ERROR; + /* Get info for the domain */ if ((domain = find_domain_from_name(name_domain)) == NULL) { @@ -866,16 +887,16 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) goto done; for (i = 0; i < num_groups; i++) { - gid_t gid; - - if (NT_STATUS_IS_ERR(sid_to_gid(user_gids[i], &gid))) { + if (!winbindd_idmap_get_gid_from_sid( + user_gids[i], + &gid_list[num_gids])) { fstring sid_string; DEBUG(1, ("unable to convert group sid %s to gid\n", sid_to_string(sid_string, user_gids[i]))); continue; } - gid_list[num_gids] = gid; + num_gids++; } diff --git a/source3/nsswitch/winbindd_idmap.c b/source3/nsswitch/winbindd_idmap.c new file mode 100644 index 0000000000..3b23089200 --- /dev/null +++ b/source3/nsswitch/winbindd_idmap.c @@ -0,0 +1,194 @@ +/* + Unix SMB/CIFS implementation. + Winbind ID Mapping + Copyright (C) Tim Potter 2000 + Copyright (C) Anthony Liguori <aliguor@us.ibm.com> 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "winbindd.h" + +static struct { + const char *name; + /* Function to create a member of the idmap_methods list */ + BOOL (*reg_meth)(struct winbindd_idmap_methods **methods); + struct winbindd_idmap_methods *methods; +} builtin_winbindd_idmap_functions[] = { + { "tdb", winbind_idmap_reg_tdb, NULL }, + { NULL, NULL, NULL } +}; + +/* singleton pattern: uberlazy evaluation */ +static struct winbindd_idmap_methods *impl; + +static struct winbindd_idmap_methods *get_impl(const char *name) +{ + int i = 0; + struct winbindd_idmap_methods *ret = NULL; + + while (builtin_winbindd_idmap_functions[i].name && + strcmp(builtin_winbindd_idmap_functions[i].name, name)) { + i++; + } + + if (builtin_winbindd_idmap_functions[i].name) { + if (!builtin_winbindd_idmap_functions[i].methods) { + builtin_winbindd_idmap_functions[i].reg_meth(&builtin_winbindd_idmap_functions[i].methods); + } + + ret = builtin_winbindd_idmap_functions[i].methods; + } + + return ret; +} + +/* Initialize backend */ +BOOL winbindd_idmap_init(void) +{ + BOOL ret = False; + + DEBUG(3, ("winbindd_idmap_init: using '%s' as backend\n", + lp_winbind_backend())); + + if (!impl) { + impl = get_impl(lp_winbind_backend()); + if (!impl) { + DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", + lp_winbind_backend())); + } + } + + if (impl) { + ret = impl->init(); + } + + DEBUG(3, ("winbind_idmap_init: returning %s\n", ret ? "true" : "false")); + + return ret; +} + +/* Get UID from SID */ +BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid) +{ + BOOL ret = False; + + if (!impl) { + impl = get_impl(lp_winbind_backend()); + if (!impl) { + DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", + lp_winbind_backend())); + } + } + + if (impl) { + ret = impl->get_uid_from_sid(sid, uid); + } + + return ret; +} + +/* Get GID from SID */ +BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid) +{ + BOOL ret = False; + + if (!impl) { + impl = get_impl(lp_winbind_backend()); + if (!impl) { + DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", + lp_winbind_backend())); + } + } + + if (impl) { + ret = impl->get_gid_from_sid(sid, gid); + } + + return ret; +} + +/* Get SID from UID */ +BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid) +{ + BOOL ret = False; + + if (!impl) { + impl = get_impl(lp_winbind_backend()); + if (!impl) { + DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", + lp_winbind_backend())); + } + } + + if (impl) { + ret = impl->get_sid_from_uid(uid, sid); + } + + return ret; +} + +/* Get SID from GID */ +BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid) +{ + BOOL ret = False; + + if (!impl) { + impl = get_impl(lp_winbind_backend()); + } + + if (impl) { + ret = impl->get_sid_from_gid(gid, sid); + } else { + DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", + lp_winbind_backend())); + } + + return ret; +} + +/* Close backend */ +BOOL winbindd_idmap_close(void) +{ + BOOL ret = False; + + if (!impl) { + impl = get_impl(lp_winbind_backend()); + } + + if (impl) { + ret = impl->close(); + } else { + DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", + lp_winbind_backend())); + } + + return ret; +} + +/* Dump backend status */ +void winbindd_idmap_status(void) +{ + if (!impl) { + impl = get_impl(lp_winbind_backend()); + } + + if (impl) { + impl->status(); + } else { + DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", + lp_winbind_backend())); + } +} diff --git a/source3/nsswitch/winbindd_idmap_tdb.c b/source3/nsswitch/winbindd_idmap_tdb.c new file mode 100644 index 0000000000..12d6972bae --- /dev/null +++ b/source3/nsswitch/winbindd_idmap_tdb.c @@ -0,0 +1,459 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon - user related function + + Copyright (C) Tim Potter 2000 + Copyright (C) Anthony Liguori 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +/* High water mark keys */ +#define HWM_GROUP "GROUP HWM" +#define HWM_USER "USER HWM" + +/* idmap version determines auto-conversion */ +#define IDMAP_VERSION 2 + +/* Globals */ +static TDB_CONTEXT *idmap_tdb; + +/* convert one record to the new format */ +static int tdb_convert_fn(TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data, + void *ignored) +{ + struct winbindd_domain *domain; + char *p; + DOM_SID sid; + uint32 rid; + fstring keystr; + fstring dom_name; + TDB_DATA key2; + + p = strchr(key.dptr, '/'); + if (!p) + return 0; + + *p = 0; + fstrcpy(dom_name, key.dptr); + *p++ = '/'; + + domain = find_domain_from_name(dom_name); + if (!domain) { + /* We must delete the old record. */ + DEBUG(0, + ("winbindd: tdb_convert_fn : Unable to find domain %s\n", + dom_name)); + DEBUG(0, + ("winbindd: tdb_convert_fn : deleting record %s\n", + key.dptr)); + tdb_delete(idmap_tdb, key); + return 0; + } + + rid = atoi(p); + + sid_copy(&sid, &domain->sid); + sid_append_rid(&sid, rid); + + sid_to_string(keystr, &sid); + key2.dptr = keystr; + key2.dsize = strlen(keystr) + 1; + + if (tdb_store(idmap_tdb, key2, data, TDB_INSERT) != 0) { + /* not good! */ + DEBUG(0, + ("winbindd: tdb_convert_fn : Unable to update record %s\n", + key2.dptr)); + DEBUG(0, + ("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n")); + return -1; + } + + if (tdb_store(idmap_tdb, data, key2, TDB_REPLACE) != 0) { + /* not good! */ + DEBUG(0, + ("winbindd: tdb_convert_fn : Unable to update record %s\n", + data.dptr)); + DEBUG(0, + ("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n")); + return -1; + } + + tdb_delete(idmap_tdb, key); + + return 0; +} + +/***************************************************************************** + Convert the idmap database from an older version. +*****************************************************************************/ +static BOOL tdb_idmap_convert(void) +{ + int32 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); + BOOL bigendianheader = + (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False; + + if (vers == IDMAP_VERSION) + return True; + + if (((vers == -1) && bigendianheader) + || (IREV(vers) == IDMAP_VERSION)) { + /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */ + /* + * high and low records were created on a + * big endian machine and will need byte-reversing. + */ + + int32 wm; + + wm = tdb_fetch_int32(idmap_tdb, HWM_USER); + + if (wm != -1) { + wm = IREV(wm); + } else + wm = server_state.uid_low; + + if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) { + DEBUG(0, + ("tdb_idmap_convert: Unable to byteswap user hwm in idmap database\n")); + return False; + } + + wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP); + if (wm != -1) { + wm = IREV(wm); + } else + wm = server_state.gid_low; + + if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) { + DEBUG(0, + ("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n")); + return False; + } + } + + /* the old format stored as DOMAIN/rid - now we store the SID direct */ + tdb_traverse(idmap_tdb, tdb_convert_fn, NULL); + + if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == + -1) { + DEBUG(0, + ("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n")); + return False; + } + + return True; +} + +/* Allocate either a user or group id from the pool */ +static BOOL tdb_allocate_id(uid_t * id, BOOL isgroup) +{ + int hwm; + + /* Get current high water mark */ + if ((hwm = tdb_fetch_int32(idmap_tdb, + isgroup ? HWM_GROUP : HWM_USER)) == + -1) { + return False; + } + + /* Return next available uid in list */ + if ((isgroup && (hwm > server_state.gid_high)) || + (!isgroup && (hwm > server_state.uid_high))) { + DEBUG(0, + ("winbind %sid range full!\n", isgroup ? "g" : "u")); + return False; + } + + if (id) { + *id = hwm; + } + + hwm++; + + /* Store new high water mark */ + tdb_store_int32(idmap_tdb, isgroup ? HWM_GROUP : HWM_USER, hwm); + + return True; +} + +/* Get a sid from an id */ +static BOOL tdb_get_sid_from_id(int id, DOM_SID * sid, BOOL isgroup) +{ + TDB_DATA key, data; + fstring keystr; + BOOL result = False; + + slprintf(keystr, sizeof(keystr), "%s %d", isgroup ? "GID" : "UID", + id); + + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + data = tdb_fetch(idmap_tdb, key); + + if (data.dptr) { + result = string_to_sid(sid, data.dptr); + SAFE_FREE(data.dptr); + } + + return result; +} + +/* Get an id from a sid */ +static BOOL tdb_get_id_from_sid(DOM_SID * sid, uid_t * id, BOOL isgroup) +{ + TDB_DATA data, key; + fstring keystr; + BOOL result = False; + + /* Check if sid is present in database */ + sid_to_string(keystr, sid); + + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + data = tdb_fetch(idmap_tdb, key); + + if (data.dptr) { + fstring scanstr; + int the_id; + + /* Parse and return existing uid */ + fstrcpy(scanstr, isgroup ? "GID" : "UID"); + fstrcat(scanstr, " %d"); + + if (sscanf(data.dptr, scanstr, &the_id) == 1) { + /* Store uid */ + if (id) { + *id = the_id; + } + + result = True; + } + + SAFE_FREE(data.dptr); + } else { + + /* Allocate a new id for this sid */ + if (id && tdb_allocate_id(id, isgroup)) { + fstring keystr2; + + /* Store new id */ + slprintf(keystr2, sizeof(keystr2), "%s %d", + isgroup ? "GID" : "UID", *id); + + data.dptr = keystr2; + data.dsize = strlen(keystr2) + 1; + + tdb_store(idmap_tdb, key, data, TDB_REPLACE); + tdb_store(idmap_tdb, data, key, TDB_REPLACE); + + result = True; + } + } + + return result; +} + +/***************************************************************************** + Initialise idmap database. +*****************************************************************************/ +static BOOL tdb_idmap_init(void) +{ + SMB_STRUCT_STAT stbuf; + + /* move to the new database on first startup */ + if (!file_exist(lock_path("idmap.tdb"), &stbuf)) { + if (file_exist(lock_path("winbindd_idmap.tdb"), &stbuf)) { + char *cmd = NULL; + + /* lazy file copy */ + if (asprintf(&cmd, "cp -p %s/winbindd_idmap.tdb %s/idmap.tdb", lp_lockdir(), lp_lockdir()) != -1) { + system(cmd); + free(cmd); + } + if (!file_exist(lock_path("idmap.tdb"), &stbuf)) { + DEBUG(0, ("idmap_init: Unable to make a new database copy\n")); + return False; + } + } + } + + /* Open tdb cache */ + if (!(idmap_tdb = tdb_open_log(lock_path("idmap.tdb"), 0, + TDB_DEFAULT, O_RDWR | O_CREAT, + 0600))) { + DEBUG(0, + ("winbindd_idmap_init: Unable to open idmap database\n")); + return False; + } + + /* possibly convert from an earlier version */ + if (!tdb_idmap_convert()) { + DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n")); + return False; + } + + /* Create high water marks for group and user id */ + if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) { + if (tdb_store_int32 + (idmap_tdb, HWM_USER, server_state.uid_low) == -1) { + DEBUG(0, + ("winbindd_idmap_init: Unable to initialise user hwm in idmap database\n")); + return False; + } + } + + if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) { + if (tdb_store_int32 + (idmap_tdb, HWM_GROUP, server_state.gid_low) == -1) { + DEBUG(0, + ("winbindd_idmap_init: Unable to initialise group hwm in idmap database\n")); + return False; + } + } + + return True; +} + +/* Get a sid from a uid */ +static BOOL tdb_get_sid_from_uid(uid_t uid, DOM_SID * sid) +{ + return tdb_get_sid_from_id((int) uid, sid, False); +} + +/* Get a sid from a gid */ +static BOOL tdb_get_sid_from_gid(gid_t gid, DOM_SID * sid) +{ + return tdb_get_sid_from_id((int) gid, sid, True); +} + +/* Get a uid from a sid */ +static BOOL tdb_get_uid_from_sid(DOM_SID * sid, uid_t * uid) +{ + return tdb_get_id_from_sid(sid, uid, False); +} + +/* Get a gid from a group sid */ +static BOOL tdb_get_gid_from_sid(DOM_SID * sid, gid_t * gid) +{ + return tdb_get_id_from_sid(sid, gid, True); +} + +/* Close the tdb */ +static BOOL tdb_idmap_close(void) +{ + if (idmap_tdb) + return (tdb_close(idmap_tdb) == 0); + return True; +} + + +/* Dump status information to log file. Display different stuff based on + the debug level: + + Debug Level Information Displayed + ================================================================= + 0 Percentage of [ug]id range allocated + 0 High water marks (next allocated ids) +*/ + +#define DUMP_INFO 0 + +static void tdb_idmap_status(void) +{ + int user_hwm, group_hwm; + + DEBUG(0, ("winbindd idmap status:\n")); + + /* Get current high water marks */ + + if ((user_hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { + DEBUG(DUMP_INFO, + ("\tCould not get userid high water mark!\n")); + } + + if ((group_hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) { + DEBUG(DUMP_INFO, + ("\tCould not get groupid high water mark!\n")); + } + + /* Display next ids to allocate */ + + if (user_hwm != -1) { + DEBUG(DUMP_INFO, + ("\tNext userid to allocate is %d\n", user_hwm)); + } + + if (group_hwm != -1) { + DEBUG(DUMP_INFO, + ("\tNext groupid to allocate is %d\n", group_hwm)); + } + + /* Display percentage of id range already allocated. */ + + if (user_hwm != -1) { + int num_users = user_hwm - server_state.uid_low; + int total_users = + server_state.uid_high - server_state.uid_low; + + DEBUG(DUMP_INFO, + ("\tUser id range is %d%% full (%d of %d)\n", + num_users * 100 / total_users, num_users, + total_users)); + } + + if (group_hwm != -1) { + int num_groups = group_hwm - server_state.gid_low; + int total_groups = + server_state.gid_high - server_state.gid_low; + + DEBUG(DUMP_INFO, + ("\tGroup id range is %d%% full (%d of %d)\n", + num_groups * 100 / total_groups, num_groups, + total_groups)); + } + + /* Display complete mapping of users and groups to rids */ +} + +struct winbindd_idmap_methods tdb_idmap_methods = { + tdb_idmap_init, + + tdb_get_sid_from_uid, + tdb_get_sid_from_gid, + + tdb_get_uid_from_sid, + tdb_get_gid_from_sid, + + tdb_idmap_close, + + tdb_idmap_status +}; + +BOOL winbind_idmap_reg_tdb(struct winbindd_idmap_methods **meth) +{ + *meth = &tdb_idmap_methods; + + return True; +} diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c index f5dd904dc1..41bda7e5bc 100644 --- a/source3/nsswitch/winbindd_sid.c +++ b/source3/nsswitch/winbindd_sid.c @@ -98,6 +98,11 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) name_domain = state->request.data.name.dom_name; name_user = state->request.data.name.name; + /* fail if we are a PDC and this is our domain; should be done by passdb */ + + if ( lp_server_role() == ROLE_DOMAIN_PDC && 0==StrCaseCmp( name_domain, lp_workgroup()) ) + return WINBINDD_ERROR; + if ((domain = find_domain_from_name(name_domain)) == NULL) { DEBUG(0, ("could not find domain entry for domain %s\n", name_domain)); @@ -137,7 +142,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) } /* Find uid for this sid and return it */ - if (NT_STATUS_IS_ERR(sid_to_uid(&sid, &(state->response.data.uid)))) { + if (!winbindd_idmap_get_uid_from_sid(&sid, &state->response.data.uid)) { DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid)); return WINBINDD_ERROR; @@ -166,7 +171,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) } /* Find gid for this sid and return it */ - if (NT_STATUS_IS_ERR(sid_to_gid(&sid, &(state->response.data.gid)))) { + if (!winbindd_idmap_get_gid_from_sid(&sid, &state->response.data.gid)) { DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid)); return WINBINDD_ERROR; @@ -192,7 +197,7 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) state->request.data.uid)); /* Lookup rid for this uid */ - if (NT_STATUS_IS_ERR(uid_to_sid(&sid, state->request.data.uid))) { + if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, &sid)) { DEBUG(1, ("Could not convert uid %d to rid\n", state->request.data.uid)); return WINBINDD_ERROR; @@ -221,7 +226,7 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) state->request.data.gid)); /* Lookup sid for this uid */ - if (NT_STATUS_IS_ERR(gid_to_sid(&sid, state->request.data.gid))) { + if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &sid)) { DEBUG(1, ("Could not convert gid %d to sid\n", state->request.data.gid)); return WINBINDD_ERROR; diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index dc07bc42e7..d2bd231918 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -41,15 +41,17 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, return False; /* Resolve the uid number */ - - if (NT_STATUS_IS_ERR(sid_to_uid(user_sid, &(pw->pw_uid)))) { + + if (!winbindd_idmap_get_uid_from_sid(user_sid, + &pw->pw_uid)) { DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid))); return False; } /* Resolve the gid number */ - - if (NT_STATUS_IS_ERR(sid_to_gid(group_sid, &(pw->pw_gid)))) { + + if (!winbindd_idmap_get_gid_from_sid(group_sid, + &pw->pw_gid)) { DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid))); return False; } @@ -176,9 +178,9 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) fstring user_name; enum SID_NAME_USE name_type; WINBIND_USERINFO user_info; + gid_t gid; TALLOC_CTX *mem_ctx; NTSTATUS status; - gid_t gid; /* Bug out if the uid isn't in the winbind range */ @@ -191,7 +193,8 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) /* Get rid from uid */ - if (NT_STATUS_IS_ERR(uid_to_sid(&user_sid, state->request.data.uid))) { + if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, + &user_sid)) { DEBUG(1, ("could not convert uid %d to SID\n", state->request.data.uid)); return WINBINDD_ERROR; @@ -233,9 +236,9 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - /* Check group has a gid number */ + /* Resolve gid number */ - if (NT_STATUS_IS_ERR(sid_to_gid(user_info.group_sid, &gid))) { + if (!winbindd_idmap_get_gid_from_sid(user_info.group_sid, &gid)) { DEBUG(1, ("error getting group id for user %s\n", user_name)); talloc_destroy(mem_ctx); return WINBINDD_ERROR; diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index ac0b317b42..ef030e2c7b 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -126,7 +126,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const /* see if this is a native mode win2k domain, but only for our own domain */ - if ( strequal( lp_workgroup(), domain_name) ) { + if ( lp_server_role() != ROLE_DOMAIN_PDC && strequal( lp_workgroup(), domain_name) ) { domain->native_mode = cm_check_for_native_mode_win2k( domain_name ); DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain_name, domain->native_mode ? "native" : "mixed" )); @@ -211,6 +211,7 @@ BOOL init_domain_list(void) /* Add ourselves as the first entry */ domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL); + if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) { DEBUG(1, ("Could not fetch sid for our domain %s\n", domain->name)); @@ -219,7 +220,7 @@ BOOL init_domain_list(void) /* get any alternate name for the primary domain */ cache_methods.alternate_name(domain); - + /* do an initial scan for trusted domains */ rescan_trusted_domains(True); @@ -380,12 +381,12 @@ BOOL winbindd_param_init(void) { /* Parse winbind uid and winbind_gid parameters */ - if (!lp_idmap_uid(&server_state.uid_low, &server_state.uid_high)) { + if (!lp_winbind_uid(&server_state.uid_low, &server_state.uid_high)) { DEBUG(0, ("winbind uid range missing or invalid\n")); return False; } - if (!lp_idmap_gid(&server_state.gid_low, &server_state.gid_high)) { + if (!lp_winbind_gid(&server_state.gid_low, &server_state.gid_high)) { DEBUG(0, ("winbind gid range missing or invalid\n")); return False; } |