054ba57e37c544a18a02437cdea5a2b133abdf07
[abartlet/samba.git/.git] / libcli / security / privileges.c
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    Copyright (C) Andrew Bartlett                2010
9    Copyright (C) Andrew Tridgell                2004
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 /*
26  * Basic privileges functions (mask-operations and conversion
27  * functions between the different formats (se_priv, privset, luid)
28  * moved here * from lib/privileges.c to minimize linker deps.
29  *
30  * generally SID- and LUID-related code is left in lib/privileges.c
31  *
32  * some extra functions to hide privs array from lib/privileges.c
33  */
34
35 #include "includes.h"
36 #include "libcli/security/privileges.h"
37 #include "librpc/gen_ndr/security.h"
38
39 /* The use of strcasecmp here is safe, all the comparison strings are ASCII */
40 #undef strcasecmp
41
42 const uint64_t se_priv_all         = SE_ALL_PRIVS;
43
44 /* Define variables for all privileges so we can use the
45    uint64_t* in the various se_priv_XXX() functions */
46
47 const uint64_t se_priv_none       = SE_NONE;
48 const uint64_t se_machine_account = SE_MACHINE_ACCOUNT;
49 const uint64_t se_print_operator  = SE_PRINT_OPERATOR;
50 const uint64_t se_add_users       = SE_ADD_USERS;
51 const uint64_t se_disk_operators  = SE_DISK_OPERATOR;
52 const uint64_t se_remote_shutdown = SE_REMOTE_SHUTDOWN;
53 const uint64_t se_restore         = SE_RESTORE;
54 const uint64_t se_take_ownership  = SE_TAKE_OWNERSHIP;
55
56 #define NUM_SHORT_LIST_PRIVS 8
57
58 static const struct {
59         enum sec_privilege luid;
60         uint64_t privilege_mask;
61         const char *name;
62         const char *description;
63 } privs[] = {
64
65         {SEC_PRIV_MACHINE_ACCOUNT, SE_MACHINE_ACCOUNT,   "SeMachineAccountPrivilege",   "Add machines to domain"},
66         {SEC_PRIV_TAKE_OWNERSHIP,  SE_TAKE_OWNERSHIP,    "SeTakeOwnershipPrivilege",    "Take ownership of files or other objects"},
67         {SEC_PRIV_BACKUP,          SE_BACKUP,            "SeBackupPrivilege",           "Back up files and directories"},
68         {SEC_PRIV_RESTORE,         SE_RESTORE,           "SeRestorePrivilege",          "Restore files and directories"},
69         {SEC_PRIV_REMOTE_SHUTDOWN, SE_REMOTE_SHUTDOWN,   "SeRemoteShutdownPrivilege",   "Force shutdown from a remote system"},
70
71         {SEC_PRIV_PRINT_OPERATOR,  SE_PRINT_OPERATOR,    "SePrintOperatorPrivilege",    "Manage printers"},
72         {SEC_PRIV_ADD_USERS,       SE_ADD_USERS,         "SeAddUsersPrivilege",         "Add users and groups to the domain"},
73         {SEC_PRIV_DISK_OPERATOR,   SE_DISK_OPERATOR,     "SeDiskOperatorPrivilege",     "Manage disk shares"},
74
75         /* The list from here on was not displayed in the code from
76          * source3/ with the comment that usrmgr will display these
77          * next 2 twice if you include them.  The source4/ code has
78          * always included them, but they do not appear in Windows
79          * 2008 R2.
80
81            Finally, the parameter 'short_list' determines if the short
82            or full list (including many other privileges) is used */
83
84         {SEC_PRIV_SECURITY,
85          SE_SECURITY,
86          "SeSecurityPrivilege",
87         "System security"},
88
89         {SEC_PRIV_SYSTEMTIME,
90          SE_SYSTEMTIME,
91          "SeSystemtimePrivilege",
92         "Set the system clock"},
93
94         {SEC_PRIV_SHUTDOWN,
95          SE_SHUTDOWN,
96          "SeShutdownPrivilege",
97         "Shutdown the system"},
98
99         {SEC_PRIV_DEBUG,
100          SE_DEBUG,
101          "SeDebugPrivilege",
102         "Debug processes"},
103
104         {SEC_PRIV_SYSTEM_ENVIRONMENT,
105          SE_SYSTEM_ENVIRONMENT,
106          "SeSystemEnvironmentPrivilege",
107         "Modify system environment"},
108
109         {SEC_PRIV_SYSTEM_PROFILE,
110          SE_SYSTEM_PROFILE,
111          "SeSystemProfilePrivilege",
112         "Profile the system"},
113
114         {SEC_PRIV_PROFILE_SINGLE_PROCESS,
115          SE_PROFILE_SINGLE_PROCESS,
116          "SeProfileSingleProcessPrivilege",
117         "Profile one process"},
118
119         {SEC_PRIV_INCREASE_BASE_PRIORITY,
120          SE_INCREASE_BASE_PRIORITY,
121          "SeIncreaseBasePriorityPrivilege",
122          "Increase base priority"},
123
124         {SEC_PRIV_LOAD_DRIVER,
125          SE_LOAD_DRIVER,
126          "SeLoadDriverPrivilege",
127         "Load drivers"},
128
129         {SEC_PRIV_CREATE_PAGEFILE,
130          SE_CREATE_PAGEFILE,
131          "SeCreatePagefilePrivilege",
132         "Create page files"},
133
134         {SEC_PRIV_INCREASE_QUOTA,
135          SE_INCREASE_QUOTA,
136          "SeIncreaseQuotaPrivilege",
137         "Increase quota"},
138
139         {SEC_PRIV_CHANGE_NOTIFY,
140          SE_CHANGE_NOTIFY,
141          "SeChangeNotifyPrivilege",
142         "Register for change notify"},
143
144         {SEC_PRIV_UNDOCK,
145          SE_UNDOCK,
146          "SeUndockPrivilege",
147         "Undock devices"},
148
149         {SEC_PRIV_MANAGE_VOLUME,
150          SE_MANAGE_VOLUME,
151          "SeManageVolumePrivilege",
152         "Manage system volumes"},
153
154         {SEC_PRIV_IMPERSONATE,
155          SE_IMPERSONATE,
156          "SeImpersonatePrivilege",
157         "Impersonate users"},
158
159         {SEC_PRIV_CREATE_GLOBAL,
160          SE_CREATE_GLOBAL,
161          "SeCreateGlobalPrivilege",
162         "Create global"},
163
164         {SEC_PRIV_ENABLE_DELEGATION,
165          SE_ENABLE_DELEGATION,
166          "SeEnableDelegationPrivilege",
167         "Enable Delegation"},
168
169         {SEC_PRIV_INTERACTIVE_LOGON,
170          SE_INTERACTIVE_LOGON,
171          "SeInteractiveLogonRight",
172         "Interactive logon"},
173
174         {SEC_PRIV_NETWORK_LOGON,
175          SE_NETWORK_LOGON,
176          "SeNetworkLogonRight",
177         "Network logon"},
178
179         {SEC_PRIV_REMOTE_INTERACTIVE_LOGON,
180          SE_REMOTE_INTERACTIVE_LOGON,
181          "SeRemoteInteractiveLogonRight",
182         "Remote Interactive logon"}
183 };
184
185 /***************************************************************************
186  copy an uint64_t privilege bitmap
187 ****************************************************************************/
188
189 bool se_priv_copy( uint64_t *dst, const uint64_t *src )
190 {
191         if ( !dst || !src )
192                 return false;
193
194         *dst = *src;
195
196         return true;
197 }
198
199 /***************************************************************************
200  put all valid privileges into a mask
201 ****************************************************************************/
202
203 bool se_priv_put_all_privileges(uint64_t *privilege_mask)
204 {
205         int i;
206         uint32_t num_privs = ARRAY_SIZE(privs);
207
208         if (!se_priv_copy(privilege_mask, &se_priv_none)) {
209                 return false;
210         }
211         for ( i=0; i<num_privs; i++ ) {
212                 se_priv_add(privilege_mask, &privs[i].privilege_mask);
213         }
214         return true;
215 }
216
217 /***************************************************************************
218  combine 2 uint64_t privilege bitmaps and store the resulting set in new_mask
219 ****************************************************************************/
220
221 void se_priv_add( uint64_t *privilege_mask, const uint64_t *addpriv )
222 {
223         *privilege_mask |= *addpriv;
224 }
225
226 /***************************************************************************
227  remove one uint64_t privileges bitmap from another and store the resulting set
228  in privilege_mask
229 ****************************************************************************/
230
231 void se_priv_remove( uint64_t *privilege_mask, const uint64_t *removepriv )
232 {
233         *privilege_mask &= ~*removepriv;
234 }
235
236 /***************************************************************************
237  invert a given uint64_t and store the set in new_mask
238 ****************************************************************************/
239
240 static void se_priv_invert( uint64_t *new_mask, const uint64_t *privilege_mask )
241 {
242         uint64_t allprivs;
243
244         se_priv_copy( &allprivs, &se_priv_all );
245         se_priv_remove( &allprivs, privilege_mask );
246         se_priv_copy( new_mask, &allprivs );
247 }
248
249 /***************************************************************************
250  check if 2 privilege bitmaps (as uint64_t) are equal
251 ****************************************************************************/
252
253 bool se_priv_equal( const uint64_t *privilege_mask1, const uint64_t *privilege_mask2 )
254 {
255         return *privilege_mask1 == *privilege_mask2;
256 }
257
258 /***************************************************************************
259  check if a uint64_t has any assigned privileges
260 ****************************************************************************/
261
262 static bool se_priv_empty( const uint64_t *privilege_mask )
263 {
264         uint64_t p1;
265
266         se_priv_copy( &p1, privilege_mask );
267
268         p1 &= se_priv_all;
269
270         return se_priv_equal( &p1, &se_priv_none );
271 }
272
273 /*********************************************************************
274  Lookup the uint64_t bitmask value for a privilege name
275 *********************************************************************/
276
277 bool se_priv_from_name( const char *name, uint64_t *privilege_mask )
278 {
279         int i;
280
281         uint32_t num_privs = ARRAY_SIZE(privs);
282
283         for ( i=0; i<num_privs; i++ ) {
284                 if ( strequal( privs[i].name, name ) ) {
285                         se_priv_copy( privilege_mask, &privs[i].privilege_mask );
286                         return true;
287                 }
288         }
289
290         return false;
291 }
292
293 /****************************************************************************
294  check if the privilege (by bitmask) is in the privilege list
295 ****************************************************************************/
296
297 bool is_privilege_assigned(const uint64_t *privileges,
298                            const uint64_t *check)
299 {
300         uint64_t p1, p2;
301
302         if ( !privileges || !check )
303                 return false;
304
305         /* everyone has privileges if you aren't checking for any */
306
307         if ( se_priv_empty( check ) ) {
308                 DEBUG(1,("is_privilege_assigned: no privileges in check_mask!\n"));
309                 return true;
310         }
311
312         se_priv_copy( &p1, check );
313
314         /* invert the uint64_t we want to check for and remove that from the
315            original set.  If we are left with the uint64_t we are checking
316            for then return true */
317
318         se_priv_invert( &p1, check );
319         se_priv_copy( &p2, privileges );
320         se_priv_remove( &p2, &p1 );
321
322         return se_priv_equal( &p2, check );
323 }
324
325 /****************************************************************************
326  check if the any of the privileges (by bitmask) is in the privilege list
327 ****************************************************************************/
328
329 static bool is_any_privilege_assigned( uint64_t *privileges, const uint64_t *check )
330 {
331         uint64_t p1, p2;
332
333         if ( !privileges || !check )
334                 return false;
335
336         /* everyone has privileges if you aren't checking for any */
337
338         if ( se_priv_empty( check ) ) {
339                 DEBUG(1,("is_any_privilege_assigned: no privileges in check_mask!\n"));
340                 return true;
341         }
342
343         se_priv_copy( &p1, check );
344
345         /* invert the uint64_t we want to check for and remove that from the
346            original set.  If we are left with the uint64_t we are checking
347            for then return true */
348
349         se_priv_invert( &p1, check );
350         se_priv_copy( &p2, privileges );
351         se_priv_remove( &p2, &p1 );
352
353         /* see if we have any bits left */
354
355         return !se_priv_empty( &p2 );
356 }
357
358 /*********************************************************************
359  Generate the struct lsa_LUIDAttribute structure based on a bitmask
360 *********************************************************************/
361
362 const char* get_privilege_dispname( const char *name )
363 {
364         int i;
365
366         uint32_t num_privs = ARRAY_SIZE(privs);
367
368         if (!name) {
369                 return NULL;
370         }
371
372         for ( i=0; i<num_privs; i++ ) {
373                 if ( strequal( privs[i].name, name ) ) {
374                         return privs[i].description;
375                 }
376         }
377
378         return NULL;
379 }
380
381 /****************************************************************************
382  initialise a privilege list and set the talloc context
383  ****************************************************************************/
384
385 /****************************************************************************
386  Does the user have the specified privilege ?  We only deal with one privilege
387  at a time here.
388 *****************************************************************************/
389
390 bool user_has_privileges(const struct security_token *token, const uint64_t *privilege_bit)
391 {
392         if ( !token )
393                 return false;
394
395         return is_privilege_assigned( &token->privilege_mask, privilege_bit );
396 }
397
398 /****************************************************************************
399  Does the user have any of the specified privileges ?  We only deal with one privilege
400  at a time here.
401 *****************************************************************************/
402
403 bool user_has_any_privilege(struct security_token *token, const uint64_t *privilege_mask)
404 {
405         if ( !token )
406                 return false;
407
408         return is_any_privilege_assigned( &token->privilege_mask, privilege_mask );
409 }
410
411 /*******************************************************************
412  return the number of elements in the 'short' privlege array (traditional source3 behaviour)
413 *******************************************************************/
414
415 int num_privileges_in_short_list( void )
416 {
417         return NUM_SHORT_LIST_PRIVS;
418 }
419
420 /****************************************************************************
421  Convert a LUID to a named string
422 ****************************************************************************/
423
424 const char *luid_to_privilege_name(const struct lsa_LUID *set)
425 {
426         int i;
427
428         uint32_t num_privs = ARRAY_SIZE(privs);
429
430         if (set->high != 0)
431                 return NULL;
432
433         for ( i=0; i<num_privs; i++ ) {
434                 if ( set->low == privs[i].luid ) {
435                         return privs[i].name;
436                 }
437         }
438
439         return NULL;
440 }
441
442
443 /****************************************************************************
444  add a privilege to a privilege array
445  ****************************************************************************/
446
447 static bool privilege_set_add(PRIVILEGE_SET *priv_set, struct lsa_LUIDAttribute set)
448 {
449         struct lsa_LUIDAttribute *new_set;
450
451         /* we can allocate memory to add the new privilege */
452
453         new_set = talloc_realloc(priv_set->mem_ctx, priv_set->set, struct lsa_LUIDAttribute, priv_set->count + 1);
454         if ( !new_set ) {
455                 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
456                 return false;
457         }
458
459         new_set[priv_set->count].luid.high = set.luid.high;
460         new_set[priv_set->count].luid.low = set.luid.low;
461         new_set[priv_set->count].attribute = set.attribute;
462
463         priv_set->count++;
464         priv_set->set = new_set;
465
466         return true;
467 }
468
469 /*******************************************************************
470 *******************************************************************/
471
472 bool se_priv_to_privilege_set( PRIVILEGE_SET *set, uint64_t privilege_mask )
473 {
474         int i;
475         uint32_t num_privs = ARRAY_SIZE(privs);
476         struct lsa_LUIDAttribute luid;
477
478         luid.attribute = 0;
479         luid.luid.high = 0;
480
481         for ( i=0; i<num_privs; i++ ) {
482                 if ((privilege_mask & privs[i].privilege_mask) == 0)
483                         continue;
484
485                 luid.luid.high = 0;
486                 luid.luid.low = privs[i].luid;
487
488                 if ( !privilege_set_add( set, luid ) )
489                         return false;
490         }
491
492         return true;
493 }
494
495 /*******************************************************************
496 *******************************************************************/
497
498 static bool luid_to_se_priv( struct lsa_LUID *luid, uint64_t *privilege_mask )
499 {
500         int i;
501         uint32_t num_privs = ARRAY_SIZE(privs);
502
503         for ( i=0; i<num_privs; i++ ) {
504                 if ( luid->low == privs[i].luid ) {
505                         se_priv_copy( privilege_mask, &privs[i].privilege_mask );
506                         return true;
507                 }
508         }
509
510         return false;
511 }
512
513 /*******************************************************************
514 *******************************************************************/
515
516 bool privilege_set_to_se_priv( uint64_t *privilege_mask, struct lsa_PrivilegeSet *privset )
517 {
518         int i;
519
520         ZERO_STRUCTP( privilege_mask );
521
522         for ( i=0; i<privset->count; i++ ) {
523                 uint64_t r;
524
525                 /* sanity check for invalid privilege.  we really
526                    only care about the low 32 bits */
527
528                 if ( privset->set[i].luid.high != 0 )
529                         return false;
530
531                 if ( luid_to_se_priv( &privset->set[i].luid, &r ) )
532                         se_priv_add( privilege_mask, &r );
533         }
534
535         return true;
536 }
537
538 /*
539   map a privilege id to the wire string constant
540 */
541 const char *sec_privilege_name(enum sec_privilege privilege)
542 {
543         int i;
544         for (i=0;i<ARRAY_SIZE(privs);i++) {
545                 if (privs[i].luid == privilege) {
546                         return privs[i].name;
547                 }
548         }
549         return NULL;
550 }
551
552 /*
553   map a privilege id to a privilege display name. Return NULL if not found
554
555   TODO: this should use language mappings
556 */
557 const char *sec_privilege_display_name(enum sec_privilege privilege, uint16_t *language)
558 {
559         int i;
560         if (privilege < 1 || privilege > 64) {
561                 return NULL;
562         }
563         for (i=0;i<ARRAY_SIZE(privs);i++) {
564                 if (privs[i].luid == privilege) {
565                         return privs[i].description;
566                 }
567         }
568         return NULL;
569 }
570
571 /*
572   map a privilege name to a privilege id. Return -1 if not found
573 */
574 enum sec_privilege sec_privilege_id(const char *name)
575 {
576         int i;
577         for (i=0;i<ARRAY_SIZE(privs);i++) {
578                 if (strcasecmp(privs[i].name, name) == 0) {
579                         return privs[i].luid;
580                 }
581         }
582         return -1;
583 }
584
585 /*
586   map a privilege name to a privilege id. Return -1 if not found
587 */
588 enum sec_privilege sec_privilege_from_mask(uint64_t mask)
589 {
590         int i;
591         for (i=0;i<ARRAY_SIZE(privs);i++) {
592                 if (privs[i].privilege_mask == mask) {
593                         return privs[i].luid;
594                 }
595         }
596         return -1;
597 }
598
599 /*
600   assist in walking the table of privileges - return the LUID (low 32 bits) by index
601 */
602 enum sec_privilege sec_privilege_from_index(int idx)
603 {
604         if (idx >= 0 && idx<ARRAY_SIZE(privs)) {
605                 return privs[idx].luid;
606         }
607         return -1;
608 }
609
610 /*
611   assist in walking the table of privileges - return the string constant by index
612 */
613 const char *sec_privilege_name_from_index(int idx)
614 {
615         if (idx >= 0 && idx<ARRAY_SIZE(privs)) {
616                 return privs[idx].name;
617         }
618         return NULL;
619 }
620
621
622 /*
623   return a privilege mask given a privilege id
624 */
625 static uint64_t sec_privilege_mask(enum sec_privilege privilege)
626 {
627         int i;
628         for (i=0;i<ARRAY_SIZE(privs);i++) {
629                 if (privs[i].luid == privilege) {
630                         return privs[i].privilege_mask;
631                 }
632         }
633
634         return 0;
635 }
636
637
638 /*
639   return true if a security_token has a particular privilege bit set
640 */
641 bool security_token_has_privilege(const struct security_token *token, enum sec_privilege privilege)
642 {
643         uint64_t mask;
644
645         mask = sec_privilege_mask(privilege);
646         if (mask == 0) {
647                 return false;
648         }
649
650         if (token->privilege_mask & mask) {
651                 return true;
652         }
653         return false;
654 }
655
656 /*
657   set a bit in the privilege mask
658 */
659 void security_token_set_privilege(struct security_token *token, enum sec_privilege privilege)
660 {
661         /* Relies on the fact that an invalid privilage will return 0, so won't change this */
662         token->privilege_mask |= sec_privilege_mask(privilege);
663 }
664
665 void security_token_debug_privileges(int dbg_lev, const struct security_token *token)
666 {
667         DEBUGADD(dbg_lev, (" Privileges (0x%16llX):\n",
668                             (unsigned long long) token->privilege_mask));
669
670         if (token->privilege_mask) {
671                 int i = 0;
672                 uint64_t mask;
673                 for (mask = 1; mask != 0; mask = mask << 1) {
674                         if (token->privilege_mask & mask) {
675                                 enum sec_privilege privilege = sec_privilege_from_mask(mask);
676                                 DEBUGADD(dbg_lev, ("  Privilege[%3lu]: %s\n", (unsigned long)i++,
677                                         sec_privilege_name(privilege)));
678                         }
679                 }
680         }
681 }