first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[metze/samba/wip.git] / source3 / lib / util_pwdb.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Password and authentication handling
5    Copyright (C) Jeremy Allison 1996-1998
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1998
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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "nterr.h"
25
26 extern int DEBUGLEVEL;
27 extern DOM_SID global_sam_sid;
28 extern fstring global_sam_name;
29
30 extern DOM_SID global_member_sid;
31 extern fstring global_myworkgroup;
32
33 extern DOM_SID global_sid_S_1_5_20;
34
35 extern pstring global_myname;
36
37 typedef struct
38 {
39         uint32 rid;
40         char *defaultname;
41         char *name;
42 } rid_name;
43
44 /*
45  * A list of the rids of well known BUILTIN and Domain users
46  * and groups.
47  */
48
49 static rid_name builtin_alias_rids[] =
50 {  
51     { BUILTIN_ALIAS_RID_ADMINS       , "Administrators"    , NULL },
52     { BUILTIN_ALIAS_RID_USERS        , "Users"             , NULL },
53     { BUILTIN_ALIAS_RID_GUESTS       , "Guests"            , NULL },
54     { BUILTIN_ALIAS_RID_POWER_USERS  , "Power Users"       , NULL },
55    
56     { BUILTIN_ALIAS_RID_ACCOUNT_OPS  , "Account Operators" , NULL },
57     { BUILTIN_ALIAS_RID_SYSTEM_OPS   , "System Operators"  , NULL },
58     { BUILTIN_ALIAS_RID_PRINT_OPS    , "Print Operators"   , NULL },
59     { BUILTIN_ALIAS_RID_BACKUP_OPS   , "Backup Operators"  , NULL },
60     { BUILTIN_ALIAS_RID_REPLICATOR   , "Replicator"        , NULL },
61     { 0                              , NULL                , NULL}
62 };
63
64 /* array lookup of well-known Domain RID users. */
65 static rid_name domain_user_rids[] =
66 {  
67     { DOMAIN_USER_RID_ADMIN         , "Administrator" , NULL },
68     { DOMAIN_USER_RID_GUEST         , "Guest"         , NULL },
69     { 0                             , NULL            , NULL}
70 };
71
72 /* array lookup of well-known Domain RID groups. */
73 static rid_name domain_group_rids[] =
74 {  
75     { DOMAIN_GROUP_RID_ADMINS       , "Domain Admins" , NULL },
76     { DOMAIN_GROUP_RID_USERS        , "Domain Users"  , NULL },
77     { DOMAIN_GROUP_RID_GUESTS       , "Domain Guests" , NULL },
78     { 0                             , NULL            , NULL}
79 };
80
81 /*******************************************************************
82   make an entry in wk name map
83   the name is strdup()ed!
84  *******************************************************************/
85 static BOOL make_alias_entry(rid_name *map, char *defaultname, char *name)
86 {
87         if(isdigit(*defaultname))
88         {
89                 long rid = -1;
90                 char *s;
91
92                 if(*defaultname == '0')
93                 {
94                         if(defaultname[1] == 'x')
95                         {
96                                 s = "%lx";
97                                 defaultname += 2;
98                         }
99                         else
100                         {
101                                 s = "%lo";
102                         }
103                 }
104                 else
105                 {
106                         s = "%ld";
107                 }
108
109                 sscanf(defaultname, s, &rid);
110
111                 for( ; map->rid; map++)
112                 {
113                         if(map->rid == rid) {
114                                 map->name = strdup(name);
115                                 DEBUG(5, ("make_alias_entry: mapping %s (rid 0x%x) to %s\n",
116                                       map->defaultname, map->rid, map->name));
117                                 return True;
118                         }
119                 }
120                 return False;
121         }
122
123         for( ; map->rid; map++)
124         {
125                 if(!StrCaseCmp(map->name, defaultname)) {
126                         map->name = strdup(name);
127                         DEBUG(5, ("make_alias_entry: mapping %s (rid 0x%x) to %s\n",
128                               map->defaultname, map->rid, map->name));
129                         return True;
130                 }
131         }
132         return False;
133 }
134
135 /*******************************************************************
136   reset wk map to default values
137  *******************************************************************/
138 static void reset_wk_map(rid_name *map)
139 {
140         for( ; map->rid; map++)
141         {
142                 if(map->name != NULL && map->name != map->defaultname)
143                         free(map->name);
144                 map->name = map->defaultname;
145         }
146 }
147
148 /*******************************************************************
149   reset all wk maps
150  *******************************************************************/
151 static void reset_wk_maps(void)
152 {
153         DEBUG(4, ("reset_wk_maps: Initializing maps\n"));
154         reset_wk_map(builtin_alias_rids);
155         reset_wk_map(domain_user_rids);
156         reset_wk_map(domain_group_rids);
157 }
158
159 /*******************************************************************
160   Load builtin alias map
161  *******************************************************************/
162 static BOOL load_wk_rid_map(void)
163 {
164         static int map_initialized = 0;
165         static time_t builtin_rid_file_last_modified = (time_t)0;
166         char *builtin_rid_file = lp_builtinrid_file();
167
168         FILE *fp;
169         char *s;
170         pstring buf;
171
172         if (!map_initialized)
173         {
174                 reset_wk_maps();
175                 map_initialized = 1;
176         }
177
178         if (!*builtin_rid_file)
179         {
180                 return False;
181         }
182
183         fp = open_file_if_modified(builtin_rid_file, "r", &builtin_rid_file_last_modified);
184         if(!fp)
185         {
186                 DEBUG(0,("load_wk_rid_map: can't open name map %s. Error was %s\n",
187                           builtin_rid_file, strerror(errno)));
188                  return False;
189         }
190
191         reset_wk_maps();
192         DEBUG(4,("load_wk_rid_map: Scanning builtin rid map %s\n",builtin_rid_file));
193
194         while ((s = fgets_slash(buf, sizeof(buf), fp)) != NULL)
195         {
196                 pstring defaultname;
197                 pstring name;
198
199                 DEBUG(10,("Read line |%s|\n", s));
200
201                 if (!*s || strchr("#;",*s))
202                         continue;
203
204                 if (!next_token(&s,name, "\t\n\r=", sizeof(defaultname)))
205                         continue;
206
207                 if (!next_token(&s,defaultname, "\t\n\r=", sizeof(name)))
208                         continue;
209
210                 trim_string(defaultname, " ", " ");
211                 trim_string(name, " ", " ");
212
213                 if (!*defaultname || !*name)
214                         continue;
215
216                 if(make_alias_entry(builtin_alias_rids, defaultname, name))
217                         continue;
218                 if(make_alias_entry(domain_user_rids, defaultname, name))
219                         continue;
220                 if(make_alias_entry(domain_group_rids, defaultname, name))
221                         continue;
222
223                 DEBUG(0,("load_wk_rid_map: Unknown alias %s in map %s\n",
224                          defaultname, builtin_rid_file));
225         }
226
227         fclose(fp);
228         return True;
229 }
230
231 /*******************************************************************
232  lookup_wk_group_name
233  ********************************************************************/
234 uint32 lookup_wk_group_name(const char *group_name, const char *domain,
235                                 DOM_SID *sid, uint8 *type)
236 {
237         char *grp_name;
238         int i = -1; /* start do loop at -1 */
239         uint32 rid;
240         (*type) = SID_NAME_DOM_GRP;
241
242         if (strequal(domain, global_sam_name))
243         {
244                 sid_copy(sid, &global_sam_sid);
245         }
246         else if (strequal(domain, "BUILTIN"))
247         {
248                 sid_copy(sid, &global_sid_S_1_5_20);
249         }
250         else
251         {
252                 return 0xC0000000 | NT_STATUS_NONE_MAPPED;
253         }
254
255         load_wk_rid_map();
256
257         do /* find, if it exists, a group rid for the group name */
258         {
259                 i++;
260                 rid      = domain_group_rids[i].rid;
261                 grp_name = domain_group_rids[i].name;
262
263                 if (strequal(grp_name, group_name))
264                 {
265                         sid_append_rid(sid, rid);
266
267                         return 0x0;
268                 }
269                         
270         } while (grp_name != NULL);
271
272         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
273 }
274
275 /*******************************************************************
276  lookup_wk_user_name
277  ********************************************************************/
278 uint32 lookup_wk_user_name(const char *user_name, const char *domain,
279                                 DOM_SID *sid, uint8 *type)
280 {
281         char *usr_name;
282         int i = -1; /* start do loop at -1 */
283         (*type) = SID_NAME_USER;
284
285         if (strequal(domain, global_sam_name))
286         {
287                 sid_copy(sid, &global_sam_sid);
288         }
289         else if (strequal(domain, "BUILTIN"))
290         {
291                 sid_copy(sid, &global_sid_S_1_5_20);
292         }
293         else
294         {
295                 return 0xC0000000 | NT_STATUS_NONE_MAPPED;
296         }
297
298         load_wk_rid_map();
299
300         do /* find, if it exists, a alias rid for the alias name */
301         {
302                 i++;
303                 usr_name = domain_user_rids[i].name;
304
305         } while (usr_name != NULL && !strequal(usr_name, user_name));
306
307         if (usr_name != NULL)
308         {
309                 sid_append_rid(sid, domain_user_rids[i].rid);
310                 return 0;
311         }
312
313         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
314 }
315
316 /*******************************************************************
317  lookup_builtin_alias_name
318  ********************************************************************/
319 uint32 lookup_builtin_alias_name(const char *alias_name, const char *domain,
320                                 DOM_SID *sid, uint8 *type)
321 {
322         char *als_name;
323         int i = 0;
324         uint32 rid;
325
326         if (strequal(domain, "BUILTIN"))
327         {
328                 if (sid != NULL)
329                 {
330                         sid_copy(sid, &global_sid_S_1_5_20);
331                 }
332         }
333         else
334         {
335                 return 0xC0000000 | NT_STATUS_NONE_MAPPED;
336         }
337
338         load_wk_rid_map();
339
340         do /* find, if it exists, a alias rid for the alias name*/
341         {
342                 rid      = builtin_alias_rids[i].rid;
343                 als_name = builtin_alias_rids[i].name;
344
345                 if (strequal(als_name, alias_name))
346                 {
347                         if (sid != NULL)
348                         {
349                                 sid_append_rid(sid, rid);
350                         }
351
352                         if (type != NULL)
353                         {
354                                 (*type) = SID_NAME_ALIAS;
355                         }
356
357                         return 0x0;
358                 }
359                         
360                 i++;
361
362         } while (als_name != NULL);
363
364         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
365 }
366
367 /*************************************************************
368  initialise password databases, domain names, domain sid.
369 **************************************************************/
370 BOOL pwdb_initialise(BOOL is_server)
371 {
372         get_sam_domain_name();
373
374         if (!init_myworkgroup())
375         {
376                 return False;
377         }
378
379         generate_wellknown_sids();
380
381         if (is_server)
382         {
383                 if (!generate_sam_sid(global_sam_name, &global_sam_sid))
384                 {
385                         DEBUG(0,("ERROR: Samba cannot create a SAM SID for its domain (%s).\n",
386                                   global_sam_name));
387                         return False;
388                 }
389         }
390         else
391         {
392                 if (!get_domain_sids(lp_workgroup(), &global_member_sid,
393                                       &global_sam_sid))
394                 {
395                         return False;
396                 }
397         }
398
399         create_sidmap_table();
400
401         return initialise_password_db();
402 }
403
404 /*************************************************************
405  the following functions lookup wk rid's.
406  these may be unnecessary...
407 **************************************************************/
408 static char *lookup_wk_rid(uint32 rid, rid_name *table)
409 {
410         load_wk_rid_map();
411         for( ; table->rid ; table++)
412         {
413                 if(table->rid == rid)
414                 {
415                         return table->name;
416                 }
417         }
418         return NULL;
419 }
420
421 char *lookup_wk_alias_rid(uint32 rid)
422 {
423         return lookup_wk_rid(rid, builtin_alias_rids);
424 }
425
426 char *lookup_wk_user_rid(uint32 rid)
427 {
428         return lookup_wk_rid(rid, domain_user_rids);
429 }
430
431 char *lookup_wk_group_rid(uint32 rid)
432 {
433         return lookup_wk_rid(rid, domain_group_rids);
434 }
435