diff options
Diffstat (limited to 'source3/smbd/map_username.c')
-rw-r--r-- | source3/smbd/map_username.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c new file mode 100644 index 0000000000..7536758bcb --- /dev/null +++ b/source3/smbd/map_username.c @@ -0,0 +1,215 @@ +/* + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#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_alloc was called. + Returns True if username was changed, false otherwise. +********************************************************************/ + +static char *last_from, *last_to; + +static const char *get_last_from(void) +{ + if (!last_from) { + return ""; + } + return last_from; +} + +static const char *get_last_to(void) +{ + if (!last_to) { + return ""; + } + return last_to; +} + +static bool set_last_from_to(const char *from, const char *to) +{ + char *orig_from = last_from; + char *orig_to = last_to; + + last_from = SMB_STRDUP(from); + last_to = SMB_STRDUP(to); + + SAFE_FREE(orig_from); + SAFE_FREE(orig_to); + + if (!last_from || !last_to) { + SAFE_FREE(last_from); + SAFE_FREE(last_to); + return false; + } + return true; +} + +bool map_username(fstring user) +{ + XFILE *f; + char *mapfile = lp_username_map(); + char *s; + char buf[512]; + bool mapped_user = False; + char *cmd = lp_username_map_script(); + + if (!*user) + return false; + + if (strequal(user,get_last_to())) + return false; + + if (strequal(user,get_last_from())) { + DEBUG(3,("Mapped user %s to %s\n",user,get_last_to())); + fstrcpy(user,get_last_to()); + return true; + } + + /* first try the username map script */ + + if ( *cmd ) { + char **qlines; + char *command = NULL; + int numlines, ret, fd; + + command = talloc_asprintf(talloc_tos(), + "%s \"%s\"", + cmd, + user); + if (!command) { + return false; + } + + 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 && qlines) { + 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; + + 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--; + } + } + + /* skip lines like 'user = ' */ + + dosuserlist = str_list_make(talloc_tos(), dosname, NULL); + if (!dosuserlist) { + DEBUG(0,("Bad username map entry. Unable to build user list. Ignoring.\n")); + continue; + } + + if (strchr_m(dosname,'*') || + user_in_list(user, (const char **)dosuserlist)) { + DEBUG(3,("Mapped user %s to %s\n",user,unixname)); + mapped_user = True; + + set_last_from_to(user, unixname); + fstrcpy( user, unixname ); + + if ( return_if_mapped ) { + TALLOC_FREE(dosuserlist); + x_fclose(f); + return True; + } + } + + TALLOC_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. + */ + + set_last_from_to(user, user); + + return mapped_user; +} |