4815d1837c0c965cf77605a702ba264a418d3c47
[samba.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 PRIVS privs[] = {
57 #if 0   /* usrmgr will display these twice if you include them.  We don't
58            use them but we'll keep the bitmasks reserved in privileges.h anyways */
59
60         {0x0,                      SE_NETWORK_LOGON,     "SeNetworkLogonRight",         "Access this computer from network"},
61         {0x0,                      SE_INTERACTIVE_LOGON, "SeInteractiveLogonRight",     "Log on locally"},
62         {0x0,                      SE_BATCH_LOGON,       "SeBatchLogonRight",           "Log on as a batch job"},
63         {0x0,                      SE_SERVICE_LOGON,     "SeServiceLogonRight",         "Log on as a service"},
64 #endif
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 };
76
77 /***************************************************************************
78  copy an uint64_t privilege bitmap
79 ****************************************************************************/
80
81 bool se_priv_copy( uint64_t *dst, const uint64_t *src )
82 {
83         if ( !dst || !src )
84                 return false;
85
86         *dst = *src;
87
88         return true;
89 }
90
91 /***************************************************************************
92  put all valid privileges into a mask
93 ****************************************************************************/
94
95 bool se_priv_put_all_privileges(uint64_t *privilege_mask)
96 {
97         int i;
98         uint32_t num_privs = ARRAY_SIZE(privs);
99
100         if (!se_priv_copy(privilege_mask, &se_priv_none)) {
101                 return false;
102         }
103         for ( i=0; i<num_privs; i++ ) {
104                 se_priv_add(privilege_mask, &privs[i].privilege_mask);
105         }
106         return true;
107 }
108
109 /***************************************************************************
110  combine 2 uint64_t privilege bitmaps and store the resulting set in new_mask
111 ****************************************************************************/
112
113 void se_priv_add( uint64_t *privilege_mask, const uint64_t *addpriv )
114 {
115         *privilege_mask |= *addpriv;
116 }
117
118 /***************************************************************************
119  remove one uint64_t privileges bitmap from another and store the resulting set
120  in privilege_mask
121 ****************************************************************************/
122
123 void se_priv_remove( uint64_t *privilege_mask, const uint64_t *removepriv )
124 {
125         *privilege_mask &= ~*removepriv;
126 }
127
128 /***************************************************************************
129  invert a given uint64_t and store the set in new_mask
130 ****************************************************************************/
131
132 static void se_priv_invert( uint64_t *new_mask, const uint64_t *privilege_mask )
133 {
134         uint64_t allprivs;
135
136         se_priv_copy( &allprivs, &se_priv_all );
137         se_priv_remove( &allprivs, privilege_mask );
138         se_priv_copy( new_mask, &allprivs );
139 }
140
141 /***************************************************************************
142  check if 2 privilege bitmaps (as uint64_t) are equal
143 ****************************************************************************/
144
145 bool se_priv_equal( const uint64_t *privilege_mask1, const uint64_t *privilege_mask2 )
146 {
147         return *privilege_mask1 == *privilege_mask2;
148 }
149
150 /***************************************************************************
151  check if a uint64_t has any assigned privileges
152 ****************************************************************************/
153
154 static bool se_priv_empty( const uint64_t *privilege_mask )
155 {
156         uint64_t p1;
157
158         se_priv_copy( &p1, privilege_mask );
159
160         p1 &= se_priv_all;
161
162         return se_priv_equal( &p1, &se_priv_none );
163 }
164
165 /*********************************************************************
166  Lookup the uint64_t bitmask value for a privilege name
167 *********************************************************************/
168
169 bool se_priv_from_name( const char *name, uint64_t *privilege_mask )
170 {
171         int i;
172
173         uint32_t num_privs = ARRAY_SIZE(privs);
174
175         for ( i=0; i<num_privs; i++ ) {
176                 if ( strequal( privs[i].name, name ) ) {
177                         se_priv_copy( privilege_mask, &privs[i].privilege_mask );
178                         return true;
179                 }
180         }
181
182         return false;
183 }
184
185 /****************************************************************************
186  check if the privilege (by bitmask) is in the privilege list
187 ****************************************************************************/
188
189 bool is_privilege_assigned(const uint64_t *privileges,
190                            const uint64_t *check)
191 {
192         uint64_t p1, p2;
193
194         if ( !privileges || !check )
195                 return false;
196
197         /* everyone has privileges if you aren't checking for any */
198
199         if ( se_priv_empty( check ) ) {
200                 DEBUG(1,("is_privilege_assigned: no privileges in check_mask!\n"));
201                 return true;
202         }
203
204         se_priv_copy( &p1, check );
205
206         /* invert the uint64_t we want to check for and remove that from the
207            original set.  If we are left with the uint64_t we are checking
208            for then return true */
209
210         se_priv_invert( &p1, check );
211         se_priv_copy( &p2, privileges );
212         se_priv_remove( &p2, &p1 );
213
214         return se_priv_equal( &p2, check );
215 }
216
217 /****************************************************************************
218  check if the any of the privileges (by bitmask) is in the privilege list
219 ****************************************************************************/
220
221 static bool is_any_privilege_assigned( uint64_t *privileges, const uint64_t *check )
222 {
223         uint64_t p1, p2;
224
225         if ( !privileges || !check )
226                 return false;
227
228         /* everyone has privileges if you aren't checking for any */
229
230         if ( se_priv_empty( check ) ) {
231                 DEBUG(1,("is_any_privilege_assigned: no privileges in check_mask!\n"));
232                 return true;
233         }
234
235         se_priv_copy( &p1, check );
236
237         /* invert the uint64_t we want to check for and remove that from the
238            original set.  If we are left with the uint64_t we are checking
239            for then return true */
240
241         se_priv_invert( &p1, check );
242         se_priv_copy( &p2, privileges );
243         se_priv_remove( &p2, &p1 );
244
245         /* see if we have any bits left */
246
247         return !se_priv_empty( &p2 );
248 }
249
250 /*********************************************************************
251  Generate the struct lsa_LUIDAttribute structure based on a bitmask
252 *********************************************************************/
253
254 const char* get_privilege_dispname( const char *name )
255 {
256         int i;
257
258         uint32_t num_privs = ARRAY_SIZE(privs);
259
260         if (!name) {
261                 return NULL;
262         }
263
264         for ( i=0; i<num_privs; i++ ) {
265                 if ( strequal( privs[i].name, name ) ) {
266                         return privs[i].description;
267                 }
268         }
269
270         return NULL;
271 }
272
273 /****************************************************************************
274  initialise a privilege list and set the talloc context
275  ****************************************************************************/
276
277 /****************************************************************************
278  Does the user have the specified privilege ?  We only deal with one privilege
279  at a time here.
280 *****************************************************************************/
281
282 bool user_has_privileges(const struct security_token *token, const uint64_t *privilege_bit)
283 {
284         if ( !token )
285                 return false;
286
287         return is_privilege_assigned( &token->privilege_mask, privilege_bit );
288 }
289
290 /****************************************************************************
291  Does the user have any of the specified privileges ?  We only deal with one privilege
292  at a time here.
293 *****************************************************************************/
294
295 bool user_has_any_privilege(struct security_token *token, const uint64_t *privilege_mask)
296 {
297         if ( !token )
298                 return false;
299
300         return is_any_privilege_assigned( &token->privilege_mask, privilege_mask );
301 }
302
303 /*******************************************************************
304  return the number of elements in the privlege array
305 *******************************************************************/
306
307 int count_all_privileges( void )
308 {
309         return ARRAY_SIZE(privs);
310 }
311
312
313 /*********************************************************************
314  Generate the struct lsa_LUIDAttribute structure based on a bitmask
315  The assumption here is that the privilege has already been validated
316  so we are guaranteed to find it in the list.
317 *********************************************************************/
318
319 enum sec_privilege get_privilege_luid( uint64_t *privilege_mask )
320 {
321         int i;
322
323         uint32_t num_privs = ARRAY_SIZE(privs);
324
325         for ( i=0; i<num_privs; i++ ) {
326                 if ( se_priv_equal( &privs[i].privilege_mask, privilege_mask ) ) {
327                         return privs[i].luid;
328                 }
329         }
330
331         return 0;
332 }
333
334 /****************************************************************************
335  Convert a LUID to a named string
336 ****************************************************************************/
337
338 const char *luid_to_privilege_name(const struct lsa_LUID *set)
339 {
340         int i;
341
342         uint32_t num_privs = ARRAY_SIZE(privs);
343
344         if (set->high != 0)
345                 return NULL;
346
347         for ( i=0; i<num_privs; i++ ) {
348                 if ( set->low == privs[i].luid ) {
349                         return privs[i].name;
350                 }
351         }
352
353         return NULL;
354 }
355
356
357 /****************************************************************************
358  add a privilege to a privilege array
359  ****************************************************************************/
360
361 static bool privilege_set_add(PRIVILEGE_SET *priv_set, struct lsa_LUIDAttribute set)
362 {
363         struct lsa_LUIDAttribute *new_set;
364
365         /* we can allocate memory to add the new privilege */
366
367         new_set = talloc_realloc(priv_set->mem_ctx, priv_set->set, struct lsa_LUIDAttribute, priv_set->count + 1);
368         if ( !new_set ) {
369                 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
370                 return false;
371         }
372
373         new_set[priv_set->count].luid.high = set.luid.high;
374         new_set[priv_set->count].luid.low = set.luid.low;
375         new_set[priv_set->count].attribute = set.attribute;
376
377         priv_set->count++;
378         priv_set->set = new_set;
379
380         return true;
381 }
382
383 /*******************************************************************
384 *******************************************************************/
385
386 bool se_priv_to_privilege_set( PRIVILEGE_SET *set, uint64_t *privilege_mask )
387 {
388         int i;
389         uint32_t num_privs = ARRAY_SIZE(privs);
390         struct lsa_LUIDAttribute luid;
391
392         luid.attribute = 0;
393         luid.luid.high = 0;
394
395         for ( i=0; i<num_privs; i++ ) {
396                 if ( !is_privilege_assigned(privilege_mask, &privs[i].privilege_mask) )
397                         continue;
398
399                 luid.luid.high = 0;
400                 luid.luid.low = privs[i].luid;
401
402                 if ( !privilege_set_add( set, luid ) )
403                         return false;
404         }
405
406         return true;
407 }
408
409 /*******************************************************************
410 *******************************************************************/
411
412 static bool luid_to_se_priv( struct lsa_LUID *luid, uint64_t *privilege_mask )
413 {
414         int i;
415         uint32_t num_privs = ARRAY_SIZE(privs);
416
417         for ( i=0; i<num_privs; i++ ) {
418                 if ( luid->low == privs[i].luid ) {
419                         se_priv_copy( privilege_mask, &privs[i].privilege_mask );
420                         return true;
421                 }
422         }
423
424         return false;
425 }
426
427 /*******************************************************************
428 *******************************************************************/
429
430 bool privilege_set_to_se_priv( uint64_t *privilege_mask, struct lsa_PrivilegeSet *privset )
431 {
432         int i;
433
434         ZERO_STRUCTP( privilege_mask );
435
436         for ( i=0; i<privset->count; i++ ) {
437                 uint64_t r;
438
439                 /* sanity check for invalid privilege.  we really
440                    only care about the low 32 bits */
441
442                 if ( privset->set[i].luid.high != 0 )
443                         return false;
444
445                 if ( luid_to_se_priv( &privset->set[i].luid, &r ) )
446                         se_priv_add( privilege_mask, &r );
447         }
448
449         return true;
450 }
451
452 static const PRIVS privilege_names[] = {
453         {SEC_PRIV_SECURITY,
454          SE_SECURITY,
455          "SeSecurityPrivilege",
456         "System security"},
457
458         {SEC_PRIV_BACKUP,
459          SE_BACKUP,
460          "SeBackupPrivilege",
461          "Backup files and directories"},
462
463         {SEC_PRIV_RESTORE,
464          SE_RESTORE,
465          "SeRestorePrivilege",
466         "Restore files and directories"},
467
468         {SEC_PRIV_SYSTEMTIME,
469          SE_SYSTEMTIME,
470          "SeSystemtimePrivilege",
471         "Set the system clock"},
472
473         {SEC_PRIV_SHUTDOWN,
474          SE_SHUTDOWN,
475          "SeShutdownPrivilege",
476         "Shutdown the system"},
477
478         {SEC_PRIV_REMOTE_SHUTDOWN,
479          SE_REMOTE_SHUTDOWN,
480          "SeRemoteShutdownPrivilege",
481         "Shutdown the system remotely"},
482
483         {SEC_PRIV_TAKE_OWNERSHIP,
484          SE_TAKE_OWNERSHIP,
485          "SeTakeOwnershipPrivilege",
486         "Take ownership of files and directories"},
487
488         {SEC_PRIV_DEBUG,
489          SE_DEBUG,
490          "SeDebugPrivilege",
491         "Debug processes"},
492
493         {SEC_PRIV_SYSTEM_ENVIRONMENT,
494          SE_SYSTEM_ENVIRONMENT,
495          "SeSystemEnvironmentPrivilege",
496         "Modify system environment"},
497
498         {SEC_PRIV_SYSTEM_PROFILE,
499          SE_SYSTEM_PROFILE,
500          "SeSystemProfilePrivilege",
501         "Profile the system"},
502
503         {SEC_PRIV_PROFILE_SINGLE_PROCESS,
504          SE_PROFILE_SINGLE_PROCESS,
505          "SeProfileSingleProcessPrivilege",
506         "Profile one process"},
507
508         {SEC_PRIV_INCREASE_BASE_PRIORITY,
509          SE_INCREASE_BASE_PRIORITY,
510          "SeIncreaseBasePriorityPrivilege",
511          "Increase base priority"},
512
513         {SEC_PRIV_LOAD_DRIVER,
514          SE_LOAD_DRIVER,
515          "SeLoadDriverPrivilege",
516         "Load drivers"},
517
518         {SEC_PRIV_CREATE_PAGEFILE,
519          SE_CREATE_PAGEFILE,
520          "SeCreatePagefilePrivilege",
521         "Create page files"},
522
523         {SEC_PRIV_INCREASE_QUOTA,
524          SE_INCREASE_QUOTA,
525          "SeIncreaseQuotaPrivilege",
526         "Increase quota"},
527
528         {SEC_PRIV_CHANGE_NOTIFY,
529          SE_CHANGE_NOTIFY,
530          "SeChangeNotifyPrivilege",
531         "Register for change notify"},
532
533         {SEC_PRIV_UNDOCK,
534          SE_UNDOCK,
535          "SeUndockPrivilege",
536         "Undock devices"},
537
538         {SEC_PRIV_MANAGE_VOLUME,
539          SE_MANAGE_VOLUME,
540          "SeManageVolumePrivilege",
541         "Manage system volumes"},
542
543         {SEC_PRIV_IMPERSONATE,
544          SE_IMPERSONATE,
545          "SeImpersonatePrivilege",
546         "Impersonate users"},
547
548         {SEC_PRIV_CREATE_GLOBAL,
549          SE_CREATE_GLOBAL,
550          "SeCreateGlobalPrivilege",
551         "Create global"},
552
553         {SEC_PRIV_ENABLE_DELEGATION,
554          SE_ENABLE_DELEGATION,
555          "SeEnableDelegationPrivilege",
556         "Enable Delegation"},
557
558         {SEC_PRIV_INTERACTIVE_LOGON,
559          SE_INTERACTIVE_LOGON,
560          "SeInteractiveLogonRight",
561         "Interactive logon"},
562
563         {SEC_PRIV_NETWORK_LOGON,
564          SE_NETWORK_LOGON,
565          "SeNetworkLogonRight",
566         "Network logon"},
567
568         {SEC_PRIV_REMOTE_INTERACTIVE_LOGON,
569          SE_REMOTE_INTERACTIVE_LOGON,
570          "SeRemoteInteractiveLogonRight",
571         "Remote Interactive logon"},
572
573         {SEC_PRIV_MACHINE_ACCOUNT,
574          SE_MACHINE_ACCOUNT,
575          "SeMachineAccountPrivilege",
576          "Add workstations to domain"},
577
578         /* These last 3 are Samba only */
579         {SEC_PRIV_PRINT_OPERATOR,
580          SE_PRINT_OPERATOR,
581          "SePrintOperatorPrivilege",
582          "Manage printers"},
583
584         {SEC_PRIV_ADD_USERS,
585          SE_ADD_USERS,
586          "SeAddUsersPrivilege",
587          "Add users and groups to the domain"},
588
589         {SEC_PRIV_DISK_OPERATOR,
590          SE_DISK_OPERATOR,
591          "SeDiskOperatorPrivilege",
592          "Manage disk shares"},
593 };
594
595
596 /*
597   map a privilege id to the wire string constant
598 */
599 const char *sec_privilege_name(enum sec_privilege privilege)
600 {
601         int i;
602         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
603                 if (privilege_names[i].luid == privilege) {
604                         return privilege_names[i].name;
605                 }
606         }
607         return NULL;
608 }
609
610 /*
611   map a privilege id to a privilege display name. Return NULL if not found
612
613   TODO: this should use language mappings
614 */
615 const char *sec_privilege_display_name(enum sec_privilege privilege, uint16_t *language)
616 {
617         int i;
618         if (privilege < 1 || privilege > 64) {
619                 return NULL;
620         }
621         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
622                 if (privilege_names[i].luid == privilege) {
623                         return privilege_names[i].description;
624                 }
625         }
626         return NULL;
627 }
628
629 /*
630   map a privilege name to a privilege id. Return -1 if not found
631 */
632 enum sec_privilege sec_privilege_id(const char *name)
633 {
634         int i;
635         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
636                 if (strcasecmp(privilege_names[i].name, name) == 0) {
637                         return privilege_names[i].luid;
638                 }
639         }
640         return -1;
641 }
642
643 /*
644   map a privilege name to a privilege id. Return -1 if not found
645 */
646 enum sec_privilege sec_privilege_from_mask(uint64_t mask)
647 {
648         int i;
649         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
650                 if (privilege_names[i].privilege_mask == mask) {
651                         return privilege_names[i].luid;
652                 }
653         }
654         return -1;
655 }
656
657 /*
658   map a privilege name to a privilege id. Return -1 if not found
659 */
660 enum sec_privilege sec_privilege_from_index(int idx)
661 {
662         if (idx >= 0 && idx<ARRAY_SIZE(privilege_names)) {
663                 return privilege_names[idx].luid;
664         }
665         return -1;
666 }
667
668
669 /*
670   return a privilege mask given a privilege id
671 */
672 static uint64_t sec_privilege_mask(enum sec_privilege privilege)
673 {
674         int i;
675         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
676                 if (privilege_names[i].luid == privilege) {
677                         return privilege_names[i].privilege_mask;
678                 }
679         }
680
681         return 0;
682 }
683
684
685 /*
686   return true if a security_token has a particular privilege bit set
687 */
688 bool security_token_has_privilege(const struct security_token *token, enum sec_privilege privilege)
689 {
690         uint64_t mask;
691
692         mask = sec_privilege_mask(privilege);
693         if (mask == 0) {
694                 return false;
695         }
696
697         if (token->privilege_mask & mask) {
698                 return true;
699         }
700         return false;
701 }
702
703 /*
704   set a bit in the privilege mask
705 */
706 void security_token_set_privilege(struct security_token *token, enum sec_privilege privilege)
707 {
708         /* Relies on the fact that an invalid privilage will return 0, so won't change this */
709         token->privilege_mask |= sec_privilege_mask(privilege);
710 }
711
712 void security_token_debug_privileges(int dbg_lev, const struct security_token *token)
713 {
714         DEBUGADD(dbg_lev, (" Privileges (0x%16llX):\n",
715                             (unsigned long long) token->privilege_mask));
716
717         if (token->privilege_mask) {
718                 int i = 0;
719                 uint64_t mask;
720                 for (mask = 1; mask != 0; mask = mask << 1) {
721                         if (token->privilege_mask & mask) {
722                                 enum sec_privilege privilege = sec_privilege_from_mask(mask);
723                                 DEBUGADD(dbg_lev, ("  Privilege[%3lu]: %s\n", (unsigned long)i++,
724                                         sec_privilege_name(privilege)));
725                         }
726                 }
727         }
728 }