Basic doc changes to keep up to date.
[samba.git] / source3 / lib / username.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Username handling
5    Copyright (C) Andrew Tridgell 1992-1995
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 extern int DEBUGLEVEL;
24
25
26 /****************************************************************************
27 get a users home directory. tries as-is then lower case
28 ****************************************************************************/
29 char *get_home_dir(char *user)
30 {
31   static struct passwd *pass;
32
33   pass = Get_Pwnam(user,False);
34
35   if (!pass) return(NULL);
36   return(pass->pw_dir);      
37 }
38
39
40 /*******************************************************************
41 map a username from a dos name to a unix name by looking in the username
42 map
43 ********************************************************************/
44 void map_username(char *user)
45 {
46   static int depth=0;
47   static BOOL initialised=False;
48   static fstring last_from,last_to;
49   FILE *f;
50   char *s;
51   char *mapfile = lp_username_map();
52   if (!*mapfile || depth) return;
53
54   if (!*user) return;
55
56   if (!initialised) {
57     *last_from = *last_to = 0;
58     initialised = True;
59   }
60
61   if (strequal(user,last_to)) return;
62
63   if (strequal(user,last_from)) {
64     DEBUG(3,("Mapped user %s to %s\n",user,last_to));
65     strcpy(user,last_to);
66     return;
67   }
68   
69   f = fopen(mapfile,"r");
70   if (!f) {
71     DEBUG(0,("can't open username map %s\n",mapfile));
72     return;
73   }
74
75   DEBUG(4,("Scanning username map %s\n",mapfile));
76
77   depth++;
78
79   for (; (s=fgets_slash(NULL,80,f)); free(s)) {
80     char *unixname = s;
81     char *dosname = strchr(unixname,'=');
82
83     if (!dosname) continue;
84     *dosname++ = 0;
85
86     while (isspace(*unixname)) unixname++;
87     if (!*unixname || strchr("#;",*unixname)) continue;
88
89     {
90       int l = strlen(unixname);
91       while (l && isspace(unixname[l-1])) {
92         unixname[l-1] = 0;
93         l--;
94       }
95     }
96
97     if (strchr(dosname,'*') || user_in_list(user,dosname)) {
98       DEBUG(3,("Mapped user %s to %s\n",user,unixname));
99       StrnCpy(last_from,user,sizeof(last_from)-1);
100       sscanf(unixname,"%s",user);
101       StrnCpy(last_to,user,sizeof(last_to)-1);
102     }
103   }
104
105   fclose(f);
106
107   depth--;
108 }
109
110 /****************************************************************************
111 internals of Get_Pwnam wrapper
112 ****************************************************************************/
113 static struct passwd *_Get_Pwnam(char *s)
114 {
115   struct passwd *ret;
116
117   ret = getpwnam(s);
118   if (ret)
119     {
120 #ifdef GETPWANAM
121       struct passwd_adjunct *pwret;
122       pwret = getpwanam(s);
123       if (pwret)
124         {
125           free(ret->pw_passwd);
126           ret->pw_passwd = pwret->pwa_passwd;
127         }
128 #endif
129
130     }
131
132   return(ret);
133 }
134
135
136 /****************************************************************************
137 a wrapper for getpwnam() that tries with all lower and all upper case 
138 if the initial name fails. Also tried with first letter capitalised
139 Note that this changes user!
140 ****************************************************************************/
141 struct passwd *Get_Pwnam(char *user,BOOL allow_change)
142 {
143   fstring user2;
144
145   struct passwd *ret;  
146
147   if (!user || !(*user))
148     return(NULL);
149
150   StrnCpy(user2,user,sizeof(user2)-1);
151
152   if (!allow_change) {
153     user = &user2[0];
154   }
155
156   map_username(user);
157
158   ret = _Get_Pwnam(user);
159   if (ret) return(ret);
160
161   strlower(user);
162   ret = _Get_Pwnam(user);
163   if (ret)  return(ret);
164
165   strupper(user);
166   ret = _Get_Pwnam(user);
167   if (ret) return(ret);
168
169   /* try with first letter capitalised */
170   if (strlen(user) > 1)
171     strlower(user+1);  
172   ret = _Get_Pwnam(user);
173   if (ret) return(ret);
174
175   if (allow_change)
176     strcpy(user,user2);
177
178   return(NULL);
179 }
180
181
182 /****************************************************************************
183 check if a user is in a user list
184 ****************************************************************************/
185 BOOL user_in_list(char *user,char *list)
186 {
187   pstring tok;
188   char *p=list;
189
190   while (next_token(&p,tok,LIST_SEP))
191     {
192       if (strequal(user,tok))
193         return(True);
194
195 #ifdef NETGROUP
196       if (*tok == '@')
197         {
198           static char *mydomain = NULL;
199           if (mydomain == 0)
200             yp_get_default_domain(&mydomain);
201           
202           DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
203                    user, mydomain, &tok[1]));
204           DEBUG(5,("innetgr is %s\n",
205                    innetgr(&tok[1], (char *) 0, user, mydomain)
206                    ? "TRUE" : "FALSE"));
207           
208           if (innetgr(&tok[1], (char *)0, user, mydomain))
209             return (True);
210         }
211 #endif
212
213
214 #if HAVE_GETGRNAM 
215       if (*tok == '@')
216         {
217           struct group *gptr;
218           char **member;  
219           struct passwd *pass = Get_Pwnam(user,False);
220
221           if (pass) { 
222             gptr = getgrgid(pass->pw_gid);
223             if (gptr && strequal(gptr->gr_name,&tok[1]))
224               return(True); 
225           } 
226
227           gptr = (struct group *)getgrnam(&tok[1]);
228
229           if (gptr)
230             {
231               member = gptr->gr_mem;
232               while (member && *member)
233                 {
234                   if (strequal(*member,user))
235                     return(True);
236                   member++;
237                 }
238             }
239         }             
240 #endif
241     }
242   return(False);
243 }
244
245