libcli/security Remove luid_to_se_priv() and luid_to_privilege_name()
[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 #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  add a privilege to a privilege array
422  ****************************************************************************/
423
424 static bool privilege_set_add(PRIVILEGE_SET *priv_set, struct lsa_LUIDAttribute set)
425 {
426         struct lsa_LUIDAttribute *new_set;
427
428         /* we can allocate memory to add the new privilege */
429
430         new_set = talloc_realloc(priv_set->mem_ctx, priv_set->set, struct lsa_LUIDAttribute, priv_set->count + 1);
431         if ( !new_set ) {
432                 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
433                 return false;
434         }
435
436         new_set[priv_set->count].luid.high = set.luid.high;
437         new_set[priv_set->count].luid.low = set.luid.low;
438         new_set[priv_set->count].attribute = set.attribute;
439
440         priv_set->count++;
441         priv_set->set = new_set;
442
443         return true;
444 }
445
446 /*******************************************************************
447 *******************************************************************/
448
449 bool se_priv_to_privilege_set( PRIVILEGE_SET *set, uint64_t privilege_mask )
450 {
451         int i;
452         uint32_t num_privs = ARRAY_SIZE(privs);
453         struct lsa_LUIDAttribute luid;
454
455         luid.attribute = 0;
456         luid.luid.high = 0;
457
458         for ( i=0; i<num_privs; i++ ) {
459                 if ((privilege_mask & privs[i].privilege_mask) == 0)
460                         continue;
461
462                 luid.luid.high = 0;
463                 luid.luid.low = privs[i].luid;
464
465                 if ( !privilege_set_add( set, luid ) )
466                         return false;
467         }
468
469         return true;
470 }
471
472 /*******************************************************************
473 *******************************************************************/
474
475 bool privilege_set_to_se_priv( uint64_t *privilege_mask, struct lsa_PrivilegeSet *privset )
476 {
477         int i;
478
479         ZERO_STRUCTP( privilege_mask );
480
481         for ( i=0; i<privset->count; i++ ) {
482                 uint64_t r;
483
484                 /* sanity check for invalid privilege.  we really
485                    only care about the low 32 bits */
486
487                 if ( privset->set[i].luid.high != 0 )
488                         return false;
489
490                 r = sec_privilege_mask(privset->set[i].luid.low);
491                 if (r) {
492                         *privilege_mask |= r;
493                 }
494         }
495
496         return true;
497 }
498
499 /*
500   map a privilege id to the wire string constant
501 */
502 const char *sec_privilege_name(enum sec_privilege privilege)
503 {
504         int i;
505         for (i=0;i<ARRAY_SIZE(privs);i++) {
506                 if (privs[i].luid == privilege) {
507                         return privs[i].name;
508                 }
509         }
510         return NULL;
511 }
512
513 /*
514   map a privilege id to a privilege display name. Return NULL if not found
515
516   TODO: this should use language mappings
517 */
518 const char *sec_privilege_display_name(enum sec_privilege privilege, uint16_t *language)
519 {
520         int i;
521         if (privilege < 1 || privilege > 64) {
522                 return NULL;
523         }
524         for (i=0;i<ARRAY_SIZE(privs);i++) {
525                 if (privs[i].luid == privilege) {
526                         return privs[i].description;
527                 }
528         }
529         return NULL;
530 }
531
532 /*
533   map a privilege name to a privilege id. Return -1 if not found
534 */
535 enum sec_privilege sec_privilege_id(const char *name)
536 {
537         int i;
538         for (i=0;i<ARRAY_SIZE(privs);i++) {
539                 if (strcasecmp(privs[i].name, name) == 0) {
540                         return privs[i].luid;
541                 }
542         }
543         return -1;
544 }
545
546 /*
547   map a privilege name to a privilege id. Return -1 if not found
548 */
549 enum sec_privilege sec_privilege_from_mask(uint64_t mask)
550 {
551         int i;
552         for (i=0;i<ARRAY_SIZE(privs);i++) {
553                 if (privs[i].privilege_mask == mask) {
554                         return privs[i].luid;
555                 }
556         }
557         return -1;
558 }
559
560 /*
561   assist in walking the table of privileges - return the LUID (low 32 bits) by index
562 */
563 enum sec_privilege sec_privilege_from_index(int idx)
564 {
565         if (idx >= 0 && idx<ARRAY_SIZE(privs)) {
566                 return privs[idx].luid;
567         }
568         return -1;
569 }
570
571 /*
572   assist in walking the table of privileges - return the string constant by index
573 */
574 const char *sec_privilege_name_from_index(int idx)
575 {
576         if (idx >= 0 && idx<ARRAY_SIZE(privs)) {
577                 return privs[idx].name;
578         }
579         return NULL;
580 }
581
582
583 /*
584   return a privilege mask given a privilege id
585 */
586 static uint64_t sec_privilege_mask(enum sec_privilege privilege)
587 {
588         int i;
589         for (i=0;i<ARRAY_SIZE(privs);i++) {
590                 if (privs[i].luid == privilege) {
591                         return privs[i].privilege_mask;
592                 }
593         }
594
595         return 0;
596 }
597
598
599 /*
600   return true if a security_token has a particular privilege bit set
601 */
602 bool security_token_has_privilege(const struct security_token *token, enum sec_privilege privilege)
603 {
604         uint64_t mask;
605
606         mask = sec_privilege_mask(privilege);
607         if (mask == 0) {
608                 return false;
609         }
610
611         if (token->privilege_mask & mask) {
612                 return true;
613         }
614         return false;
615 }
616
617 /*
618   set a bit in the privilege mask
619 */
620 void security_token_set_privilege(struct security_token *token, enum sec_privilege privilege)
621 {
622         /* Relies on the fact that an invalid privilage will return 0, so won't change this */
623         token->privilege_mask |= sec_privilege_mask(privilege);
624 }
625
626 void security_token_debug_privileges(int dbg_lev, const struct security_token *token)
627 {
628         DEBUGADD(dbg_lev, (" Privileges (0x%16llX):\n",
629                             (unsigned long long) token->privilege_mask));
630
631         if (token->privilege_mask) {
632                 int idx = 0;
633                 int i = 0;
634                 for (idx = 0; idx<ARRAY_SIZE(privs); idx++) {
635                         if (token->privilege_mask & privs[idx].privilege_mask) {
636                                 DEBUGADD(dbg_lev, ("  Privilege[%3lu]: %s\n", (unsigned long)i++,
637                                                    privs[idx].name));
638                         }
639                 }
640         }
641 }