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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * Basic privileges functions (mask-operations and conversion
26 * functions between the different formats (se_priv, privset, luid)
27 * moved here * from lib/privileges.c to minimize linker deps.
29 * generally SID- and LUID-related code is left in lib/privileges.c
31 * some extra functions to hide privs array from lib/privileges.c
36 const uint64_t se_priv_all
= SE_ALL_PRIVS
;
37 static const uint64_t se_priv_end
= SE_END
;
39 /* Define variables for all privileges so we can use the
40 uint64_t* in the various se_priv_XXX() functions */
42 const uint64_t se_priv_none
= SE_NONE
;
43 const uint64_t se_machine_account
= SE_MACHINE_ACCOUNT
;
44 const uint64_t se_print_operator
= SE_PRINT_OPERATOR
;
45 const uint64_t se_add_users
= SE_ADD_USERS
;
46 const uint64_t se_disk_operators
= SE_DISK_OPERATOR
;
47 const uint64_t se_remote_shutdown
= SE_REMOTE_SHUTDOWN
;
48 const uint64_t se_restore
= SE_RESTORE
;
49 const uint64_t se_take_ownership
= SE_TAKE_OWNERSHIP
;
52 #if 0 /* usrmgr will display these twice if you include them. We don't
53 use them but we'll keep the bitmasks reserved in privileges.h anyways */
55 {SE_NETWORK_LOGON
, "SeNetworkLogonRight", "Access this computer from network", 0x0},
56 {SE_INTERACTIVE_LOGON
, "SeInteractiveLogonRight", "Log on locally", 0x0},
57 {SE_BATCH_LOGON
, "SeBatchLogonRight", "Log on as a batch job", 0x0},
58 {SE_SERVICE_LOGON
, "SeServiceLogonRight", "Log on as a service", 0x0},
60 {SE_MACHINE_ACCOUNT
, "SeMachineAccountPrivilege", "Add machines to domain", SEC_PRIV_MACHINE_ACCOUNT
},
61 {SE_TAKE_OWNERSHIP
, "SeTakeOwnershipPrivilege", "Take ownership of files or other objects",SEC_PRIV_TAKE_OWNERSHIP
},
62 {SE_BACKUP
, "SeBackupPrivilege", "Back up files and directories", SEC_PRIV_BACKUP
},
63 {SE_RESTORE
, "SeRestorePrivilege", "Restore files and directories", SEC_PRIV_RESTORE
},
64 {SE_REMOTE_SHUTDOWN
, "SeRemoteShutdownPrivilege", "Force shutdown from a remote system", SEC_PRIV_REMOTE_SHUTDOWN
},
66 {SE_PRINT_OPERATOR
, "SePrintOperatorPrivilege", "Manage printers", SEC_PRIV_PRINT_OPERATOR
},
67 {SE_ADD_USERS
, "SeAddUsersPrivilege", "Add users and groups to the domain", SEC_PRIV_ADD_USERS
},
68 {SE_DISK_OPERATOR
, "SeDiskOperatorPrivilege", "Manage disk shares", SEC_PRIV_DISK_OPERATOR
},
73 /***************************************************************************
74 copy an uint64_t structure
75 ****************************************************************************/
77 bool se_priv_copy( uint64_t *dst
, const uint64_t *src
)
82 memcpy( dst
, src
, sizeof(uint64_t) );
87 /***************************************************************************
88 put all privileges into a mask
89 ****************************************************************************/
91 bool se_priv_put_all_privileges(uint64_t *privilege_mask
)
94 uint32 num_privs
= count_all_privileges();
96 if (!se_priv_copy(privilege_mask
, &se_priv_none
)) {
99 for ( i
=0; i
<num_privs
; i
++ ) {
100 se_priv_add(privilege_mask
, &privs
[i
].privilege_mask
);
105 /***************************************************************************
106 combine 2 uint64_t structures and store the resulting set in mew_mask
107 ****************************************************************************/
109 void se_priv_add( uint64_t *privilege_mask
, const uint64_t *addpriv
)
111 *privilege_mask
|= *addpriv
;
114 /***************************************************************************
115 remove one uint64_t sytucture from another and store the resulting set
117 ****************************************************************************/
119 void se_priv_remove( uint64_t *privilege_mask
, const uint64_t *removepriv
)
121 *privilege_mask
&= ~*removepriv
;
124 /***************************************************************************
125 invert a given uint64_t and store the set in new_mask
126 ****************************************************************************/
128 static void se_priv_invert( uint64_t *new_mask
, const uint64_t *privilege_mask
)
132 se_priv_copy( &allprivs
, &se_priv_all
);
133 se_priv_remove( &allprivs
, privilege_mask
);
134 se_priv_copy( new_mask
, &allprivs
);
137 /***************************************************************************
138 check if 2 uint64_t structure are equal
139 ****************************************************************************/
141 bool se_priv_equal( const uint64_t *privilege_mask1
, const uint64_t *privilege_mask2
)
143 return *privilege_mask1
== *privilege_mask2
;
146 /***************************************************************************
147 check if a uint64_t has any assigned privileges
148 ****************************************************************************/
150 static bool se_priv_empty( const uint64_t *privilege_mask
)
154 se_priv_copy( &p1
, privilege_mask
);
158 return se_priv_equal( &p1
, &se_priv_none
);
161 /*********************************************************************
162 Lookup the uint64_t value for a privilege name
163 *********************************************************************/
165 bool se_priv_from_name( const char *name
, uint64_t *privilege_mask
)
169 for ( i
=0; !se_priv_equal(&privs
[i
].privilege_mask
, &se_priv_end
); i
++ ) {
170 if ( strequal( privs
[i
].name
, name
) ) {
171 se_priv_copy( privilege_mask
, &privs
[i
].privilege_mask
);
179 /***************************************************************************
180 dump an uint64_t structure to the log files
181 ****************************************************************************/
183 void dump_se_priv( int dbg_cl
, int dbg_lvl
, const uint64_t *privilege_mask
)
185 DEBUGADDC( dbg_cl
, dbg_lvl
,("uint64_t 0x%llx\n", (unsigned long long)*privilege_mask
));
188 /****************************************************************************
189 check if the privilege is in the privilege list
190 ****************************************************************************/
192 bool is_privilege_assigned(const uint64_t *privileges
,
193 const uint64_t *check
)
197 if ( !privileges
|| !check
)
200 /* everyone has privileges if you aren't checking for any */
202 if ( se_priv_empty( check
) ) {
203 DEBUG(1,("is_privilege_assigned: no privileges in check_mask!\n"));
207 se_priv_copy( &p1
, check
);
209 /* invert the uint64_t we want to check for and remove that from the
210 original set. If we are left with the uint64_t we are checking
211 for then return True */
213 se_priv_invert( &p1
, check
);
214 se_priv_copy( &p2
, privileges
);
215 se_priv_remove( &p2
, &p1
);
217 return se_priv_equal( &p2
, check
);
220 /****************************************************************************
221 check if the privilege is in the privilege list
222 ****************************************************************************/
224 static bool is_any_privilege_assigned( uint64_t *privileges
, const uint64_t *check
)
228 if ( !privileges
|| !check
)
231 /* everyone has privileges if you aren't checking for any */
233 if ( se_priv_empty( check
) ) {
234 DEBUG(1,("is_any_privilege_assigned: no privileges in check_mask!\n"));
238 se_priv_copy( &p1
, check
);
240 /* invert the uint64_t we want to check for and remove that from the
241 original set. If we are left with the uint64_t we are checking
242 for then return True */
244 se_priv_invert( &p1
, check
);
245 se_priv_copy( &p2
, privileges
);
246 se_priv_remove( &p2
, &p1
);
248 /* see if we have any bits left */
250 return !se_priv_empty( &p2
);
253 /*********************************************************************
254 Generate the struct lsa_LUIDAttribute structure based on a bitmask
255 *********************************************************************/
257 const char* get_privilege_dispname( const char *name
)
265 for ( i
=0; !se_priv_equal(&privs
[i
].privilege_mask
, &se_priv_end
); i
++ ) {
267 if ( strequal( privs
[i
].name
, name
) ) {
268 return privs
[i
].description
;
275 /****************************************************************************
276 initialise a privilege list and set the talloc context
277 ****************************************************************************/
279 /****************************************************************************
280 Does the user have the specified privilege ? We only deal with one privilege
282 *****************************************************************************/
284 bool user_has_privileges(const struct security_token
*token
, const uint64_t *privilege_bit
)
289 return is_privilege_assigned( &token
->privilege_mask
, privilege_bit
);
292 /****************************************************************************
293 Does the user have any of the specified privileges ? We only deal with one privilege
295 *****************************************************************************/
297 bool user_has_any_privilege(struct security_token
*token
, const uint64_t *privilege_mask
)
302 return is_any_privilege_assigned( &token
->privilege_mask
, privilege_mask
);
305 /*******************************************************************
306 return the number of elements in the privlege array
307 *******************************************************************/
309 int count_all_privileges( void )
312 * The -1 is due to the weird SE_END record...
314 return (sizeof(privs
) / sizeof(privs
[0])) - 1;
318 /*********************************************************************
319 Generate the struct lsa_LUIDAttribute structure based on a bitmask
320 The assumption here is that the privilege has already been validated
321 so we are guaranteed to find it in the list.
322 *********************************************************************/
324 struct lsa_LUIDAttribute
get_privilege_luid( uint64_t *privilege_mask
)
326 struct lsa_LUIDAttribute priv_luid
;
329 ZERO_STRUCT( priv_luid
);
331 for ( i
=0; !se_priv_equal(&privs
[i
].privilege_mask
, &se_priv_end
); i
++ ) {
333 if ( se_priv_equal( &privs
[i
].privilege_mask
, privilege_mask
) ) {
334 priv_luid
.luid
.low
= privs
[i
].luid
;
335 priv_luid
.luid
.high
= 0;
343 /****************************************************************************
344 Convert a LUID to a named string
345 ****************************************************************************/
347 const char *luid_to_privilege_name(const struct lsa_LUID
*set
)
354 for ( i
=0; !se_priv_equal(&privs
[i
].privilege_mask
, &se_priv_end
); i
++ ) {
355 if ( set
->low
== privs
[i
].luid
) {
356 return privs
[i
].name
;
364 /****************************************************************************
365 add a privilege to a privilege array
366 ****************************************************************************/
368 static bool privilege_set_add(PRIVILEGE_SET
*priv_set
, struct lsa_LUIDAttribute set
)
370 struct lsa_LUIDAttribute
*new_set
;
372 /* we can allocate memory to add the new privilege */
374 new_set
= TALLOC_REALLOC_ARRAY(priv_set
->mem_ctx
, priv_set
->set
, struct lsa_LUIDAttribute
, priv_set
->count
+ 1);
376 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
380 new_set
[priv_set
->count
].luid
.high
= set
.luid
.high
;
381 new_set
[priv_set
->count
].luid
.low
= set
.luid
.low
;
382 new_set
[priv_set
->count
].attribute
= set
.attribute
;
385 priv_set
->set
= new_set
;
390 /*******************************************************************
391 *******************************************************************/
393 bool se_priv_to_privilege_set( PRIVILEGE_SET
*set
, uint64_t *privilege_mask
)
396 uint32 num_privs
= count_all_privileges();
397 struct lsa_LUIDAttribute luid
;
402 for ( i
=0; i
<num_privs
; i
++ ) {
403 if ( !is_privilege_assigned(privilege_mask
, &privs
[i
].privilege_mask
) )
407 luid
.luid
.low
= privs
[i
].luid
;
409 if ( !privilege_set_add( set
, luid
) )
416 /*******************************************************************
417 *******************************************************************/
419 static bool luid_to_se_priv( struct lsa_LUID
*luid
, uint64_t *privilege_mask
)
422 uint32 num_privs
= count_all_privileges();
424 for ( i
=0; i
<num_privs
; i
++ ) {
425 if ( luid
->low
== privs
[i
].luid
) {
426 se_priv_copy( privilege_mask
, &privs
[i
].privilege_mask
);
434 /*******************************************************************
435 *******************************************************************/
437 bool privilege_set_to_se_priv( uint64_t *privilege_mask
, struct lsa_PrivilegeSet
*privset
)
441 ZERO_STRUCTP( privilege_mask
);
443 for ( i
=0; i
<privset
->count
; i
++ ) {
446 /* sanity check for invalid privilege. we really
447 only care about the low 32 bits */
449 if ( privset
->set
[i
].luid
.high
!= 0 )
452 if ( luid_to_se_priv( &privset
->set
[i
].luid
, &r
) )
453 se_priv_add( privilege_mask
, &r
);