1/* 2 Unix SMB/CIFS implementation. 3 Username handling 4 Copyright (C) Andrew Tridgell 1992-1998 5 Copyright (C) Jeremy Allison 1997-2001. 6 Copyright (C) Volker Lendecke 2006 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "smbd/globals.h" 24 25/******************************************************************* 26 Map a username from a dos name to a unix name by looking in the username 27 map. Note that this modifies the name in place. 28 This is the main function that should be called *once* on 29 any incoming or new username - in order to canonicalize the name. 30 This is being done to de-couple the case conversions from the user mapping 31 function. Previously, the map_username was being called 32 every time Get_Pwnam_alloc was called. 33 Returns True if username was changed, false otherwise. 34********************************************************************/ 35 36static const char *get_last_from(void) 37{ 38 if (!last_from) { 39 return ""; 40 } 41 return last_from; 42} 43 44static const char *get_last_to(void) 45{ 46 if (!last_to) { 47 return ""; 48 } 49 return last_to; 50} 51 52static bool set_last_from_to(const char *from, const char *to) 53{ 54 char *orig_from = last_from; 55 char *orig_to = last_to; 56 57 last_from = SMB_STRDUP(from); 58 last_to = SMB_STRDUP(to); 59 60 SAFE_FREE(orig_from); 61 SAFE_FREE(orig_to); 62 63 if (!last_from || !last_to) { 64 SAFE_FREE(last_from); 65 SAFE_FREE(last_to); 66 return false; 67 } 68 return true; 69} 70 71bool map_username(struct smbd_server_connection *sconn, fstring user) 72{ 73 XFILE *f; 74 char *mapfile = lp_username_map(); 75 char *s; 76 char buf[512]; 77 bool mapped_user = False; 78 char *cmd = lp_username_map_script(); 79 80 if (!*user) 81 return false; 82 83 if (strequal(user,get_last_to())) 84 return false; 85 86 if (strequal(user,get_last_from())) { 87 DEBUG(3,("Mapped user %s to %s\n",user,get_last_to())); 88 fstrcpy(user,get_last_to()); 89 return true; 90 } 91 92 /* first try the username map script */ 93 94 if ( *cmd ) { 95 char **qlines; 96 char *command = NULL; 97 int numlines, ret, fd; 98 99 command = talloc_asprintf(talloc_tos(), 100 "%s \"%s\"", 101 cmd, 102 user); 103 if (!command) { 104 return false; 105 } 106 107 DEBUG(10,("Running [%s]\n", command)); 108 ret = smbrun(command, &fd); 109 DEBUGADD(10,("returned [%d]\n", ret)); 110 111 if ( ret != 0 ) { 112 if (fd != -1) 113 close(fd); 114 return False; 115 } 116 117 numlines = 0; 118 qlines = fd_lines_load(fd, &numlines,0, NULL); 119 DEBUGADD(10,("Lines returned = [%d]\n", numlines)); 120 close(fd); 121 122 /* should be either no lines or a single line with the mapped username */ 123 124 if (numlines && qlines) { 125 DEBUG(3,("Mapped user %s to %s\n", user, qlines[0] )); 126 fstrcpy( user, qlines[0] ); 127 } 128 129 TALLOC_FREE(qlines); 130 131 return numlines != 0; 132 } 133 134 /* ok. let's try the mapfile */ 135 if (!*mapfile) 136 return False; 137 138 f = x_fopen(mapfile,O_RDONLY, 0); 139 if (!f) { 140 DEBUG(0,("can't open username map %s. Error %s\n",mapfile, strerror(errno) )); 141 return False; 142 } 143 144 DEBUG(4,("Scanning username map %s\n",mapfile)); 145 146 while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) { 147 char *unixname = s; 148 char *dosname = strchr_m(unixname,'='); 149 char **dosuserlist; 150 bool return_if_mapped = False; 151 152 if (!dosname) 153 continue; 154 155 *dosname++ = 0; 156 157 while (isspace((int)*unixname)) 158 unixname++; 159 160 if ('!' == *unixname) { 161 return_if_mapped = True; 162 unixname++; 163 while (*unixname && isspace((int)*unixname)) 164 unixname++; 165 } 166 167 if (!*unixname || strchr_m("#;",*unixname)) 168 continue; 169 170 { 171 int l = strlen(unixname); 172 while (l && isspace((int)unixname[l-1])) { 173 unixname[l-1] = 0; 174 l--; 175 } 176 } 177 178 /* skip lines like 'user = ' */ 179 180 dosuserlist = str_list_make_v3(talloc_tos(), dosname, NULL); 181 if (!dosuserlist) { 182 DEBUG(0,("Bad username map entry. Unable to build user list. Ignoring.\n")); 183 continue; 184 } 185 186 if (strchr_m(dosname,'*') || 187 user_in_list(sconn, user, (const char **)dosuserlist)) { 188 DEBUG(3,("Mapped user %s to %s\n",user,unixname)); 189 mapped_user = True; 190 191 set_last_from_to(user, unixname); 192 fstrcpy( user, unixname ); 193 194 if ( return_if_mapped ) { 195 TALLOC_FREE(dosuserlist); 196 x_fclose(f); 197 return True; 198 } 199 } 200 201 TALLOC_FREE(dosuserlist); 202 } 203 204 x_fclose(f); 205 206 /* 207 * Setup the last_from and last_to as an optimization so 208 * that we don't scan the file again for the same user. 209 */ 210 211 set_last_from_to(user, user); 212 213 return mapped_user; 214} 215