1/*
2   Unix SMB/CIFS implementation.
3   Samba utility functions
4   Copyright (C) Andrew Tridgell 1992-1998
5   Copyright (C) Luke Kenneth Caseson Leighton 1998-1999
6   Copyright (C) Jeremy Allison  1999
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
25#define MAX_SID_NAMES	7
26
27typedef struct _known_sid_users {
28	uint32 rid;
29	enum SID_NAME_USE sid_name_use;
30	const char *known_user_name;
31} known_sid_users;
32
33static struct sid_name_map_info
34{
35	DOM_SID *sid;
36	const char *name;
37	const known_sid_users *known_users;
38} sid_name_map[MAX_SID_NAMES];
39
40extern DOM_SID global_sid_Builtin; 				/* Local well-known domain */
41extern DOM_SID global_sid_World_Domain;	    	/* Everyone domain */
42extern DOM_SID global_sid_Creator_Owner_Domain;    /* Creator Owner domain */
43extern DOM_SID global_sid_NT_Authority;    		/* NT Authority */
44
45
46static BOOL sid_name_map_initialized = False;
47/* static known_sid_users no_users[] = {{0, 0, NULL}}; */
48
49static const known_sid_users everyone_users[] = {
50	{ 0, SID_NAME_WKN_GRP, "Everyone" },
51	{0, (enum SID_NAME_USE)0, NULL}};
52
53static const known_sid_users creator_owner_users[] = {
54	{ 0, SID_NAME_WKN_GRP, "Creator Owner" },
55	{ 1, SID_NAME_WKN_GRP, "Creator Group" },
56	{0, (enum SID_NAME_USE)0, NULL}};
57
58static const known_sid_users nt_authority_users[] = {
59	{  1, SID_NAME_WKN_GRP, "Dialup" },
60	{  2, SID_NAME_WKN_GRP, "Network"},
61	{  3, SID_NAME_WKN_GRP, "Batch"},
62	{  4, SID_NAME_WKN_GRP, "Interactive"},
63	{  6, SID_NAME_WKN_GRP, "Service"},
64	{  7, SID_NAME_WKN_GRP, "AnonymousLogon"},
65	{  8, SID_NAME_WKN_GRP, "Proxy"},
66	{  9, SID_NAME_WKN_GRP, "ServerLogon"},
67	{ 10, SID_NAME_WKN_GRP, "Self"},
68	{ 11, SID_NAME_WKN_GRP, "Authenticated Users"},
69	{ 12, SID_NAME_WKN_GRP, "Restricted"},
70	{ 13, SID_NAME_WKN_GRP, "Terminal Server User"},
71	{ 14, SID_NAME_WKN_GRP, "Remote Interactive Logon"},
72	{ 15, SID_NAME_WKN_GRP, "This Organization"},
73	{ 18, SID_NAME_WKN_GRP, "SYSTEM"},
74	{ 19, SID_NAME_WKN_GRP, "Local Service"},
75	{ 20, SID_NAME_WKN_GRP, "Network Service"},
76	{  0, (enum SID_NAME_USE)0, NULL}};
77
78static const known_sid_users builtin_groups[] = {
79	{ BUILTIN_ALIAS_RID_ADMINS, SID_NAME_ALIAS, "Administrators" },
80	{ BUILTIN_ALIAS_RID_USERS, SID_NAME_ALIAS, "Users" },
81	{ BUILTIN_ALIAS_RID_GUESTS, SID_NAME_ALIAS, "Guests" },
82	{ BUILTIN_ALIAS_RID_POWER_USERS, SID_NAME_ALIAS, "Power Users" },
83	{ BUILTIN_ALIAS_RID_ACCOUNT_OPS, SID_NAME_ALIAS, "Account Operators" },
84	{ BUILTIN_ALIAS_RID_SYSTEM_OPS, SID_NAME_ALIAS, "Server Operators" },
85	{ BUILTIN_ALIAS_RID_PRINT_OPS, SID_NAME_ALIAS, "Print Operators" },
86	{ BUILTIN_ALIAS_RID_BACKUP_OPS, SID_NAME_ALIAS, "Backup Operators" },
87	{ BUILTIN_ALIAS_RID_REPLICATOR, SID_NAME_ALIAS, "Replicator" },
88	{ BUILTIN_ALIAS_RID_RAS_SERVERS, SID_NAME_ALIAS, "RAS Servers" },
89	{ BUILTIN_ALIAS_RID_PRE_2K_ACCESS, SID_NAME_ALIAS, "Pre-Windows 2000 Compatible Access" },
90	{  0, (enum SID_NAME_USE)0, NULL}};
91
92/**************************************************************************
93 Quick init function.
94*************************************************************************/
95
96static void init_sid_name_map (void)
97{
98	int i = 0;
99
100	if (sid_name_map_initialized) return;
101
102	generate_wellknown_sids();
103
104	if ((lp_security() == SEC_USER) && lp_domain_logons()) {
105		sid_name_map[i].sid = get_global_sam_sid();
106		/* This is not lp_workgroup() for good reason:
107		   it must stay around longer than the lp_*()
108		   strings do */
109		sid_name_map[i].name = SMB_STRDUP(lp_workgroup());
110		sid_name_map[i].known_users = NULL;
111		i++;
112		sid_name_map[i].sid = get_global_sam_sid();
113		sid_name_map[i].name = SMB_STRDUP(global_myname());
114		sid_name_map[i].known_users = NULL;
115		i++;
116	} else {
117		sid_name_map[i].sid = get_global_sam_sid();
118		sid_name_map[i].name = SMB_STRDUP(global_myname());
119		sid_name_map[i].known_users = NULL;
120		i++;
121	}
122
123	sid_name_map[i].sid = &global_sid_Builtin;
124	sid_name_map[i].name = "BUILTIN";
125	sid_name_map[i].known_users = &builtin_groups[0];
126	i++;
127
128	sid_name_map[i].sid = &global_sid_World_Domain;
129	sid_name_map[i].name = "";
130	sid_name_map[i].known_users = &everyone_users[0];
131	i++;
132
133	sid_name_map[i].sid = &global_sid_Creator_Owner_Domain;
134	sid_name_map[i].name = "";
135	sid_name_map[i].known_users = &creator_owner_users[0];
136	i++;
137
138	sid_name_map[i].sid = &global_sid_NT_Authority;
139	sid_name_map[i].name = "NT Authority";
140	sid_name_map[i].known_users = &nt_authority_users[0];
141	i++;
142
143	/* End of array. */
144	sid_name_map[i].sid = NULL;
145	sid_name_map[i].name = NULL;
146	sid_name_map[i].known_users = NULL;
147
148	sid_name_map_initialized = True;
149
150	return;
151}
152
153/**************************************************************************
154 Turns a domain SID into a name, returned in the nt_domain argument.
155***************************************************************************/
156
157BOOL map_domain_sid_to_name(DOM_SID *sid, fstring nt_domain)
158{
159	fstring sid_str;
160	int i = 0;
161
162	sid_to_string(sid_str, sid);
163
164	if (!sid_name_map_initialized)
165		init_sid_name_map();
166
167	DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str));
168
169	if (nt_domain == NULL)
170		return False;
171
172	while (sid_name_map[i].sid != NULL) {
173		sid_to_string(sid_str, sid_name_map[i].sid);
174		DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str));
175		if (sid_equal(sid_name_map[i].sid, sid)) {
176			fstrcpy(nt_domain, sid_name_map[i].name);
177			DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain));
178			return True;
179		}
180		i++;
181	}
182
183	DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str));
184
185    return False;
186}
187
188/**************************************************************************
189 Looks up a known username from one of the known domains.
190***************************************************************************/
191
192BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, enum SID_NAME_USE *psid_name_use)
193{
194	int i = 0;
195	struct sid_name_map_info *psnm;
196
197	if (!sid_name_map_initialized)
198		init_sid_name_map();
199
200	for(i = 0; sid_name_map[i].sid != NULL; i++) {
201		psnm = &sid_name_map[i];
202		if(sid_equal(psnm->sid, sid)) {
203			int j;
204			for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) {
205				if(rid == psnm->known_users[j].rid) {
206					DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '%s'\n",
207						(unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name ));
208					fstrcpy( name, psnm->known_users[j].known_user_name);
209					*psid_name_use = psnm->known_users[j].sid_name_use;
210					return True;
211				}
212			}
213		}
214	}
215
216	return False;
217}
218
219/**************************************************************************
220 Turns a domain name into a SID.
221 *** side-effect: if the domain name is NULL, it is set to our domain ***
222***************************************************************************/
223
224BOOL map_domain_name_to_sid(DOM_SID *sid, char *nt_domain)
225{
226	int i = 0;
227
228	if (nt_domain == NULL) {
229		DEBUG(5,("map_domain_name_to_sid: mapping NULL domain to our SID.\n"));
230		sid_copy(sid, get_global_sam_sid());
231		return True;
232	}
233
234	if (nt_domain[0] == 0) {
235		fstrcpy(nt_domain, global_myname());
236		DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n", nt_domain));
237		sid_copy(sid, get_global_sam_sid());
238		return True;
239	}
240
241	DEBUG(5,("map_domain_name_to_sid: %s\n", nt_domain));
242
243	if (!sid_name_map_initialized)
244		init_sid_name_map();
245
246	while (sid_name_map[i].name != NULL) {
247		DEBUG(5,("map_domain_name_to_sid: compare: %s\n", sid_name_map[i].name));
248		if (strequal(sid_name_map[i].name, nt_domain)) {
249			fstring sid_str;
250			sid_copy(sid, sid_name_map[i].sid);
251			sid_to_string(sid_str, sid_name_map[i].sid);
252			DEBUG(5,("map_domain_name_to_sid: found %s\n", sid_str));
253			return True;
254		}
255		i++;
256	}
257
258	DEBUG(0,("map_domain_name_to_sid: mapping to %s not found.\n", nt_domain));
259	return False;
260}
261
262/*****************************************************************
263 Check if the SID is our domain SID (S-1-5-21-x-y-z).
264*****************************************************************/
265
266BOOL sid_check_is_domain(const DOM_SID *sid)
267{
268	return sid_equal(sid, get_global_sam_sid());
269}
270
271/*****************************************************************
272 Check if the SID is our domain SID (S-1-5-21-x-y-z).
273*****************************************************************/
274
275BOOL sid_check_is_in_our_domain(const DOM_SID *sid)
276{
277	DOM_SID dom_sid;
278	uint32 rid;
279
280	sid_copy(&dom_sid, sid);
281	sid_split_rid(&dom_sid, &rid);
282
283	return sid_equal(&dom_sid, get_global_sam_sid());
284}
285
286/**************************************************************************
287 Try and map a name to one of the well known SIDs.
288***************************************************************************/
289
290BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char *name)
291{
292	int i, j;
293
294	if (!sid_name_map_initialized)
295		init_sid_name_map();
296
297	DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name));
298
299	for (i=0; sid_name_map[i].sid != NULL; i++) {
300		const known_sid_users *users = sid_name_map[i].known_users;
301
302		if (users == NULL)
303			continue;
304
305		for (j=0; users[j].known_user_name != NULL; j++) {
306			if ( strequal(users[j].known_user_name, name) ) {
307				sid_copy(sid, sid_name_map[i].sid);
308				sid_append_rid(sid, users[j].rid);
309				*use = users[j].sid_name_use;
310				return True;
311			}
312		}
313	}
314
315	return False;
316}
317
318
319