From 5b0038a2afd8abbd6fd4a58f5477a40d1926d498 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 13 Oct 2000 01:59:14 +0000 Subject: Fix to allow smbd to call winbindd if it is running for all group enumeration, falling back to the UNIX calls on error. This should fix all problems with smbd enumerating all users in all groups in all trusted domains via winbindd. Also changed GETDC to query 1C name rather than 1b name as only the PDC registers 1b. Jeremy. --- source/include/proto.h | 29 ++++-- source/lib/username.c | 130 ++++++++++++++++++++--- source/lib/util.c | 50 ++++++--- source/libsmb/namequery.c | 2 +- source/nsswitch/wb_client.c | 247 +++++++++----------------------------------- source/smbd/groupname.c | 10 +- source/smbd/service.c | 16 ++- source/smbd/uid.c | 226 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 457 insertions(+), 253 deletions(-) diff --git a/source/include/proto.h b/source/include/proto.h index b68209434f0..e3d574de21d 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -151,6 +151,7 @@ void mdfour(unsigned char *out, unsigned char *in, int n); /*The following definitions come from lib/messages.c */ void ping_message(int msg_type, pid_t src, void *buf, size_t len); +void debuglevel_message(int msg_type, pid_t src, void *buf, size_t len); BOOL message_init(void); BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len); void message_dispatch(void); @@ -317,6 +318,7 @@ char *ufc_crypt(char *key,char *salt); char *get_user_home_dir(char *user); BOOL map_username(char *user); struct passwd *Get_Pwnam(char *user,BOOL allow_change); +BOOL user_in_group_list(char *user,char *gname); BOOL user_in_list(char *user,char *list); struct passwd *smb_getpwnam(char *user, BOOL allow_change); @@ -358,8 +360,8 @@ struct hostent *Get_Hostbyname(const char *name); BOOL process_exists(pid_t pid); char *uidtoname(uid_t uid); char *gidtoname(gid_t gid); -uid_t nametouid(const char *name); -gid_t nametogid(const char *name); +uid_t nametouid(char *name); +gid_t nametogid(char *name); void smb_panic(char *why); char *readdirname(DIR *p); BOOL is_in_path(char *name, name_compare_entry *namelist); @@ -1299,12 +1301,16 @@ void expire_workgroups_and_servers(time_t t); BOOL winbind_lookup_name(char *name, DOM_SID *sid, enum SID_NAME_USE *name_type); BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type); -BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type); -BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type); -DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid); -DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid); -BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype); -BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype); +BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid); +BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid); +BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid); +BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid); +int winbind_initgroups(char *user, gid_t gid); +int winbind_getgroups(char *user, int size, gid_t *list); +BOOL winbind_uidtoname(fstring name, uid_t uid); +BOOL winbind_gidtoname(fstring name, gid_t gid); +BOOL winbind_nametouid(uid_t *puid, char *name); +BOOL winbind_nametogid(gid_t *pgid, char *gname); /*The following definitions come from nsswitch/wb_common.c */ @@ -3648,7 +3654,6 @@ user_struct *get_valid_user_struct(uint16 vuid); void invalidate_vuid(uint16 vuid); char *validated_username(uint16 vuid); char *validated_domain(uint16 vuid); -BOOL initialize_groups(char *user, uid_t uid, gid_t gid); NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups); uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, char *domain,BOOL guest); @@ -3843,6 +3848,12 @@ BOOL become_authenticated_pipe_user(pipes_struct *p); BOOL unbecome_authenticated_pipe_user(pipes_struct *p); void become_root(void); void unbecome_root(void); +BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type); +BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type); +DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid); +DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid); +BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype); +BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype); #endif /*The following definitions come from smbd/unix_acls.c */ diff --git a/source/lib/username.c b/source/lib/username.c index ad44c0c5444..32e9eb31885 100644 --- a/source/lib/username.c +++ b/source/lib/username.c @@ -260,35 +260,130 @@ static BOOL user_in_netgroup_list(char *user,char *ngname) } /**************************************************************************** - Check if a user is in a UNIX user list. + Check if a user is in a winbind group. +****************************************************************************/ + +static BOOL user_in_winbind_group_list(char *user,char *gname, BOOL *winbind_answered) +{ + int num_groups; + int i; + gid_t *groups = NULL; + gid_t gid; + DOM_SID g_sid; + enum SID_NAME_USE name_type; + BOOL ret = False; + + *winbind_answered = False; + + /* + * Get the gid's that this user belongs to. + */ + + if ((num_groups = winbind_getgroups(user, 0, NULL)) == -1) + return False; + + if (num_groups == 0) { + *winbind_answered = True; + return False; + } + + if ((groups = (gid_t *)malloc(sizeof(gid_t) * num_groups )) == NULL) { + DEBUG(0,("user_in_winbind_group_list: malloc fail.\n")); + goto err; + } + + if ((num_groups = winbind_getgroups(user, num_groups, groups)) == -1) { + DEBUG(0,("user_in_winbind_group_list: second winbind_getgroups call \ +failed with error %s\n", strerror(errno) )); + goto err; + } + + /* + * Now we have the gid list for this user - convert the gname + * to a gid_t via winbind and do the comparison. + */ + + if (!winbind_nametogid(gname, &gid)) { + DEBUG(0,("user_in_winbind_group_list: winbind_lookup_name for group %s failed.\n", + gname )); + goto err; + } + + for (i = 0; i < num_groups; i++) { + if (gid == groups[i]) { + ret = True; + break; + } + } + + *winbind_answered = True; + safe_free(groups); + return ret; + + err: + + *winbind_answered = False; + safe_free(groups); + return False; +} + +/**************************************************************************** + Check if a user is in a UNIX group. ****************************************************************************/ -static BOOL user_in_group_list(char *user,char *gname) +static BOOL user_in_unix_group_list(char *user,char *gname) { struct group *gptr; char **member; struct passwd *pass = Get_Pwnam(user,False); - if (pass) { - gptr = getgrgid(pass->pw_gid); - if (gptr && strequal(gptr->gr_name,gname)) - return True; - } - - if ((gptr = (struct group *)getgrnam(gname)) == NULL) - return False; - - member = gptr->gr_mem; - while (member && *member) { - if (strequal(*member,user)) { - return(True); - } + DEBUG(10,("user_in_unix_group_list: checking user %s in group %s\n", user, gname)); + + /* + * We need to check the users primary group as this + * group is implicit and often not listed in the group database. + */ + + if (pass) { + gptr = getgrgid(pass->pw_gid); + if (gptr && strequal(gptr->gr_name,gname)) { + DEBUG(10,("user_in_unix_group_list: group %s is primary group.\n", gname )); + return True; + } + } + + if ((gptr = (struct group *)getgrnam(gname)) == NULL) { + DEBUG(10,("user_in_unix_group_list: no such group %s\n", gname )); + return False; + } + + member = gptr->gr_mem; + while (member && *member) { + DEBUG(10,("user_in_unix_group_list: checking user %s against member %s\n", user, *member )); + if (strequal(*member,user)) { + return(True); + } member++; } return False; } +/**************************************************************************** + Check if a user is in a group list. Ask winbind first, then use UNIX. +****************************************************************************/ + +BOOL user_in_group_list(char *user,char *gname) +{ + BOOL winbind_answered = False; + BOOL ret = user_in_winbind_group_list(user, gname, &winbind_answered); + + if (winbind_answered) + return ret; + + return user_in_unix_group_list(user, gname); +} + /**************************************************************************** Check if a user is in a user list - can check combinations of UNIX and netgroup lists. @@ -299,6 +394,8 @@ BOOL user_in_list(char *user,char *list) pstring tok; char *p=list; + DEBUG(10,("user_in_list: checking user %s in list %s\n", user, list)); + while (next_token(&p,tok,LIST_SEP, sizeof(tok))) { /* * Check raw username. @@ -447,4 +544,3 @@ struct passwd *smb_getpwnam(char *user, BOOL allow_change) return NULL; } - diff --git a/source/lib/util.c b/source/lib/util.c index aced56bc2f7..0aef60082f3 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -1099,60 +1099,80 @@ BOOL process_exists(pid_t pid) /******************************************************************* -turn a uid into a user name + Convert a uid into a user name. ********************************************************************/ + char *uidtoname(uid_t uid) { - static char name[40]; - struct passwd *pass = sys_getpwuid(uid); - if (pass) return(pass->pw_name); - slprintf(name, sizeof(name) - 1, "%d",(int)uid); - return(name); + static fstring name; + struct passwd *pass; + + if (winbind_uidtoname(name, uid)) + return name; + + pass = sys_getpwuid(uid); + if (pass) return(pass->pw_name); + slprintf(name, sizeof(name) - 1, "%d",(int)uid); + return(name); } /******************************************************************* -turn a gid into a group name + Convert a gid into a group name. ********************************************************************/ char *gidtoname(gid_t gid) { - static char name[40]; - struct group *grp = getgrgid(gid); + static fstring name; + struct group *grp; + + if (winbind_gidtoname(name, gid)) + return name; + + grp = getgrgid(gid); if (grp) return(grp->gr_name); slprintf(name,sizeof(name) - 1, "%d",(int)gid); return(name); } /******************************************************************* -turn a user name into a uid + Convert a user name into a uid. If winbindd is present uses this. ********************************************************************/ -uid_t nametouid(const char *name) + +uid_t nametouid(char *name) { struct passwd *pass; char *p; uid_t u; - u = strtol(name, &p, 0); + u = (uid_t)strtol(name, &p, 0); if (p != name) return u; + if (winbind_nametouid(&u, name)) + return u; + pass = sys_getpwnam(name); if (pass) return(pass->pw_uid); return (uid_t)-1; } /******************************************************************* -turn a group name into a gid + Convert a name to a gid_t if possible. Return -1 if not a group. If winbindd + is present does a shortcut lookup... ********************************************************************/ -gid_t nametogid(const char *name) + +gid_t nametogid(char *name) { struct group *grp; char *p; gid_t g; - g = strtol(name, &p, 0); + g = (gid_t)strtol(name, &p, 0); if (p != name) return g; + if (winbind_nametogid(&g, name)) + return g; + grp = getgrnam(name); if (grp) return(grp->gr_gid); return (gid_t)-1; diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c index 41924d4631e..52ff6287c42 100644 --- a/source/libsmb/namequery.c +++ b/source/libsmb/namequery.c @@ -891,7 +891,7 @@ BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pd dgram->header.packet_offset = 0; make_nmb_name(&dgram->source_name,srcname,0); - make_nmb_name(&dgram->dest_name,domain,0x1B); + make_nmb_name(&dgram->dest_name,domain,0x1C); ptr = &dgram->data[0]; diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c index 436bbc7bcc3..d2762674aac 100644 --- a/source/nsswitch/wb_client.c +++ b/source/nsswitch/wb_client.c @@ -58,27 +58,8 @@ BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_N struct winbindd_request request; struct winbindd_response response; enum nss_status result; - DOM_SID tmp_sid; - uint32 rid; fstring sid_str; - if (!name_type) - return False; - - /* Check if this is our own sid. This should perhaps be done by - winbind? For the moment handle it here. */ - - if (sid->num_auths == 5) { - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - - if (sid_equal(&global_sam_sid, &tmp_sid)) { - - return map_domain_sid_to_name(&tmp_sid, dom_name) && - local_lookup_rid(rid, name, name_type); - } - } - /* Initialise request */ ZERO_STRUCT(request); @@ -103,7 +84,7 @@ BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_N /* Call winbindd to convert SID to uid */ -static BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid) +BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid) { struct winbindd_request request; struct winbindd_response response; @@ -136,7 +117,7 @@ static BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid) /* Call winbindd to convert uid to sid */ -static BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid) +BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid) { struct winbindd_request request; struct winbindd_response response; @@ -169,7 +150,7 @@ static BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid) /* Call winbindd to convert SID to gid */ -static BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid) +BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid) { struct winbindd_request request; struct winbindd_response response; @@ -202,7 +183,7 @@ static BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid) /* Call winbindd to convert gid to sid */ -static BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid) +BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid) { struct winbindd_request request; struct winbindd_response response; @@ -361,208 +342,82 @@ int winbind_getgroups(char *user, int size, gid_t *list) return result; } -/***************************************************************** - *THE CANONICAL* convert name to SID function. - Tries winbind first - then uses local lookup. -*****************************************************************/ +/********************************************************************************** + Utility function. Convert a uid_t to a name if possible. +**********************************************************************************/ -BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) +BOOL winbind_uidtoname(fstring name, uid_t uid) { - extern pstring global_myname; - fstring sid; - - if (!winbind_lookup_name(name, psid, name_type)) { - BOOL ret; - - DEBUG(10,("lookup_name: winbind lookup for %s failed - trying local\n", name )); - - ret = local_lookup_name(global_myname, name, psid, name_type); - if (ret) - DEBUG(10,("lookup_name : (local) %s -> SID %s (type %u)\n", - name, sid_to_string(sid,psid), - (unsigned int)*name_type )); - else - DEBUG(10,("lookup name : (local) %s failed.\n", - name )); - return ret; - } - - DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", - name, sid_to_string(sid,psid), (unsigned int)*name_type )); - return True; -} - -/***************************************************************** - *THE CANONICAL* convert SID to name function. - Tries winbind first - then uses local lookup. -*****************************************************************/ + DOM_SID sid; + fstring dom_name; + enum SID_NAME_USE name_type; -BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) -{ - if (!winbind_lookup_sid(sid, dom_name, name, name_type)) { - fstring sid_str; - DOM_SID tmp_sid; - uint32 rid; + if (!winbind_uid_to_sid(&sid, uid)) + return False; + if (!winbind_lookup_sid(&sid, dom_name, name, &name_type)) + return False; - DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) )); + if (name_type != SID_NAME_USER) + return False; - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - return map_domain_sid_to_name(&tmp_sid, dom_name) && - lookup_known_rid(&tmp_sid, rid, name, name_type); - } return True; } -/***************************************************************** - *THE CANONICAL* convert uid_t to SID function. - Tries winbind first - then uses local lookup. - Returns SID pointer. -*****************************************************************/ +/********************************************************************************** + Utility function. Convert a gid_t to a name if possible. +**********************************************************************************/ -DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) +BOOL winbind_gidtoname(fstring name, gid_t gid) { - fstring sid; - - if (!winbind_uid_to_sid(psid, uid)) { - DEBUG(10,("uid_to_sid: winbind lookup for uid %u failed - trying local.\n", (unsigned int)uid )); - - return local_uid_to_sid(psid, uid); - } - - DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid) )); - - return psid; -} - -/***************************************************************** - *THE CANONICAL* convert gid_t to SID function. - Tries winbind first - then uses local lookup. - Returns SID pointer. -*****************************************************************/ - -DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) -{ - fstring sid; - - if (!winbind_gid_to_sid(psid, gid)) { - DEBUG(10,("gid_to_sid: winbind lookup for gid %u failed - trying local.\n", (unsigned int)gid )); - - return local_gid_to_sid(psid, gid); - } - - DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", - (unsigned int)gid, sid_to_string(sid,psid) )); - - return psid; -} - -/***************************************************************** - *THE CANONICAL* convert SID to uid function. - Tries winbind first - then uses local lookup. - Returns True if this name is a user sid and the conversion - was done correctly, False if not. -*****************************************************************/ - -BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) -{ - fstring dom_name, name, sid_str; + DOM_SID sid; + fstring dom_name; enum SID_NAME_USE name_type; - *sidtype = SID_NAME_UNKNOWN; - - /* - * First we must look up the name and decide if this is a user sid. - */ - - if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { - DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", - sid_to_string(sid_str, psid) )); - - return local_sid_to_uid(puid, psid, sidtype); - } - - /* - * Ensure this is a user sid. - */ - - if (name_type != SID_NAME_USER) { - DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n", - (unsigned int)name_type )); + if (!winbind_gid_to_sid(&sid, gid)) return False; - } - - *sidtype = SID_NAME_USER; - - /* - * Get the uid for this SID. - */ - - if (!winbind_sid_to_uid(puid, psid)) { - DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n", - sid_to_string(sid_str, psid) )); + if (!winbind_lookup_sid(&sid, dom_name, name, &name_type)) return False; - } - DEBUG(10,("sid_to_uid: winbindd %s -> %u\n", - sid_to_string(sid_str, psid), - (unsigned int)*puid )); + if (name_type != SID_NAME_USER) + return False; return True; } -/***************************************************************** - *THE CANONICAL* convert SID to gid function. - Tries winbind first - then uses local lookup. - Returns True if this name is a user sid and the conversion - was done correctly, False if not. -*****************************************************************/ +/********************************************************************************** + Utility function. Convert a name to a uid_t if possible. +**********************************************************************************/ -BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) +BOOL winbind_nametouid(uid_t *puid, char *name) { - fstring dom_name, name, sid_str; + DOM_SID sid; enum SID_NAME_USE name_type; - *sidtype = SID_NAME_UNKNOWN; - - /* - * First we must look up the name and decide if this is a group sid. - */ + if (!winbind_lookup_name(name, &sid, &name_type)) { + return False; + } - if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { - DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", - sid_to_string(sid_str, psid) )); - - return local_sid_to_gid(pgid, psid, sidtype); - } - - /* - * Ensure this is a group sid. - */ + if (name_type != SID_NAME_USER) + return False; - if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { - DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a know group (%u)\n", - (unsigned int)name_type )); + return winbind_sid_to_uid(puid, &sid); +} - return local_sid_to_gid(pgid, psid, sidtype); - } +/********************************************************************************** + Utility function. Convert a name to a gid_t if possible. +**********************************************************************************/ - *sidtype = name_type; +BOOL winbind_nametogid(gid_t *pgid, char *gname) +{ + DOM_SID g_sid; + enum SID_NAME_USE name_type; - /* - * Get the gid for this SID. - */ + if (!winbind_lookup_name(gname, &g_sid, &name_type)) { + return False; + } - if (!winbind_sid_to_gid(pgid, psid)) { - DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n", - sid_to_string(sid_str, psid) )); + if (name_type != SID_NAME_DOM_GRP) return False; - } - - DEBUG(10,("gid_to_uid: winbindd %s -> %u\n", - sid_to_string(sid_str, psid), - (unsigned int)*pgid )); - return True; + return winbind_sid_to_gid(pgid, &g_sid); } diff --git a/source/smbd/groupname.c b/source/smbd/groupname.c index f0b11e1b366..d53fa56a44f 100644 --- a/source/smbd/groupname.c +++ b/source/smbd/groupname.c @@ -119,7 +119,7 @@ void load_groupname_map(void) for (i=0; lines[i]; i++) { pstring unixname; pstring windows_name; - struct group *gptr; + gid_t gid; DOM_SID tmp_sid; char *s = lines[i]; @@ -150,8 +150,8 @@ void load_groupname_map(void) * Attempt to get the unix gid_t for this name. */ - if((gptr = (struct group *)getgrnam(unixname)) == NULL) { - DEBUG(0,("load_groupname_map: getgrnam for group %s failed.\ + if ((gid = nametogid(unixname)) == (gid_t)-1) + DEBUG(0,("load_groupname_map: nametogid for group %s failed.\ Error was %s.\n", unixname, strerror(errno) )); continue; } @@ -167,7 +167,7 @@ Error was %s.\n", unixname, strerror(errno) )); */ tmp_sid = global_sam_sid; tmp_sid.sub_auths[tmp_sid.num_auths++] = - pdb_gid_to_group_rid((gid_t)gptr->gr_gid); + pdb_gid_to_group_rid(gid); } /* @@ -180,7 +180,7 @@ Error was %s.\n", unixname, strerror(errno) )); return; } - new_ep->unix_gid = gptr->gr_gid; + new_ep->unix_gid = gid; new_ep->windows_sid = tmp_sid; new_ep->windows_name = strdup( windows_name ); new_ep->unix_name = strdup( unixname ); diff --git a/source/smbd/service.c b/source/smbd/service.c index 6d075627438..b86f3beadda 100644 --- a/source/smbd/service.c +++ b/source/smbd/service.c @@ -401,7 +401,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int */ if (*lp_force_group(snum)) { - struct group *gptr; + gid_t gid; pstring gname; pstring tmp_gname; BOOL user_must_be_member = False; @@ -416,9 +416,9 @@ connection_struct *make_connection(char *service,char *user,char *password, int } /* default service may be a group name */ pstring_sub(gname,"%S",service); - gptr = (struct group *)getgrnam(gname); + gid = nametogid(gname); - if (gptr) { + if (gid != (gid_t)-1) { /* * If the user has been forced and the forced group starts * with a '+', then we only set the group to be the forced @@ -426,16 +426,12 @@ connection_struct *make_connection(char *service,char *user,char *password, int * Otherwise, the meaning of the '+' would be ignored. */ if (conn->force_user && user_must_be_member) { - int i; - for (i = 0; gptr->gr_mem[i] != NULL; i++) { - if (strcmp(user,gptr->gr_mem[i]) == 0) { - conn->gid = gptr->gr_gid; + if (user_in_group_list( user, gname )) { + conn->gid = gid; DEBUG(3,("Forced group %s for member %s\n",gname,user)); - break; - } } } else { - conn->gid = gptr->gr_gid; + conn->gid = gid; DEBUG(3,("Forced group %s\n",gname)); } } else { diff --git a/source/smbd/uid.c b/source/smbd/uid.c index b28f056a301..fb83e724b8b 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -257,4 +257,230 @@ void unbecome_root(void) pop_sec_ctx(); } +/***************************************************************** + *THE CANONICAL* convert name to SID function. + Tries winbind first - then uses local lookup. +*****************************************************************/ + +BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) +{ + extern pstring global_myname; + fstring sid; + + if (!winbind_lookup_name(name, psid, name_type)) { + BOOL ret; + + DEBUG(10,("lookup_name: winbind lookup for %s failed - trying local\n", name )); + + ret = local_lookup_name(global_myname, name, psid, name_type); + if (ret) + DEBUG(10,("lookup_name : (local) %s -> SID %s (type %u)\n", + name, sid_to_string(sid,psid), + (unsigned int)*name_type )); + else + DEBUG(10,("lookup name : (local) %s failed.\n", + name )); + return ret; + } + + DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n", + name, sid_to_string(sid,psid), (unsigned int)*name_type )); + return True; +} + +/***************************************************************** + *THE CANONICAL* convert SID to name function. + Tries winbind first - then uses local lookup. +*****************************************************************/ + +BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) +{ + if (!name_type) + return False; + + /* Check if this is our own sid. This should perhaps be done by + winbind? For the moment handle it here. */ + + if (sid->num_auths == 5) { + DOM_SID tmp_sid; + uint32 rid; + + sid_copy(&tmp_sid, sid); + sid_split_rid(&tmp_sid, &rid); + + if (sid_equal(&global_sam_sid, &tmp_sid)) { + + return map_domain_sid_to_name(&tmp_sid, dom_name) && + local_lookup_rid(rid, name, name_type); + } + } + + if (!winbind_lookup_sid(sid, dom_name, name, name_type)) { + fstring sid_str; + DOM_SID tmp_sid; + uint32 rid; + + DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) )); + + sid_copy(&tmp_sid, sid); + sid_split_rid(&tmp_sid, &rid); + return map_domain_sid_to_name(&tmp_sid, dom_name) && + lookup_known_rid(&tmp_sid, rid, name, name_type); + } + return True; +} + +/***************************************************************** + *THE CANONICAL* convert uid_t to SID function. + Tries winbind first - then uses local lookup. + Returns SID pointer. +*****************************************************************/ + +DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid) +{ + fstring sid; + + if (!winbind_uid_to_sid(psid, uid)) { + DEBUG(10,("uid_to_sid: winbind lookup for uid %u failed - trying local.\n", (unsigned int)uid )); + + return local_uid_to_sid(psid, uid); + } + + DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid) )); + + return psid; +} + +/***************************************************************** + *THE CANONICAL* convert gid_t to SID function. + Tries winbind first - then uses local lookup. + Returns SID pointer. +*****************************************************************/ + +DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid) +{ + fstring sid; + + if (!winbind_gid_to_sid(psid, gid)) { + DEBUG(10,("gid_to_sid: winbind lookup for gid %u failed - trying local.\n", (unsigned int)gid )); + + return local_gid_to_sid(psid, gid); + } + + DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", + (unsigned int)gid, sid_to_string(sid,psid) )); + + return psid; +} + +/***************************************************************** + *THE CANONICAL* convert SID to uid function. + Tries winbind first - then uses local lookup. + Returns True if this name is a user sid and the conversion + was done correctly, False if not. +*****************************************************************/ + +BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + + *sidtype = SID_NAME_UNKNOWN; + + /* + * First we must look up the name and decide if this is a user sid. + */ + + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n", + sid_to_string(sid_str, psid) )); + + return local_sid_to_uid(puid, psid, sidtype); + } + + /* + * Ensure this is a user sid. + */ + + if (name_type != SID_NAME_USER) { + DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n", + (unsigned int)name_type )); + return False; + } + + *sidtype = SID_NAME_USER; + + /* + * Get the uid for this SID. + */ + + if (!winbind_sid_to_uid(puid, psid)) { + DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n", + sid_to_string(sid_str, psid) )); + return False; + } + + DEBUG(10,("sid_to_uid: winbindd %s -> %u\n", + sid_to_string(sid_str, psid), + (unsigned int)*puid )); + + return True; +} + +/***************************************************************** + *THE CANONICAL* convert SID to gid function. + Tries winbind first - then uses local lookup. + Returns True if this name is a user sid and the conversion + was done correctly, False if not. +*****************************************************************/ + +BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + + *sidtype = SID_NAME_UNKNOWN; + + /* + * First we must look up the name and decide if this is a group sid. + */ + + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", + sid_to_string(sid_str, psid) )); + + return local_sid_to_gid(pgid, psid, sidtype); + } + + /* + * Ensure this is a group sid. + */ + + if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { + DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a know group (%u)\n", + (unsigned int)name_type )); + + return local_sid_to_gid(pgid, psid, sidtype); + } + + *sidtype = name_type; + + /* + * Get the gid for this SID. + */ + + if (!winbind_sid_to_gid(pgid, psid)) { + DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n", + sid_to_string(sid_str, psid) )); + return False; + } + + DEBUG(10,("gid_to_uid: winbindd %s -> %u\n", + sid_to_string(sid_str, psid), + (unsigned int)*pgid )); + + return True; +} + #undef OLD_NTDOMAIN -- cgit