Initial version imported to CVS
[jra/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 #include "loadparm.h"
24 extern int DEBUGLEVEL;
25
26
27 /****************************************************************************
28 get a users home directory. tries as-is then lower case
29 ****************************************************************************/
30 char *get_home_dir(char *user)
31 {
32   static struct passwd *pass;
33
34   pass = Get_Pwnam(user,False);
35
36   if (!pass) return(NULL);
37   return(pass->pw_dir);      
38 }
39
40
41 /*******************************************************************
42 map a username from a dos name to a unix name by looking in the username
43 map
44 ********************************************************************/
45 void map_username(char *user)
46 {
47   static int depth=0;
48   static BOOL initialised=False;
49   static fstring last_from,last_to;
50   FILE *f;
51   char *s;
52   char *mapfile = lp_username_map();
53   if (!*mapfile || depth) return;
54
55   if (!*user) return;
56
57   if (!initialised) {
58     *last_from = *last_to = 0;
59     initialised = True;
60   }
61
62   if (strequal(user,last_to)) return;
63
64   if (strequal(user,last_from)) {
65     DEBUG(3,("Mapped user %s to %s\n",user,last_to));
66     strcpy(user,last_to);
67     return;
68   }
69   
70   f = fopen(mapfile,"r");
71   if (!f) {
72     DEBUG(0,("can't open username map %s\n",mapfile));
73     return;
74   }
75
76   DEBUG(4,("Scanning username map %s\n",mapfile));
77
78   depth++;
79
80   for (; (s=fgets_slash(NULL,80,f)); free(s)) {
81     char *unixname = s;
82     char *dosname = strchr(unixname,'=');
83
84     if (!dosname) continue;
85     *dosname++ = 0;
86
87     while (isspace(*unixname)) unixname++;
88     if (!*unixname || strchr("#;",*unixname)) continue;
89
90     {
91       int l = strlen(unixname);
92       while (l && isspace(unixname[l-1])) {
93         unixname[l-1] = 0;
94         l--;
95       }
96     }
97
98     if (strchr(dosname,'*') || user_in_list(user,dosname)) {
99       DEBUG(3,("Mapped user %s to %s\n",user,unixname));
100       StrnCpy(last_from,user,sizeof(last_from)-1);
101       sscanf(unixname,"%s",user);
102       StrnCpy(last_to,user,sizeof(last_to)-1);
103     }
104   }
105
106   fclose(f);
107
108   depth--;
109 }
110
111 /****************************************************************************
112 internals of Get_Pwnam wrapper
113 ****************************************************************************/
114 static struct passwd *_Get_Pwnam(char *s)
115 {
116   struct passwd *ret;
117
118   ret = getpwnam(s);
119   if (ret)
120     {
121 #ifdef GETPWANAM
122       struct passwd_adjunct *pwret;
123       pwret = getpwanam(s);
124       if (pwret)
125         {
126           free(ret->pw_passwd);
127           ret->pw_passwd = pwret->pwa_passwd;
128         }
129 #endif
130
131     }
132
133   return(ret);
134 }
135
136
137 /****************************************************************************
138 a wrapper for getpwnam() that tries with all lower and all upper case 
139 if the initial name fails. Also tried with first letter capitalised
140 Note that this changes user!
141 ****************************************************************************/
142 struct passwd *Get_Pwnam(char *user,BOOL allow_change)
143 {
144   fstring user2;
145
146   struct passwd *ret;  
147
148   if (!user || !(*user))
149     return(NULL);
150
151   StrnCpy(user2,user,sizeof(user2)-1);
152
153   if (!allow_change) {
154     user = &user2[0];
155   }
156
157   map_username(user);
158
159   ret = _Get_Pwnam(user);
160   if (ret) return(ret);
161
162   strlower(user);
163   ret = _Get_Pwnam(user);
164   if (ret)  return(ret);
165
166   strupper(user);
167   ret = _Get_Pwnam(user);
168   if (ret) return(ret);
169
170   /* try with first letter capitalised */
171   if (strlen(user) > 1)
172     strlower(user+1);  
173   ret = _Get_Pwnam(user);
174   if (ret) return(ret);
175
176   if (allow_change)
177     strcpy(user,user2);
178
179   return(NULL);
180 }
181
182
183 /****************************************************************************
184 check if a user is in a user list
185 ****************************************************************************/
186 BOOL user_in_list(char *user,char *list)
187 {
188   pstring tok;
189   char *p=list;
190
191   while (next_token(&p,tok,LIST_SEP))
192     {
193       if (strequal(user,tok))
194         return(True);
195
196 #ifdef NETGROUP
197       if (*tok == '@')
198         {
199           static char *mydomain = NULL;
200           if (mydomain == 0)
201             yp_get_default_domain(&mydomain);
202           
203           DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
204                    user, mydomain, &tok[1]));
205           DEBUG(5,("innetgr is %s\n",
206                    innetgr(&tok[1], (char *) 0, user, mydomain)
207                    ? "TRUE" : "FALSE"));
208           
209           if (innetgr(&tok[1], (char *)0, user, mydomain))
210             return (True);
211         }
212 #endif
213
214
215 #if HAVE_GETGRNAM 
216       if (*tok == '@')
217         {
218           struct group *gptr;
219           char **member;  
220           struct passwd *pass = Get_Pwnam(user,False);
221
222           if (pass) { 
223             gptr = getgrgid(pass->pw_gid);
224             if (gptr && strequal(gptr->gr_name,&tok[1]))
225               return(True); 
226           } 
227
228           gptr = (struct group *)getgrnam(&tok[1]);
229
230           if (gptr)
231             {
232               member = gptr->gr_mem;
233               while (member && *member)
234                 {
235                   if (strequal(*member,user))
236                     return(True);
237                   member++;
238                 }
239             }
240         }             
241 #endif
242     }
243   return(False);
244 }
245
246