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