libcli/security Don't memcpy a uint64_t value, just assign it.
[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 struct lsa_LUIDAttribute get_privilege_luid( uint64_t *privilege_mask )
320 {
321         struct lsa_LUIDAttribute priv_luid;
322         int i;
323
324         uint32_t num_privs = ARRAY_SIZE(privs);
325
326         ZERO_STRUCT( priv_luid );
327
328         for ( i=0; i<num_privs; i++ ) {
329                 if ( se_priv_equal( &privs[i].privilege_mask, privilege_mask ) ) {
330                         priv_luid.luid.low = privs[i].luid;
331                         priv_luid.luid.high = 0;
332                         break;
333                 }
334         }
335
336         return priv_luid;
337 }
338
339 /****************************************************************************
340  Convert a LUID to a named string
341 ****************************************************************************/
342
343 const char *luid_to_privilege_name(const struct lsa_LUID *set)
344 {
345         int i;
346
347         uint32_t num_privs = ARRAY_SIZE(privs);
348
349         if (set->high != 0)
350                 return NULL;
351
352         for ( i=0; i<num_privs; i++ ) {
353                 if ( set->low == privs[i].luid ) {
354                         return privs[i].name;
355                 }
356         }
357
358         return NULL;
359 }
360
361
362 /****************************************************************************
363  add a privilege to a privilege array
364  ****************************************************************************/
365
366 static bool privilege_set_add(PRIVILEGE_SET *priv_set, struct lsa_LUIDAttribute set)
367 {
368         struct lsa_LUIDAttribute *new_set;
369
370         /* we can allocate memory to add the new privilege */
371
372         new_set = talloc_realloc(priv_set->mem_ctx, priv_set->set, struct lsa_LUIDAttribute, priv_set->count + 1);
373         if ( !new_set ) {
374                 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
375                 return false;
376         }
377
378         new_set[priv_set->count].luid.high = set.luid.high;
379         new_set[priv_set->count].luid.low = set.luid.low;
380         new_set[priv_set->count].attribute = set.attribute;
381
382         priv_set->count++;
383         priv_set->set = new_set;
384
385         return true;
386 }
387
388 /*******************************************************************
389 *******************************************************************/
390
391 bool se_priv_to_privilege_set( PRIVILEGE_SET *set, uint64_t *privilege_mask )
392 {
393         int i;
394         uint32_t num_privs = ARRAY_SIZE(privs);
395         struct lsa_LUIDAttribute luid;
396
397         luid.attribute = 0;
398         luid.luid.high = 0;
399
400         for ( i=0; i<num_privs; i++ ) {
401                 if ( !is_privilege_assigned(privilege_mask, &privs[i].privilege_mask) )
402                         continue;
403
404                 luid.luid.high = 0;
405                 luid.luid.low = privs[i].luid;
406
407                 if ( !privilege_set_add( set, luid ) )
408                         return false;
409         }
410
411         return true;
412 }
413
414 /*******************************************************************
415 *******************************************************************/
416
417 static bool luid_to_se_priv( struct lsa_LUID *luid, uint64_t *privilege_mask )
418 {
419         int i;
420         uint32_t num_privs = ARRAY_SIZE(privs);
421
422         for ( i=0; i<num_privs; i++ ) {
423                 if ( luid->low == privs[i].luid ) {
424                         se_priv_copy( privilege_mask, &privs[i].privilege_mask );
425                         return true;
426                 }
427         }
428
429         return false;
430 }
431
432 /*******************************************************************
433 *******************************************************************/
434
435 bool privilege_set_to_se_priv( uint64_t *privilege_mask, struct lsa_PrivilegeSet *privset )
436 {
437         int i;
438
439         ZERO_STRUCTP( privilege_mask );
440
441         for ( i=0; i<privset->count; i++ ) {
442                 uint64_t r;
443
444                 /* sanity check for invalid privilege.  we really
445                    only care about the low 32 bits */
446
447                 if ( privset->set[i].luid.high != 0 )
448                         return false;
449
450                 if ( luid_to_se_priv( &privset->set[i].luid, &r ) )
451                         se_priv_add( privilege_mask, &r );
452         }
453
454         return true;
455 }
456
457 static const PRIVS privilege_names[] = {
458         {SEC_PRIV_SECURITY,
459          SE_SECURITY,
460          "SeSecurityPrivilege",
461         "System security"},
462
463         {SEC_PRIV_BACKUP,
464          SE_BACKUP,
465          "SeBackupPrivilege",
466          "Backup files and directories"},
467
468         {SEC_PRIV_RESTORE,
469          SE_RESTORE,
470          "SeRestorePrivilege",
471         "Restore files and directories"},
472
473         {SEC_PRIV_SYSTEMTIME,
474          SE_SYSTEMTIME,
475          "SeSystemtimePrivilege",
476         "Set the system clock"},
477
478         {SEC_PRIV_SHUTDOWN,
479          SE_SHUTDOWN,
480          "SeShutdownPrivilege",
481         "Shutdown the system"},
482
483         {SEC_PRIV_REMOTE_SHUTDOWN,
484          SE_REMOTE_SHUTDOWN,
485          "SeRemoteShutdownPrivilege",
486         "Shutdown the system remotely"},
487
488         {SEC_PRIV_TAKE_OWNERSHIP,
489          SE_TAKE_OWNERSHIP,
490          "SeTakeOwnershipPrivilege",
491         "Take ownership of files and directories"},
492
493         {SEC_PRIV_DEBUG,
494          SE_DEBUG,
495          "SeDebugPrivilege",
496         "Debug processes"},
497
498         {SEC_PRIV_SYSTEM_ENVIRONMENT,
499          SE_SYSTEM_ENVIRONMENT,
500          "SeSystemEnvironmentPrivilege",
501         "Modify system environment"},
502
503         {SEC_PRIV_SYSTEM_PROFILE,
504          SE_SYSTEM_PROFILE,
505          "SeSystemProfilePrivilege",
506         "Profile the system"},
507
508         {SEC_PRIV_PROFILE_SINGLE_PROCESS,
509          SE_PROFILE_SINGLE_PROCESS,
510          "SeProfileSingleProcessPrivilege",
511         "Profile one process"},
512
513         {SEC_PRIV_INCREASE_BASE_PRIORITY,
514          SE_INCREASE_BASE_PRIORITY,
515          "SeIncreaseBasePriorityPrivilege",
516          "Increase base priority"},
517
518         {SEC_PRIV_LOAD_DRIVER,
519          SE_LOAD_DRIVER,
520          "SeLoadDriverPrivilege",
521         "Load drivers"},
522
523         {SEC_PRIV_CREATE_PAGEFILE,
524          SE_CREATE_PAGEFILE,
525          "SeCreatePagefilePrivilege",
526         "Create page files"},
527
528         {SEC_PRIV_INCREASE_QUOTA,
529          SE_INCREASE_QUOTA,
530          "SeIncreaseQuotaPrivilege",
531         "Increase quota"},
532
533         {SEC_PRIV_CHANGE_NOTIFY,
534          SE_CHANGE_NOTIFY,
535          "SeChangeNotifyPrivilege",
536         "Register for change notify"},
537
538         {SEC_PRIV_UNDOCK,
539          SE_UNDOCK,
540          "SeUndockPrivilege",
541         "Undock devices"},
542
543         {SEC_PRIV_MANAGE_VOLUME,
544          SE_MANAGE_VOLUME,
545          "SeManageVolumePrivilege",
546         "Manage system volumes"},
547
548         {SEC_PRIV_IMPERSONATE,
549          SE_IMPERSONATE,
550          "SeImpersonatePrivilege",
551         "Impersonate users"},
552
553         {SEC_PRIV_CREATE_GLOBAL,
554          SE_CREATE_GLOBAL,
555          "SeCreateGlobalPrivilege",
556         "Create global"},
557
558         {SEC_PRIV_ENABLE_DELEGATION,
559          SE_ENABLE_DELEGATION,
560          "SeEnableDelegationPrivilege",
561         "Enable Delegation"},
562
563         {SEC_PRIV_INTERACTIVE_LOGON,
564          SE_INTERACTIVE_LOGON,
565          "SeInteractiveLogonRight",
566         "Interactive logon"},
567
568         {SEC_PRIV_NETWORK_LOGON,
569          SE_NETWORK_LOGON,
570          "SeNetworkLogonRight",
571         "Network logon"},
572
573         {SEC_PRIV_REMOTE_INTERACTIVE_LOGON,
574          SE_REMOTE_INTERACTIVE_LOGON,
575          "SeRemoteInteractiveLogonRight",
576         "Remote Interactive logon"},
577
578         {SEC_PRIV_MACHINE_ACCOUNT,
579          SE_MACHINE_ACCOUNT,
580          "SeMachineAccountPrivilege",
581          "Add workstations to domain"},
582
583         /* These last 3 are Samba only */
584         {SEC_PRIV_PRINT_OPERATOR,
585          SE_PRINT_OPERATOR,
586          "SePrintOperatorPrivilege",
587          "Manage printers"},
588
589         {SEC_PRIV_ADD_USERS,
590          SE_ADD_USERS,
591          "SeAddUsersPrivilege",
592          "Add users and groups to the domain"},
593
594         {SEC_PRIV_DISK_OPERATOR,
595          SE_DISK_OPERATOR,
596          "SeDiskOperatorPrivilege",
597          "Manage disk shares"},
598 };
599
600
601 /*
602   map a privilege id to the wire string constant
603 */
604 const char *sec_privilege_name(enum sec_privilege privilege)
605 {
606         int i;
607         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
608                 if (privilege_names[i].luid == privilege) {
609                         return privilege_names[i].name;
610                 }
611         }
612         return NULL;
613 }
614
615 /*
616   map a privilege id to a privilege display name. Return NULL if not found
617
618   TODO: this should use language mappings
619 */
620 const char *sec_privilege_display_name(enum sec_privilege privilege, uint16_t *language)
621 {
622         int i;
623         if (privilege < 1 || privilege > 64) {
624                 return NULL;
625         }
626         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
627                 if (privilege_names[i].luid == privilege) {
628                         return privilege_names[i].description;
629                 }
630         }
631         return NULL;
632 }
633
634 /*
635   map a privilege name to a privilege id. Return -1 if not found
636 */
637 enum sec_privilege sec_privilege_id(const char *name)
638 {
639         int i;
640         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
641                 if (strcasecmp(privilege_names[i].name, name) == 0) {
642                         return privilege_names[i].luid;
643                 }
644         }
645         return -1;
646 }
647
648 /*
649   map a privilege name to a privilege id. Return -1 if not found
650 */
651 enum sec_privilege sec_privilege_from_mask(uint64_t mask)
652 {
653         int i;
654         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
655                 if (privilege_names[i].privilege_mask == mask) {
656                         return privilege_names[i].luid;
657                 }
658         }
659         return -1;
660 }
661
662 /*
663   map a privilege name to a privilege id. Return -1 if not found
664 */
665 enum sec_privilege sec_privilege_from_index(int idx)
666 {
667         if (idx >= 0 && idx<ARRAY_SIZE(privilege_names)) {
668                 return privilege_names[idx].luid;
669         }
670         return -1;
671 }
672
673
674 /*
675   return a privilege mask given a privilege id
676 */
677 static uint64_t sec_privilege_mask(enum sec_privilege privilege)
678 {
679         int i;
680         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
681                 if (privilege_names[i].luid == privilege) {
682                         return privilege_names[i].privilege_mask;
683                 }
684         }
685
686         return 0;
687 }
688
689
690 /*
691   return true if a security_token has a particular privilege bit set
692 */
693 bool security_token_has_privilege(const struct security_token *token, enum sec_privilege privilege)
694 {
695         uint64_t mask;
696
697         mask = sec_privilege_mask(privilege);
698         if (mask == 0) {
699                 return false;
700         }
701
702         if (token->privilege_mask & mask) {
703                 return true;
704         }
705         return false;
706 }
707
708 /*
709   set a bit in the privilege mask
710 */
711 void security_token_set_privilege(struct security_token *token, enum sec_privilege privilege)
712 {
713         /* Relies on the fact that an invalid privilage will return 0, so won't change this */
714         token->privilege_mask |= sec_privilege_mask(privilege);
715 }
716
717 void security_token_debug_privileges(int dbg_lev, const struct security_token *token)
718 {
719         DEBUGADD(dbg_lev, (" Privileges (0x%16llX):\n",
720                             (unsigned long long) token->privilege_mask));
721
722         if (token->privilege_mask) {
723                 int i = 0;
724                 uint64_t mask;
725                 for (mask = 1; mask != 0; mask = mask << 1) {
726                         if (token->privilege_mask & mask) {
727                                 enum sec_privilege privilege = sec_privilege_from_mask(mask);
728                                 DEBUGADD(dbg_lev, ("  Privilege[%3lu]: %s\n", (unsigned long)i++,
729                                         sec_privilege_name(privilege)));
730                         }
731                 }
732         }
733 }