From 301d51e13a1aa4e633e2da161b0dd260a8a499cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 13 Feb 2006 17:08:25 +0000 Subject: r13494: Merge the stuff I've done in head the last days. Volker (This used to be commit bb40e544de68f01a6e774753f508e69373b39899) --- source3/smbd/chgpasswd.c | 2 +- source3/smbd/map_username.c | 178 ++++++++++++++++++++++++++++++++++++++++++++ source3/smbd/password.c | 129 ++++++++++++++++++++++++++++++++ source3/smbd/posix_acls.c | 10 +-- source3/smbd/service.c | 2 +- 5 files changed, 310 insertions(+), 11 deletions(-) create mode 100644 source3/smbd/map_username.c (limited to 'source3/smbd') diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e04e902b3a..8f3e7236c4 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1067,7 +1067,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw pass = Get_Pwnam(username); if (!pass) { - DEBUG(1, ("check_oem_password: Username %s does not exist in system !?!\n", username)); + DEBUG(1, ("change_oem_password: Username %s does not exist in system !?!\n", username)); return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c new file mode 100644 index 0000000000..a6025fcf47 --- /dev/null +++ b/source3/smbd/map_username.c @@ -0,0 +1,178 @@ +/* + Unix SMB/CIFS implementation. + Username handling + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1997-2001. + Copyright (C) Volker Lendecke 2006 + + 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 "includes.h" + +/******************************************************************* + Map a username from a dos name to a unix name by looking in the username + map. Note that this modifies the name in place. + This is the main function that should be called *once* on + any incoming or new username - in order to canonicalize the name. + This is being done to de-couple the case conversions from the user mapping + function. Previously, the map_username was being called + every time Get_Pwnam was called. + Returns True if username was changed, false otherwise. +********************************************************************/ + +BOOL map_username(fstring user) +{ + static BOOL initialised=False; + static fstring last_from,last_to; + XFILE *f; + char *mapfile = lp_username_map(); + char *s; + pstring buf; + BOOL mapped_user = False; + char *cmd = lp_username_map_script(); + + if (!*user) + return False; + + if (strequal(user,last_to)) + return False; + + if (strequal(user,last_from)) { + DEBUG(3,("Mapped user %s to %s\n",user,last_to)); + fstrcpy(user,last_to); + return True; + } + + /* first try the username map script */ + + if ( *cmd ) { + char **qlines; + pstring command; + int numlines, ret, fd; + + pstr_sprintf( command, "%s \"%s\"", cmd, user ); + + DEBUG(10,("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10,("returned [%d]\n", ret)); + + if ( ret != 0 ) { + if (fd != -1) + close(fd); + return False; + } + + numlines = 0; + qlines = fd_lines_load(fd, &numlines,0); + DEBUGADD(10,("Lines returned = [%d]\n", numlines)); + close(fd); + + /* should be either no lines or a single line with the mapped username */ + + if (numlines) { + DEBUG(3,("Mapped user %s to %s\n", user, qlines[0] )); + fstrcpy( user, qlines[0] ); + } + + file_lines_free(qlines); + + return numlines != 0; + } + + /* ok. let's try the mapfile */ + + if (!*mapfile) + return False; + + if (!initialised) { + *last_from = *last_to = 0; + initialised = True; + } + + f = x_fopen(mapfile,O_RDONLY, 0); + if (!f) { + DEBUG(0,("can't open username map %s. Error %s\n",mapfile, strerror(errno) )); + return False; + } + + DEBUG(4,("Scanning username map %s\n",mapfile)); + + while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) { + char *unixname = s; + char *dosname = strchr_m(unixname,'='); + char **dosuserlist; + BOOL return_if_mapped = False; + + if (!dosname) + continue; + + *dosname++ = 0; + + while (isspace((int)*unixname)) + unixname++; + + if ('!' == *unixname) { + return_if_mapped = True; + unixname++; + while (*unixname && isspace((int)*unixname)) + unixname++; + } + + if (!*unixname || strchr_m("#;",*unixname)) + continue; + + { + int l = strlen(unixname); + while (l && isspace((int)unixname[l-1])) { + unixname[l-1] = 0; + l--; + } + } + + dosuserlist = str_list_make(dosname, NULL); + if (!dosuserlist) { + DEBUG(0,("Unable to build user list\n")); + return False; + } + + if (strchr_m(dosname,'*') || + user_in_list(user, (const char **)dosuserlist)) { + DEBUG(3,("Mapped user %s to %s\n",user,unixname)); + mapped_user = True; + fstrcpy( last_from,user ); + fstrcpy( user, unixname ); + fstrcpy( last_to,user ); + if ( return_if_mapped ) { + str_list_free (&dosuserlist); + x_fclose(f); + return True; + } + } + + str_list_free (&dosuserlist); + } + + x_fclose(f); + + /* + * Setup the last_from and last_to as an optimization so + * that we don't scan the file again for the same user. + */ + fstrcpy(last_from,user); + fstrcpy(last_to,user); + + return mapped_user; +} diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e644550400..0eeb537ded 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -401,6 +401,135 @@ void add_session_user(const char *user) safe_strcat(session_userlist,suser,len_session_userlist-1); } +/**************************************************************************** + Check if a user is in a netgroup user list. If at first we don't succeed, + try lower case. +****************************************************************************/ + +BOOL user_in_netgroup(const char *user, const char *ngname) +{ +#ifdef HAVE_NETGROUP + static char *mydomain = NULL; + fstring lowercase_user; + + if (mydomain == NULL) + yp_get_default_domain(&mydomain); + + if(mydomain == NULL) { + DEBUG(5,("Unable to get default yp domain\n")); + return False; + } + + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", + user, mydomain, ngname)); + + if (innetgr(ngname, NULL, user, mydomain)) { + DEBUG(5,("user_in_netgroup: Found\n")); + return (True); + } else { + + /* + * Ok, innetgr is case sensitive. Try once more with lowercase + * just in case. Attempt to fix #703. JRA. + */ + + fstrcpy(lowercase_user, user); + strlower_m(lowercase_user); + + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", + lowercase_user, mydomain, ngname)); + + if (innetgr(ngname, NULL, lowercase_user, mydomain)) { + DEBUG(5,("user_in_netgroup: Found\n")); + return (True); + } + } +#endif /* HAVE_NETGROUP */ + return False; +} + +/**************************************************************************** + Check if a user is in a user list - can check combinations of UNIX + and netgroup lists. +****************************************************************************/ + +BOOL user_in_list(const char *user,const char **list) +{ + if (!list || !*list) + return False; + + DEBUG(10,("user_in_list: checking user %s in list\n", user)); + + while (*list) { + + DEBUG(10,("user_in_list: checking user |%s| against |%s|\n", + user, *list)); + + /* + * Check raw username. + */ + if (strequal(user, *list)) + return(True); + + /* + * Now check to see if any combination + * of UNIX and netgroups has been specified. + */ + + if(**list == '@') { + /* + * Old behaviour. Check netgroup list + * followed by UNIX list. + */ + if(user_in_netgroup(user, *list +1)) + return True; + if(user_in_group(user, *list +1)) + return True; + } else if (**list == '+') { + + if((*(*list +1)) == '&') { + /* + * Search UNIX list followed by netgroup. + */ + if(user_in_group(user, *list +2)) + return True; + if(user_in_netgroup(user, *list +2)) + return True; + + } else { + + /* + * Just search UNIX list. + */ + + if(user_in_group(user, *list +1)) + return True; + } + + } else if (**list == '&') { + + if(*(*list +1) == '+') { + /* + * Search netgroup list followed by UNIX list. + */ + if(user_in_netgroup(user, *list +2)) + return True; + if(user_in_group(user, *list +2)) + return True; + } else { + /* + * Just search netgroup list. + */ + if(user_in_netgroup(user, *list +1)) + return True; + } + } + + list++; + } + return(False); +} + /**************************************************************************** Check if a username is valid. ****************************************************************************/ diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index d4dd926089..2befca40c2 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -1015,7 +1015,6 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type) static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) { fstring u_name; - fstring g_name; /* "Everyone" always matches every uid. */ @@ -1028,14 +1027,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) return True; fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid)); - fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid)); - - /* - * Due to the winbind interfaces we need to do this via names, - * not uids/gids. - */ - - return user_in_group(u_name, g_name); + return user_in_group_sid(u_name, &group_ace->trustee); } /**************************************************************************** diff --git a/source3/smbd/service.c b/source3/smbd/service.c index cf0116cc09..0fce677ea9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -473,7 +473,7 @@ static NTSTATUS find_forced_group(BOOL force_user, */ if (force_user && user_must_be_member) { - if (user_in_group(username, groupname)) { + if (user_in_group_sid(username, &group_sid)) { sid_copy(pgroup_sid, &group_sid); *pgid = gid; DEBUG(3,("Forced group %s for member %s\n", -- cgit