6acf72e7a0f3aff69fed5cffdfaec986fdaf3582
[abartlet/samba.git/.git] / libcli / security / privileges.c
1 /*
2    Unix SMB/CIFS implementation.
3    Privileges handling functions
4    Copyright (C) Jean François Micouleau       1998-2001
5    Copyright (C) Simo Sorce                     2002-2003
6    Copyright (C) Gerald (Jerry) Carter          2005
7    Copyright (C) Michael Adam                   2007
8    Copyright (C) Andrew Bartlett                2010
9    Copyright (C) Andrew Tridgell                2004
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 /*
26  * Basic privileges functions (mask-operations and conversion
27  * functions between the different formats (se_priv, privset, luid)
28  * moved here * from lib/privileges.c to minimize linker deps.
29  *
30  * generally SID- and LUID-related code is left in lib/privileges.c
31  *
32  * some extra functions to hide privs array from lib/privileges.c
33  */
34
35 #include "includes.h"
36 #include "libcli/security/privileges.h"
37 #include "librpc/gen_ndr/security.h"
38
39 /* The use of strcasecmp here is safe, all the comparison strings are ASCII */
40 #undef strcasecmp
41
42 const uint64_t se_priv_all         = SE_ALL_PRIVS;
43 static const uint64_t se_priv_end  = SE_END;
44
45 /* Define variables for all privileges so we can use the
46    uint64_t* in the various se_priv_XXX() functions */
47
48 const uint64_t se_priv_none       = SE_NONE;
49 const uint64_t se_machine_account = SE_MACHINE_ACCOUNT;
50 const uint64_t se_print_operator  = SE_PRINT_OPERATOR;
51 const uint64_t se_add_users       = SE_ADD_USERS;
52 const uint64_t se_disk_operators  = SE_DISK_OPERATOR;
53 const uint64_t se_remote_shutdown = SE_REMOTE_SHUTDOWN;
54 const uint64_t se_restore         = SE_RESTORE;
55 const uint64_t se_take_ownership  = SE_TAKE_OWNERSHIP;
56
57 PRIVS privs[] = {
58 #if 0   /* usrmgr will display these twice if you include them.  We don't
59            use them but we'll keep the bitmasks reserved in privileges.h anyways */
60
61         {0x0,                      SE_NETWORK_LOGON,     "SeNetworkLogonRight",         "Access this computer from network"},
62         {0x0,                      SE_INTERACTIVE_LOGON, "SeInteractiveLogonRight",     "Log on locally"},
63         {0x0,                      SE_BATCH_LOGON,       "SeBatchLogonRight",           "Log on as a batch job"},
64         {0x0,                      SE_SERVICE_LOGON,     "SeServiceLogonRight",         "Log on as a service"},
65 #endif
66         {SEC_PRIV_MACHINE_ACCOUNT, SE_MACHINE_ACCOUNT,   "SeMachineAccountPrivilege",   "Add machines to domain"},
67         {SEC_PRIV_TAKE_OWNERSHIP,  SE_TAKE_OWNERSHIP,    "SeTakeOwnershipPrivilege",    "Take ownership of files or other objects"},
68         {SEC_PRIV_BACKUP,          SE_BACKUP,            "SeBackupPrivilege",           "Back up files and directories"},
69         {SEC_PRIV_RESTORE,         SE_RESTORE,           "SeRestorePrivilege",          "Restore files and directories"},
70         {SEC_PRIV_REMOTE_SHUTDOWN, SE_REMOTE_SHUTDOWN,   "SeRemoteShutdownPrivilege",   "Force shutdown from a remote system"},
71
72         {SEC_PRIV_PRINT_OPERATOR,  SE_PRINT_OPERATOR,    "SePrintOperatorPrivilege",    "Manage printers"},
73         {SEC_PRIV_ADD_USERS,       SE_ADD_USERS,         "SeAddUsersPrivilege",         "Add users and groups to the domain"},
74         {SEC_PRIV_DISK_OPERATOR,   SE_DISK_OPERATOR,     "SeDiskOperatorPrivilege",     "Manage disk shares"},
75
76         {0x0, SE_END, "", ""}
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         memcpy( dst, src, sizeof(uint64_t) );
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 = count_all_privileges();
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         for ( i=0; !se_priv_equal(&privs[i].privilege_mask, &se_priv_end); 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         if (!name) {
259                 return NULL;
260         }
261
262         for ( i=0; !se_priv_equal(&privs[i].privilege_mask, &se_priv_end); i++ ) {
263
264                 if ( strequal( privs[i].name, name ) ) {
265                         return privs[i].description;
266                 }
267         }
268
269         return NULL;
270 }
271
272 /****************************************************************************
273  initialise a privilege list and set the talloc context
274  ****************************************************************************/
275
276 /****************************************************************************
277  Does the user have the specified privilege ?  We only deal with one privilege
278  at a time here.
279 *****************************************************************************/
280
281 bool user_has_privileges(const struct security_token *token, const uint64_t *privilege_bit)
282 {
283         if ( !token )
284                 return false;
285
286         return is_privilege_assigned( &token->privilege_mask, privilege_bit );
287 }
288
289 /****************************************************************************
290  Does the user have any of the specified privileges ?  We only deal with one privilege
291  at a time here.
292 *****************************************************************************/
293
294 bool user_has_any_privilege(struct security_token *token, const uint64_t *privilege_mask)
295 {
296         if ( !token )
297                 return false;
298
299         return is_any_privilege_assigned( &token->privilege_mask, privilege_mask );
300 }
301
302 /*******************************************************************
303  return the number of elements in the privlege array
304 *******************************************************************/
305
306 int count_all_privileges( void )
307 {
308         /*
309          * The -1 is due to the weird SE_END record...
310          */
311         return (sizeof(privs) / sizeof(privs[0])) - 1;
312 }
313
314
315 /*********************************************************************
316  Generate the struct lsa_LUIDAttribute structure based on a bitmask
317  The assumption here is that the privilege has already been validated
318  so we are guaranteed to find it in the list.
319 *********************************************************************/
320
321 struct lsa_LUIDAttribute get_privilege_luid( uint64_t *privilege_mask )
322 {
323         struct lsa_LUIDAttribute priv_luid;
324         int i;
325
326         ZERO_STRUCT( priv_luid );
327
328         for ( i=0; !se_priv_equal(&privs[i].privilege_mask, &se_priv_end); i++ ) {
329
330                 if ( se_priv_equal( &privs[i].privilege_mask, privilege_mask ) ) {
331                         priv_luid.luid.low = privs[i].luid;
332                         priv_luid.luid.high = 0;
333                         break;
334                 }
335         }
336
337         return priv_luid;
338 }
339
340 /****************************************************************************
341  Convert a LUID to a named string
342 ****************************************************************************/
343
344 const char *luid_to_privilege_name(const struct lsa_LUID *set)
345 {
346         int i;
347
348         if (set->high != 0)
349                 return NULL;
350
351         for ( i=0; !se_priv_equal(&privs[i].privilege_mask, &se_priv_end); i++ ) {
352                 if ( set->low == privs[i].luid ) {
353                         return privs[i].name;
354                 }
355         }
356
357         return NULL;
358 }
359
360
361 /****************************************************************************
362  add a privilege to a privilege array
363  ****************************************************************************/
364
365 static bool privilege_set_add(PRIVILEGE_SET *priv_set, struct lsa_LUIDAttribute set)
366 {
367         struct lsa_LUIDAttribute *new_set;
368
369         /* we can allocate memory to add the new privilege */
370
371         new_set = talloc_realloc(priv_set->mem_ctx, priv_set->set, struct lsa_LUIDAttribute, priv_set->count + 1);
372         if ( !new_set ) {
373                 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
374                 return false;
375         }
376
377         new_set[priv_set->count].luid.high = set.luid.high;
378         new_set[priv_set->count].luid.low = set.luid.low;
379         new_set[priv_set->count].attribute = set.attribute;
380
381         priv_set->count++;
382         priv_set->set = new_set;
383
384         return true;
385 }
386
387 /*******************************************************************
388 *******************************************************************/
389
390 bool se_priv_to_privilege_set( PRIVILEGE_SET *set, uint64_t *privilege_mask )
391 {
392         int i;
393         uint32_t num_privs = count_all_privileges();
394         struct lsa_LUIDAttribute luid;
395
396         luid.attribute = 0;
397         luid.luid.high = 0;
398
399         for ( i=0; i<num_privs; i++ ) {
400                 if ( !is_privilege_assigned(privilege_mask, &privs[i].privilege_mask) )
401                         continue;
402
403                 luid.luid.high = 0;
404                 luid.luid.low = privs[i].luid;
405
406                 if ( !privilege_set_add( set, luid ) )
407                         return false;
408         }
409
410         return true;
411 }
412
413 /*******************************************************************
414 *******************************************************************/
415
416 static bool luid_to_se_priv( struct lsa_LUID *luid, uint64_t *privilege_mask )
417 {
418         int i;
419         uint32_t num_privs = count_all_privileges();
420
421         for ( i=0; i<num_privs; i++ ) {
422                 if ( luid->low == privs[i].luid ) {
423                         se_priv_copy( privilege_mask, &privs[i].privilege_mask );
424                         return true;
425                 }
426         }
427
428         return false;
429 }
430
431 /*******************************************************************
432 *******************************************************************/
433
434 bool privilege_set_to_se_priv( uint64_t *privilege_mask, struct lsa_PrivilegeSet *privset )
435 {
436         int i;
437
438         ZERO_STRUCTP( privilege_mask );
439
440         for ( i=0; i<privset->count; i++ ) {
441                 uint64_t r;
442
443                 /* sanity check for invalid privilege.  we really
444                    only care about the low 32 bits */
445
446                 if ( privset->set[i].luid.high != 0 )
447                         return false;
448
449                 if ( luid_to_se_priv( &privset->set[i].luid, &r ) )
450                         se_priv_add( privilege_mask, &r );
451         }
452
453         return true;
454 }
455
456 static const PRIVS privilege_names[] = {
457         {SEC_PRIV_SECURITY,
458          SE_SECURITY,
459          "SeSecurityPrivilege",
460         "System security"},
461
462         {SEC_PRIV_BACKUP,
463          SE_BACKUP,
464          "SeBackupPrivilege",
465          "Backup files and directories"},
466
467         {SEC_PRIV_RESTORE,
468          SE_RESTORE,
469          "SeRestorePrivilege",
470         "Restore files and directories"},
471
472         {SEC_PRIV_SYSTEMTIME,
473          SE_SYSTEMTIME,
474          "SeSystemtimePrivilege",
475         "Set the system clock"},
476
477         {SEC_PRIV_SHUTDOWN,
478          SE_SHUTDOWN,
479          "SeShutdownPrivilege",
480         "Shutdown the system"},
481
482         {SEC_PRIV_REMOTE_SHUTDOWN,
483          SE_REMOTE_SHUTDOWN,
484          "SeRemoteShutdownPrivilege",
485         "Shutdown the system remotely"},
486
487         {SEC_PRIV_TAKE_OWNERSHIP,
488          SE_TAKE_OWNERSHIP,
489          "SeTakeOwnershipPrivilege",
490         "Take ownership of files and directories"},
491
492         {SEC_PRIV_DEBUG,
493          SE_DEBUG,
494          "SeDebugPrivilege",
495         "Debug processes"},
496
497         {SEC_PRIV_SYSTEM_ENVIRONMENT,
498          SE_SYSTEM_ENVIRONMENT,
499          "SeSystemEnvironmentPrivilege",
500         "Modify system environment"},
501
502         {SEC_PRIV_SYSTEM_PROFILE,
503          SE_SYSTEM_PROFILE,
504          "SeSystemProfilePrivilege",
505         "Profile the system"},
506
507         {SEC_PRIV_PROFILE_SINGLE_PROCESS,
508          SE_PROFILE_SINGLE_PROCESS,
509          "SeProfileSingleProcessPrivilege",
510         "Profile one process"},
511
512         {SEC_PRIV_INCREASE_BASE_PRIORITY,
513          SE_INCREASE_BASE_PRIORITY,
514          "SeIncreaseBasePriorityPrivilege",
515          "Increase base priority"},
516
517         {SEC_PRIV_LOAD_DRIVER,
518          SE_LOAD_DRIVER,
519          "SeLoadDriverPrivilege",
520         "Load drivers"},
521
522         {SEC_PRIV_CREATE_PAGEFILE,
523          SE_CREATE_PAGEFILE,
524          "SeCreatePagefilePrivilege",
525         "Create page files"},
526
527         {SEC_PRIV_INCREASE_QUOTA,
528          SE_INCREASE_QUOTA,
529          "SeIncreaseQuotaPrivilege",
530         "Increase quota"},
531
532         {SEC_PRIV_CHANGE_NOTIFY,
533          SE_CHANGE_NOTIFY,
534          "SeChangeNotifyPrivilege",
535         "Register for change notify"},
536
537         {SEC_PRIV_UNDOCK,
538          SE_UNDOCK,
539          "SeUndockPrivilege",
540         "Undock devices"},
541
542         {SEC_PRIV_MANAGE_VOLUME,
543          SE_MANAGE_VOLUME,
544          "SeManageVolumePrivilege",
545         "Manage system volumes"},
546
547         {SEC_PRIV_IMPERSONATE,
548          SE_IMPERSONATE,
549          "SeImpersonatePrivilege",
550         "Impersonate users"},
551
552         {SEC_PRIV_CREATE_GLOBAL,
553          SE_CREATE_GLOBAL,
554          "SeCreateGlobalPrivilege",
555         "Create global"},
556
557         {SEC_PRIV_ENABLE_DELEGATION,
558          SE_ENABLE_DELEGATION,
559          "SeEnableDelegationPrivilege",
560         "Enable Delegation"},
561
562         {SEC_PRIV_INTERACTIVE_LOGON,
563          SE_INTERACTIVE_LOGON,
564          "SeInteractiveLogonRight",
565         "Interactive logon"},
566
567         {SEC_PRIV_NETWORK_LOGON,
568          SE_NETWORK_LOGON,
569          "SeNetworkLogonRight",
570         "Network logon"},
571
572         {SEC_PRIV_REMOTE_INTERACTIVE_LOGON,
573          SE_REMOTE_INTERACTIVE_LOGON,
574          "SeRemoteInteractiveLogonRight",
575         "Remote Interactive logon"},
576
577         {SEC_PRIV_MACHINE_ACCOUNT,
578          SE_MACHINE_ACCOUNT,
579          "SeMachineAccountPrivilege",
580          "Add workstations to domain"},
581
582         /* These last 3 are Samba only */
583         {SEC_PRIV_PRINT_OPERATOR,
584          SE_PRINT_OPERATOR,
585          "SePrintOperatorPrivilege",
586          "Manage printers"},
587
588         {SEC_PRIV_ADD_USERS,
589          SE_ADD_USERS,
590          "SeAddUsersPrivilege",
591          "Add users and groups to the domain"},
592
593         {SEC_PRIV_DISK_OPERATOR,
594          SE_DISK_OPERATOR,
595          "SeDiskOperatorPrivilege",
596          "Manage disk shares"},
597 };
598
599
600 /*
601   map a privilege id to the wire string constant
602 */
603 const char *sec_privilege_name(enum sec_privilege privilege)
604 {
605         int i;
606         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
607                 if (privilege_names[i].luid == privilege) {
608                         return privilege_names[i].name;
609                 }
610         }
611         return NULL;
612 }
613
614 /*
615   map a privilege id to a privilege display name. Return NULL if not found
616
617   TODO: this should use language mappings
618 */
619 const char *sec_privilege_display_name(enum sec_privilege privilege, uint16_t *language)
620 {
621         int i;
622         if (privilege < 1 || privilege > 64) {
623                 return NULL;
624         }
625         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
626                 if (privilege_names[i].luid == privilege) {
627                         return privilege_names[i].description;
628                 }
629         }
630         return NULL;
631 }
632
633 /*
634   map a privilege name to a privilege id. Return -1 if not found
635 */
636 enum sec_privilege sec_privilege_id(const char *name)
637 {
638         int i;
639         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
640                 if (strcasecmp(privilege_names[i].name, name) == 0) {
641                         return privilege_names[i].luid;
642                 }
643         }
644         return -1;
645 }
646
647 /*
648   map a privilege name to a privilege id. Return -1 if not found
649 */
650 enum sec_privilege sec_privilege_from_mask(uint64_t mask)
651 {
652         int i;
653         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
654                 if (privilege_names[i].privilege_mask == mask) {
655                         return privilege_names[i].luid;
656                 }
657         }
658         return -1;
659 }
660
661 /*
662   map a privilege name to a privilege id. Return -1 if not found
663 */
664 enum sec_privilege sec_privilege_from_index(int idx)
665 {
666         if (idx >= 0 && idx<ARRAY_SIZE(privilege_names)) {
667                 return privilege_names[idx].luid;
668         }
669         return -1;
670 }
671
672
673 /*
674   return a privilege mask given a privilege id
675 */
676 static uint64_t sec_privilege_mask(enum sec_privilege privilege)
677 {
678         int i;
679         for (i=0;i<ARRAY_SIZE(privilege_names);i++) {
680                 if (privilege_names[i].luid == privilege) {
681                         return privilege_names[i].privilege_mask;
682                 }
683         }
684
685         return 0;
686 }
687
688
689 /*
690   return true if a security_token has a particular privilege bit set
691 */
692 bool security_token_has_privilege(const struct security_token *token, enum sec_privilege privilege)
693 {
694         uint64_t mask;
695
696         mask = sec_privilege_mask(privilege);
697         if (mask == 0) {
698                 return false;
699         }
700
701         if (token->privilege_mask & mask) {
702                 return true;
703         }
704         return false;
705 }
706
707 /*
708   set a bit in the privilege mask
709 */
710 void security_token_set_privilege(struct security_token *token, enum sec_privilege privilege)
711 {
712         /* Relies on the fact that an invalid privilage will return 0, so won't change this */
713         token->privilege_mask |= sec_privilege_mask(privilege);
714 }
715
716 void security_token_debug_privileges(int dbg_lev, const struct security_token *token)
717 {
718         DEBUGADD(dbg_lev, (" Privileges (0x%16llX):\n",
719                             (unsigned long long) token->privilege_mask));
720
721         if (token->privilege_mask) {
722                 int i = 0;
723                 uint64_t mask;
724                 for (mask = 1; mask != 0; mask = mask << 1) {
725                         if (token->privilege_mask & mask) {
726                                 enum sec_privilege privilege = sec_privilege_from_mask(mask);
727                                 DEBUGADD(dbg_lev, ("  Privilege[%3lu]: %s\n", (unsigned long)i++,
728                                         sec_privilege_name(privilege)));
729                         }
730                 }
731         }
732 }