1 /*
2    Unix SMB/CIFS implementation.
3    Privileges handling functions
4    Copyright (C) Jean François Micouleau	1998-2001
5    Copyright (C) Simo Sorce			2002-2003
6    Copyright (C) Gerald (Jerry) Carter          2005
7    Copyright (C) Michael Adam			2007
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 
24 #include "includes.h"
25 #include "lib/privileges.h"
26 #include "dbwrap/dbwrap.h"
27 #include "libcli/security/privileges_private.h"
28 #include "../libcli/security/security.h"
29 #include "passdb.h"
30 
31 #define PRIVPREFIX              "PRIV_"
32 
33 typedef struct {
34 	uint32_t count;
35 	struct dom_sid *list;
36 } SID_LIST;
37 
38 typedef struct {
39 	TALLOC_CTX *mem_ctx;
40 	uint64_t privilege;
41 	SID_LIST sids;
42 } PRIV_SID_LIST;
43 
44 /*
45   interpret an old style SE_PRIV structure
46  */
map_old_SE_PRIV(unsigned char * dptr)47 static uint64_t map_old_SE_PRIV(unsigned char *dptr)
48 {
49 	uint32_t *old_masks = (uint32_t *)dptr;
50 	/*
51 	 * the old privileges code only ever used up to 0x800, except
52 	 * for a special case of 'SE_ALL_PRIVS' which was 0xFFFFFFFF
53 	 */
54 	if (old_masks[0] == 0xFFFFFFFF) {
55 		/* they set all privileges */
56 		return SE_ALL_PRIVS;
57 	}
58 
59 	/* the old code used the machine byte order, but we don't know
60 	 * the byte order of the machine that wrote it. However we can
61 	 * tell what byte order it was by taking advantage of the fact
62 	 * that it only ever use up to 0x800
63 	 */
64 	if (dptr[0] || dptr[1]) {
65 		/* it was little endian */
66 		return IVAL(dptr, 0);
67 	}
68 
69 	/* it was either zero or big-endian */
70 	return RIVAL(dptr, 0);
71 }
72 
73 
get_privileges(const struct dom_sid * sid,uint64_t * mask)74 static bool get_privileges( const struct dom_sid *sid, uint64_t *mask )
75 {
76 	struct db_context *db = get_account_pol_db();
77 	struct dom_sid_buf tmp;
78 	fstring keystr;
79 	TDB_DATA data;
80 	NTSTATUS status;
81 
82 	/* Fail if the admin has not enable privileges */
83 
84 	if ( !lp_enable_privileges() ) {
85 		return False;
86 	}
87 
88 	if ( db == NULL )
89 		return False;
90 
91 	/* PRIV_<SID> (NULL terminated) as the key */
92 
93 	fstr_sprintf(keystr, "%s%s", PRIVPREFIX, dom_sid_str_buf(sid, &tmp));
94 
95 	status = dbwrap_fetch_bystring(db, talloc_tos(), keystr, &data);
96 
97 	if (!NT_STATUS_IS_OK(status)) {
98 		DEBUG(4, ("get_privileges: No privileges assigned to SID "
99 			  "[%s]\n", tmp.buf));
100 		return False;
101 	}
102 
103 	if (data.dsize == 4*4) {
104 		/* it's an old style SE_PRIV structure. */
105 		*mask = map_old_SE_PRIV(data.dptr);
106 	} else {
107 		if (data.dsize != sizeof( uint64_t ) ) {
108 			DEBUG(3, ("get_privileges: Invalid privileges record assigned to SID "
109 				  "[%s]\n", tmp.buf));
110 			return False;
111 		}
112 
113 		*mask = BVAL(data.dptr, 0);
114 	}
115 
116 	TALLOC_FREE(data.dptr);
117 
118 	return True;
119 }
120 
121 /***************************************************************************
122  Store the privilege mask (set) for a given SID
123 ****************************************************************************/
124 
set_privileges(const struct dom_sid * sid,uint64_t mask)125 static bool set_privileges( const struct dom_sid *sid, uint64_t mask )
126 {
127 	struct db_context *db = get_account_pol_db();
128 	uint8_t privbuf[8];
129 	struct dom_sid_buf tmp;
130 	fstring keystr;
131 	TDB_DATA data;
132 
133 	if ( !lp_enable_privileges() )
134 		return False;
135 
136 	if ( db == NULL )
137 		return False;
138 
139 	if ( !sid || (sid->num_auths == 0) ) {
140 		DEBUG(0,("set_privileges: Refusing to store empty SID!\n"));
141 		return False;
142 	}
143 
144 	/* PRIV_<SID> (NULL terminated) as the key */
145 
146 	fstr_sprintf(keystr, "%s%s", PRIVPREFIX, dom_sid_str_buf(sid, &tmp));
147 
148 	/* This writes the 64 bit bitmask out in little endian format */
149 	SBVAL(privbuf,0,mask);
150 
151 	data.dptr  = privbuf;
152 	data.dsize = sizeof(privbuf);
153 
154 	return NT_STATUS_IS_OK(dbwrap_store_bystring(db, keystr, data,
155 						     TDB_REPLACE));
156 }
157 
158 /*********************************************************************
159  get a list of all privileges for all sids in the list
160 *********************************************************************/
161 
get_privileges_for_sids(uint64_t * privileges,struct dom_sid * slist,int scount)162 bool get_privileges_for_sids(uint64_t *privileges, struct dom_sid *slist, int scount)
163 {
164 	uint64_t mask;
165 	int i;
166 	bool found = False;
167 
168 	*privileges = 0;
169 
170 	for ( i=0; i<scount; i++ ) {
171 		struct dom_sid_buf buf;
172 
173 		/* don't add unless we actually have a privilege assigned */
174 
175 		if ( !get_privileges( &slist[i], &mask ) )
176 			continue;
177 
178 		DEBUG(5,("get_privileges_for_sids: sid = %s\nPrivilege "
179 			 "set: 0x%llx\n",
180 			 dom_sid_str_buf(&slist[i], &buf),
181 			 (unsigned long long)mask));
182 
183 		*privileges |= mask;
184 		found = True;
185 	}
186 
187 	return found;
188 }
189 
get_privileges_for_sid_as_set(TALLOC_CTX * mem_ctx,PRIVILEGE_SET ** privileges,struct dom_sid * sid)190 NTSTATUS get_privileges_for_sid_as_set(TALLOC_CTX *mem_ctx, PRIVILEGE_SET **privileges, struct dom_sid *sid)
191 {
192 	uint64_t mask;
193 	if (!get_privileges(sid, &mask)) {
194 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
195 	}
196 
197 	*privileges = talloc_zero(mem_ctx, PRIVILEGE_SET);
198 	if (!*privileges) {
199 		return NT_STATUS_NO_MEMORY;
200 	}
201 
202 	if (!se_priv_to_privilege_set(*privileges, mask)) {
203 		return NT_STATUS_NO_MEMORY;
204 	}
205 	return NT_STATUS_OK;
206 }
207 
208 /*********************************************************************
209  traversal functions for privilege_enumerate_accounts
210 *********************************************************************/
211 
priv_traverse_fn(struct db_record * rec,void * state)212 static int priv_traverse_fn(struct db_record *rec, void *state)
213 {
214 	PRIV_SID_LIST *priv = (PRIV_SID_LIST *)state;
215 	int  prefixlen = strlen(PRIVPREFIX);
216 	struct dom_sid sid;
217 	fstring sid_string;
218 	TDB_DATA key;
219 
220 	key = dbwrap_record_get_key(rec);
221 
222 	/* check we have a PRIV_+SID entry */
223 
224 	if (strncmp((char *)key.dptr, PRIVPREFIX, prefixlen) != 0)
225 		return 0;
226 
227 	/* check to see if we are looking for a particular privilege */
228 
229 	fstrcpy( sid_string, (char *)&(key.dptr[strlen(PRIVPREFIX)]) );
230 
231 	if (priv->privilege != 0) {
232 		uint64_t mask;
233 		TDB_DATA value;
234 
235 		value = dbwrap_record_get_value(rec);
236 
237 		if (value.dsize == 4*4) {
238 			mask = map_old_SE_PRIV(value.dptr);
239 		} else {
240 			if (value.dsize != sizeof( uint64_t ) ) {
241 				DEBUG(3, ("get_privileges: Invalid privileges record assigned to SID "
242 					  "[%s]\n", sid_string));
243 				return 0;
244 			}
245 			mask = BVAL(value.dptr, 0);
246 		}
247 
248 		/* if the SID does not have the specified privilege
249 		   then just return */
250 
251 		if ((mask & priv->privilege) == 0) {
252 			return 0;
253 		}
254 	}
255 
256 	/* this is a last ditch safety check to preventing returning
257 	   and invalid SID (i've somehow run into this on development branches) */
258 
259 	if ( strcmp( "S-0-0", sid_string ) == 0 )
260 		return 0;
261 
262 	if ( !string_to_sid(&sid, sid_string) ) {
263 		DEBUG(0,("travsersal_fn_enum__acct: Could not convert SID [%s]\n",
264 			sid_string));
265 		return 0;
266 	}
267 
268 	if (!NT_STATUS_IS_OK(add_sid_to_array(priv->mem_ctx, &sid,
269 					      &priv->sids.list,
270 					      &priv->sids.count)))
271 	{
272 		return 0;
273 	}
274 
275 	return 0;
276 }
277 
278 /*********************************************************************
279  Retrieve list of privileged SIDs (for _lsa_enumerate_accounts()
280 *********************************************************************/
281 
privilege_enumerate_accounts(struct dom_sid ** sids,int * num_sids)282 NTSTATUS privilege_enumerate_accounts(struct dom_sid **sids, int *num_sids)
283 {
284 	struct db_context *db = get_account_pol_db();
285 	PRIV_SID_LIST priv;
286 	NTSTATUS status;
287 
288 	if (db == NULL) {
289 		return NT_STATUS_ACCESS_DENIED;
290 	}
291 
292 	ZERO_STRUCT(priv);
293 
294 	status = dbwrap_traverse_read(db, priv_traverse_fn, &priv, NULL);
295 	if (!NT_STATUS_IS_OK(status)) {
296 		return status;
297 	}
298 
299 	/* give the memory away; caller will free */
300 
301 	*sids      = priv.sids.list;
302 	*num_sids  = priv.sids.count;
303 
304 	return NT_STATUS_OK;
305 }
306 
307 /*********************************************************************
308  Retrieve list of SIDs granted a particular privilege
309 *********************************************************************/
310 
privilege_enum_sids(enum sec_privilege privilege,TALLOC_CTX * mem_ctx,struct dom_sid ** sids,int * num_sids)311 NTSTATUS privilege_enum_sids(enum sec_privilege privilege, TALLOC_CTX *mem_ctx,
312 			     struct dom_sid **sids, int *num_sids)
313 {
314 	struct db_context *db = get_account_pol_db();
315 	PRIV_SID_LIST priv;
316 	NTSTATUS status;
317 
318 	if (db == NULL) {
319 		return NT_STATUS_ACCESS_DENIED;
320 	}
321 
322 	ZERO_STRUCT(priv);
323 
324 	priv.privilege = sec_privilege_mask(privilege);
325 	priv.mem_ctx = mem_ctx;
326 
327 	status = dbwrap_traverse_read(db, priv_traverse_fn, &priv, NULL);
328 	if (!NT_STATUS_IS_OK(status)) {
329 		return status;
330 	}
331 
332 	/* give the memory away; caller will free */
333 
334 	*sids      = priv.sids.list;
335 	*num_sids  = priv.sids.count;
336 
337 	return NT_STATUS_OK;
338 }
339 
340 /***************************************************************************
341  Add privilege to sid
342 ****************************************************************************/
343 
grant_privilege_bitmap(const struct dom_sid * sid,const uint64_t priv_mask)344 static bool grant_privilege_bitmap(const struct dom_sid *sid, const uint64_t priv_mask)
345 {
346 	uint64_t old_mask, new_mask;
347 	struct dom_sid_buf buf;
348 
349 	ZERO_STRUCT( old_mask );
350 	ZERO_STRUCT( new_mask );
351 
352 	if ( get_privileges( sid, &old_mask ) )
353 		new_mask = old_mask;
354 	else
355 		new_mask = 0;
356 
357 	new_mask |= priv_mask;
358 
359 	DEBUG(10,("grant_privilege: %s\n", dom_sid_str_buf(sid, &buf)));
360 
361 	DEBUGADD( 10, ("original privilege mask: 0x%llx\n", (unsigned long long)new_mask));
362 
363 	DEBUGADD( 10, ("new privilege mask:      0x%llx\n", (unsigned long long)new_mask));
364 
365 	return set_privileges( sid, new_mask );
366 }
367 
368 /*********************************************************************
369  Add a privilege based on its name
370 *********************************************************************/
371 
grant_privilege_by_name(const struct dom_sid * sid,const char * name)372 bool grant_privilege_by_name(const struct dom_sid *sid, const char *name)
373 {
374 	uint64_t mask;
375 
376 	if (! se_priv_from_name(name, &mask)) {
377         	DEBUG(3, ("grant_privilege_by_name: "
378 			  "No Such Privilege Found (%s)\n", name));
379 		return False;
380 	}
381 
382 	return grant_privilege_bitmap( sid, mask );
383 }
384 
385 /***************************************************************************
386  Grant a privilege set (list of LUID values) from a sid
387 ****************************************************************************/
388 
grant_privilege_set(const struct dom_sid * sid,struct lsa_PrivilegeSet * set)389 bool grant_privilege_set(const struct dom_sid *sid, struct lsa_PrivilegeSet *set)
390 {
391 	uint64_t privilege_mask;
392 	if (!privilege_set_to_se_priv(&privilege_mask, set)) {
393 		return false;
394 	}
395 	return grant_privilege_bitmap(sid, privilege_mask);
396 }
397 
398 /***************************************************************************
399  Remove privilege from sid
400 ****************************************************************************/
401 
revoke_privilege_bitmap(const struct dom_sid * sid,const uint64_t priv_mask)402 static bool revoke_privilege_bitmap(const struct dom_sid *sid, const uint64_t priv_mask)
403 {
404 	uint64_t mask;
405 	struct dom_sid_buf buf;
406 
407 	/* if the user has no privileges, then we can't revoke any */
408 
409 	if ( !get_privileges( sid, &mask ) )
410 		return True;
411 
412 	DEBUG(10,("revoke_privilege: %s\n", dom_sid_str_buf(sid, &buf)));
413 
414 	DEBUGADD( 10, ("original privilege mask: 0x%llx\n", (unsigned long long)mask));
415 
416 	mask &= ~priv_mask;
417 
418 	DEBUGADD( 10, ("new privilege mask:      0x%llx\n", (unsigned long long)mask));
419 
420 	return set_privileges( sid, mask );
421 }
422 
423 /***************************************************************************
424  Remove a privilege set (list of LUID values) from a sid
425 ****************************************************************************/
426 
revoke_privilege_set(const struct dom_sid * sid,struct lsa_PrivilegeSet * set)427 bool revoke_privilege_set(const struct dom_sid *sid, struct lsa_PrivilegeSet *set)
428 {
429 	uint64_t privilege_mask;
430 	if (!privilege_set_to_se_priv(&privilege_mask, set)) {
431 		return false;
432 	}
433 	return revoke_privilege_bitmap(sid, privilege_mask);
434 }
435 
436 /*********************************************************************
437  Revoke all privileges
438 *********************************************************************/
439 
revoke_all_privileges(const struct dom_sid * sid)440 bool revoke_all_privileges( const struct dom_sid *sid )
441 {
442 	return revoke_privilege_bitmap( sid, SE_ALL_PRIVS);
443 }
444 
445 /*********************************************************************
446  Add a privilege based on its name
447 *********************************************************************/
448 
revoke_privilege_by_name(const struct dom_sid * sid,const char * name)449 bool revoke_privilege_by_name(const struct dom_sid *sid, const char *name)
450 {
451 	uint64_t mask;
452 
453 	if (! se_priv_from_name(name, &mask)) {
454         	DEBUG(3, ("revoke_privilege_by_name: "
455 			  "No Such Privilege Found (%s)\n", name));
456         	return False;
457 	}
458 
459 	return revoke_privilege_bitmap(sid, mask);
460 
461 }
462 
463 /***************************************************************************
464  Retrieve the SIDs assigned to a given privilege
465 ****************************************************************************/
466 
privilege_create_account(const struct dom_sid * sid)467 NTSTATUS privilege_create_account(const struct dom_sid *sid )
468 {
469 	return ( grant_privilege_bitmap(sid, 0) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL);
470 }
471 
472 /***************************************************************************
473  Delete a privileged account
474 ****************************************************************************/
475 
privilege_delete_account(const struct dom_sid * sid)476 NTSTATUS privilege_delete_account(const struct dom_sid *sid)
477 {
478 	struct db_context *db = get_account_pol_db();
479 	struct dom_sid_buf tmp;
480 	fstring keystr;
481 
482 	if (!lp_enable_privileges()) {
483 		return NT_STATUS_OK;
484 	}
485 
486 	if (!db) {
487 		return NT_STATUS_INVALID_HANDLE;
488 	}
489 
490 	if (!sid || (sid->num_auths == 0)) {
491 		return NT_STATUS_INVALID_SID;
492 	}
493 
494 	/* PRIV_<SID> (NULL terminated) as the key */
495 
496 	fstr_sprintf(keystr, "%s%s", PRIVPREFIX, dom_sid_str_buf(sid, &tmp));
497 
498 	return dbwrap_delete_bystring(db, keystr);
499 }
500 
501 /*******************************************************************
502 *******************************************************************/
503 
is_privileged_sid(const struct dom_sid * sid)504 bool is_privileged_sid( const struct dom_sid *sid )
505 {
506 	uint64_t mask;
507 
508 	return get_privileges( sid, &mask );
509 }
510 
511 /*******************************************************************
512 *******************************************************************/
513 
grant_all_privileges(const struct dom_sid * sid)514 bool grant_all_privileges( const struct dom_sid *sid )
515 {
516 	uint64_t mask;
517 
518 	se_priv_put_all_privileges(&mask);
519 
520 	return grant_privilege_bitmap( sid, mask );
521 }
522