2 Unix SMB/Netbios implementation.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
25 extern int DEBUGLEVEL;
27 extern pstring global_myname;
30 * This is set on startup - it defines the SID for this
31 * machine, and therefore the SAM database for which it is
35 DOM_SID global_sam_sid;
38 * This is the name associated with the SAM database for
39 * which this machine is responsible. In the case of a PDC
40 * or PDC, this name is the same as the workgroup. In the
41 * case of "security = domain" mode, this is the same as
42 * the name of the server (global_myname).
45 fstring global_sam_name;
48 * This is obtained on startup - it defines the SID for which
49 * this machine is a member. It is therefore only set, and
50 * used, in "security = domain" mode.
53 DOM_SID global_member_sid;
56 * note the lack of a "global_member_name" - this is because
57 * this is the same as "global_myworkgroup".
60 extern fstring global_myworkgroup;
61 /* fstring global_member_dom_name; */
67 DOM_SID global_sid_S_1_5_20; /* local well-known domain */
68 DOM_SID global_sid_S_1_1; /* everyone */
69 DOM_SID global_sid_S_1_3; /* Creator Owner */
70 DOM_SID global_sid_S_1_5; /* NT Authority */
79 struct sid_map static_sid_name_map[] =
81 { &global_sid_S_1_5_20, "BUILTIN" },
82 { &global_sid_S_1_1 , "Everyone" },
83 { &global_sid_S_1_3 , "Creator Owner" },
84 { &global_sid_S_1_5 , "NT Authority" },
85 { &global_sam_sid , global_sam_name },
86 { &global_member_sid , global_myworkgroup },
90 struct sid_map **sid_name_map = NULL;
93 static struct sid_map *sid_map_dup(const struct sid_map *from)
97 struct sid_map *copy = (struct sid_map *)
98 malloc(sizeof(struct sid_map));
102 if (from->name != NULL)
104 copy->name = strdup(from->name );
106 if (from->sid != NULL)
108 copy->sid = sid_dup(from->sid);
116 static void sid_map_free(struct sid_map *map)
118 if (map->name != NULL)
122 if (map->sid != NULL)
129 /****************************************************************************
131 ****************************************************************************/
132 static void free_sidmap_array(uint32 num_entries, struct sid_map **entries)
134 void(*fn)(void*) = (void(*)(void*))&sid_map_free;
135 free_void_array(num_entries, (void**)entries, *fn);
138 /****************************************************************************
139 add a sid map state to the array
140 ****************************************************************************/
141 struct sid_map* add_sidmap_to_array(uint32 *len, struct sid_map ***array,
142 const struct sid_map *name)
144 void*(*fn)(const void*) = (void*(*)(const void*))&sid_map_dup;
145 return (struct sid_map*)add_copy_to_array(len,
146 (void***)array, (const void*)name, *fn, False);
149 /****************************************************************************
150 sets up the name associated with the SAM database for which we are responsible
151 ****************************************************************************/
152 void get_sam_domain_name(void)
154 switch (lp_server_role())
156 case ROLE_DOMAIN_PDC:
157 case ROLE_DOMAIN_BDC:
159 /* we are PDC (or BDC) for a Domain */
160 fstrcpy(global_sam_name, lp_workgroup());
163 case ROLE_DOMAIN_MEMBER:
165 /* we are a "PDC", but FOR LOCAL SAM DATABASE ONLY */
166 fstrcpy(global_sam_name, global_myname);
171 /* no domain role, probably due to "security = share" */
172 memset(global_sam_name, 0, sizeof(global_sam_name));
178 /****************************************************************************
179 obtain the sid from the PDC.
180 ****************************************************************************/
181 BOOL get_member_domain_sid(void)
183 switch (lp_server_role())
185 case ROLE_DOMAIN_NONE:
187 ZERO_STRUCT(global_member_sid);
190 case ROLE_DOMAIN_PDC:
192 sid_copy(&global_member_sid, &global_sam_sid);
197 /* member or BDC, we're going for connection to PDC */
202 return get_domain_sids(global_myname, NULL,
203 &global_member_sid, lp_workgroup());
207 /****************************************************************************
208 creates some useful well known sids
209 ****************************************************************************/
210 void generate_wellknown_sids(void)
212 string_to_sid(&global_sid_S_1_5_20, "S-1-5-32");
213 string_to_sid(&global_sid_S_1_1 , "S-1-1" );
214 string_to_sid(&global_sid_S_1_3 , "S-1-3" );
215 string_to_sid(&global_sid_S_1_5 , "S-1-5" );
218 /****************************************************************************
219 create a sid map table
220 ****************************************************************************/
221 BOOL create_sidmap_table(void)
227 for (i = 0; static_sid_name_map[i].name != NULL; i++)
229 add_sidmap_to_array(&num_maps, &sid_name_map,
230 &static_sid_name_map[i]);
233 enumtrustdoms(&doms, &num_doms);
235 for (i = 0; i < num_doms; i++)
243 if (!read_sid(map.name, map.sid))
245 DEBUG(0,("Could not read Domain SID %s\n", map.name));
248 add_sidmap_to_array(&num_maps, &sid_name_map, &map);
252 for (i = 0; i < num_maps; i++)
255 sid_to_string(sidstr, sid_name_map[i]->sid);
256 DEBUG(10,("Map:\tDomain:\t%s\tSID:\t%s\n",
257 sid_name_map[i]->name, sidstr));
261 free_char_array(num_doms, doms);
266 /****************************************************************************
267 Generate the global machine sid. Look for the DOMAINNAME.SID file first, if
268 not found then look in smb.conf and use it to create the DOMAINNAME.SID file.
269 ****************************************************************************/
270 BOOL generate_sam_sid(char *domain_name, DOM_SID *sid)
274 pstring machine_sid_file;
277 pstrcpy(sid_file, lp_smb_passwd_file());
279 if (sid_file[0] == 0)
281 DEBUG(0,("cannot find smb passwd file\n"));
285 p = strrchr(sid_file, '/');
291 if (!directory_exist(sid_file, NULL)) {
292 if (mkdir(sid_file, 0700) != 0) {
293 DEBUG(0,("can't create private directory %s : %s\n",
294 sid_file, strerror(errno)));
299 pstrcpy(machine_sid_file, sid_file);
300 pstrcat(machine_sid_file, "MACHINE.SID");
302 slprintf(file_name, sizeof(file_name)-1, "%s.SID", domain_name);
304 pstrcat(sid_file, file_name);
306 if (file_exist(machine_sid_file, NULL))
308 if (file_exist(sid_file, NULL))
310 DEBUG(0,("both %s and %s exist when only one should, unable to continue\n",
311 machine_sid_file, sid_file));
314 if (file_rename(machine_sid_file, sid_file))
316 DEBUG(0,("could not rename %s to %s. Error was %s\n",
317 machine_sid_file, sid_file, strerror(errno)));
322 /* attempt to read the SID from the file */
323 if (read_sid(domain_name, sid))
328 if (!create_new_sid(sid))
332 /* attempt to read the SID from the file */
333 if (!write_sid(domain_name, sid))
338 /* during the attempt to write, someone else wrote? */
340 /* attempt to read the SID from the file */
341 if (read_sid(domain_name, sid))
349 /**************************************************************************
350 turns a domain name into a SID.
352 *** side-effect: if the domain name is NULL, it is set to our domain ***
354 ***************************************************************************/
355 BOOL map_domain_name_to_sid(DOM_SID *sid, char **nt_domain)
359 if (nt_domain == NULL)
361 sid_copy(sid, &global_sam_sid);
365 if ((*nt_domain) == NULL)
367 DEBUG(5,("map_domain_name_to_sid: overriding NULL name to %s\n",
369 (*nt_domain) = strdup(global_sam_name);
370 sid_copy(sid, &global_sam_sid);
374 if ((*nt_domain)[0] == 0)
377 (*nt_domain) = strdup(global_sam_name);
378 DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n",
380 sid_copy(sid, &global_sam_sid);
384 DEBUG(5,("map_domain_name_to_sid: %s\n", (*nt_domain)));
386 for (i = 0; sid_name_map[i]->name != NULL; i++)
388 DEBUG(5,("compare: %s\n", sid_name_map[i]->name));
389 if (strequal(sid_name_map[i]->name, (*nt_domain)))
392 sid_copy(sid, sid_name_map[i]->sid);
393 sid_to_string(sid_str, sid_name_map[i]->sid);
394 DEBUG(5,("found %s\n", sid_str));
399 DEBUG(0,("map_domain_name_to_sid: mapping to %s NOT IMPLEMENTED\n",
404 /**************************************************************************
405 turns a domain SID into a name.
407 ***************************************************************************/
408 BOOL map_domain_sid_to_name(DOM_SID *sid, char *nt_domain)
412 sid_to_string(sid_str, sid);
414 DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str));
416 if (nt_domain == NULL)
421 for (i = 0; sid_name_map[i]->sid != NULL; i++)
423 sid_to_string(sid_str, sid_name_map[i]->sid);
424 DEBUG(5,("compare: %s\n", sid_str));
425 if (sid_equal(sid_name_map[i]->sid, sid))
427 fstrcpy(nt_domain, sid_name_map[i]->name);
428 DEBUG(5,("found %s\n", nt_domain));
433 DEBUG(0,("map_domain_sid_to_name: mapping NOT IMPLEMENTED\n"));
437 /**************************************************************************
438 turns a domain SID into a domain controller name.
439 ***************************************************************************/
440 BOOL map_domain_sid_to_any_dc(DOM_SID *sid, char *dc_name)
444 if (!map_domain_sid_to_name(sid, domain))
449 return get_any_dc_name(domain, dc_name);
452 /**************************************************************************
453 splits a name of format \DOMAIN\name or name into its two components.
454 sets the DOMAIN name to global_sam_name if it has not been specified.
455 ***************************************************************************/
456 BOOL split_domain_name(const char *fullname, char *domain, char *name)
461 if (fullname == NULL || domain == NULL || name == NULL)
466 if (fullname[0] == '\\')
470 fstrcpy(full_name, fullname);
471 p = strchr(full_name+1, '\\');
476 fstrcpy(domain, full_name);
481 fstrcpy(domain, global_sam_name);
482 fstrcpy(name, full_name);
485 DEBUG(10,("name '%s' split into domain:%s and nt name:%s'\n", fullname, domain, name));
489 /**************************************************************************
490 enumerates all trusted domains
491 ***************************************************************************/
492 BOOL enumtrustdoms(char ***doms, uint32 *num_entries)
497 /* add trusted domains */
499 tok = lp_trusted_domains();
500 if (next_token(&tok, tmp, NULL, sizeof(tmp)))
505 split_at_first_component(tmp, domain, '=', NULL);
506 add_chars_to_array(num_entries, doms, domain);
508 } while (next_token(NULL, tmp, NULL, sizeof(tmp)));
514 /**************************************************************************
515 enumerates all domains for which the SAM server is responsible
516 ***************************************************************************/
517 BOOL enumdomains(char ***doms, uint32 *num_entries)
519 add_chars_to_array(num_entries, doms, global_sam_name);
520 add_chars_to_array(num_entries, doms, "Builtin");