root/source3/lib/privileges_basic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. se_priv_copy
  2. se_priv_put_all_privileges
  3. se_priv_add
  4. se_priv_remove
  5. se_priv_invert
  6. se_priv_equal
  7. se_priv_empty
  8. se_priv_from_name
  9. dump_se_priv
  10. is_privilege_assigned
  11. is_any_privilege_assigned
  12. get_privilege_dispname
  13. user_has_privileges
  14. user_has_any_privilege
  15. count_all_privileges
  16. get_privilege_luid
  17. luid_to_privilege_name
  18. privilege_set_add
  19. se_priv_to_privilege_set
  20. luid_to_se_priv
  21. privilege_set_to_se_priv

   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 
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13 
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18 
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 /*
  24  * Basic privileges functions (mask-operations and conversion
  25  * functions between the different formats (se_priv, privset, luid)
  26  * moved here * from lib/privileges.c to minimize linker deps.
  27  *
  28  * generally SID- and LUID-related code is left in lib/privileges.c
  29  *
  30  * some extra functions to hide privs array from lib/privileges.c
  31  */
  32 
  33 #include "includes.h"
  34 
  35 const SE_PRIV se_priv_all         = SE_ALL_PRIVS;
  36 static const SE_PRIV se_priv_end  = SE_END;
  37 
  38 /* Define variables for all privileges so we can use the
  39    SE_PRIV* in the various se_priv_XXX() functions */
  40 
  41 const SE_PRIV se_priv_none       = SE_NONE;
  42 const SE_PRIV se_machine_account = SE_MACHINE_ACCOUNT;
  43 const SE_PRIV se_print_operator  = SE_PRINT_OPERATOR;
  44 const SE_PRIV se_add_users       = SE_ADD_USERS;
  45 const SE_PRIV se_disk_operators  = SE_DISK_OPERATOR;
  46 const SE_PRIV se_remote_shutdown = SE_REMOTE_SHUTDOWN;
  47 const SE_PRIV se_restore         = SE_RESTORE;
  48 const SE_PRIV se_take_ownership  = SE_TAKE_OWNERSHIP;
  49 
  50 /********************************************************************
  51  This is a list of privileges reported by a WIndows 2000 SP4 AD DC
  52  just for reference purposes (and I know the LUID is not guaranteed
  53  across reboots):
  54 
  55             SeCreateTokenPrivilege  Create a token object ( 0x0, 0x2 )
  56      SeAssignPrimaryTokenPrivilege  Replace a process level token ( 0x0, 0x3 )
  57              SeLockMemoryPrivilege  Lock pages in memory ( 0x0, 0x4 )
  58           SeIncreaseQuotaPrivilege  Increase quotas ( 0x0, 0x5 )
  59          SeMachineAccountPrivilege  Add workstations to domain ( 0x0, 0x6 )
  60                     SeTcbPrivilege  Act as part of the operating system ( 0x0, 0x7 )
  61                SeSecurityPrivilege  Manage auditing and security log ( 0x0, 0x8 )
  62           SeTakeOwnershipPrivilege  Take ownership of files or other objects ( 0x0, 0x9 )
  63              SeLoadDriverPrivilege  Load and unload device drivers ( 0x0, 0xa )
  64           SeSystemProfilePrivilege  Profile system performance ( 0x0, 0xb )
  65              SeSystemtimePrivilege  Change the system time ( 0x0, 0xc )
  66    SeProfileSingleProcessPrivilege  Profile single process ( 0x0, 0xd )
  67    SeIncreaseBasePriorityPrivilege  Increase scheduling priority ( 0x0, 0xe )
  68          SeCreatePagefilePrivilege  Create a pagefile ( 0x0, 0xf )
  69         SeCreatePermanentPrivilege  Create permanent shared objects ( 0x0, 0x10 )
  70                  SeBackupPrivilege  Back up files and directories ( 0x0, 0x11 )
  71                 SeRestorePrivilege  Restore files and directories ( 0x0, 0x12 )
  72                SeShutdownPrivilege  Shut down the system ( 0x0, 0x13 )
  73                   SeDebugPrivilege  Debug programs ( 0x0, 0x14 )
  74                   SeAuditPrivilege  Generate security audits ( 0x0, 0x15 )
  75       SeSystemEnvironmentPrivilege  Modify firmware environment values ( 0x0, 0x16 )
  76            SeChangeNotifyPrivilege  Bypass traverse checking ( 0x0, 0x17 )
  77          SeRemoteShutdownPrivilege  Force shutdown from a remote system ( 0x0, 0x18 )
  78                  SeUndockPrivilege  Remove computer from docking station ( 0x0, 0x19 )
  79               SeSyncAgentPrivilege  Synchronize directory service data ( 0x0, 0x1a )
  80        SeEnableDelegationPrivilege  Enable computer and user accounts to be trusted for delegation ( 0x0, 0x1b )
  81            SeManageVolumePrivilege  Perform volume maintenance tasks ( 0x0, 0x1c )
  82             SeImpersonatePrivilege  Impersonate a client after authentication ( 0x0, 0x1d )
  83            SeCreateGlobalPrivilege  Create global objects ( 0x0, 0x1e )
  84 
  85  ********************************************************************/
  86 
  87 /* we have to define the LUID here due to a horrible check by printmig.exe
  88    that requires the SeBackupPrivilege match what is in Windows.  So match
  89    those that we implement and start Samba privileges at 0x1001 */
  90 
  91 PRIVS privs[] = {
  92 #if 0   /* usrmgr will display these twice if you include them.  We don't
  93            use them but we'll keep the bitmasks reserved in privileges.h anyways */
  94 
  95         {SE_NETWORK_LOGON,      "SeNetworkLogonRight",          "Access this computer from network",       { 0x0, 0x0 }},
  96         {SE_INTERACTIVE_LOGON,  "SeInteractiveLogonRight",      "Log on locally",                          { 0x0, 0x0 }},
  97         {SE_BATCH_LOGON,        "SeBatchLogonRight",            "Log on as a batch job",                   { 0x0, 0x0 }},
  98         {SE_SERVICE_LOGON,      "SeServiceLogonRight",          "Log on as a service",                     { 0x0, 0x0 }},
  99 #endif
 100         {SE_MACHINE_ACCOUNT,    "SeMachineAccountPrivilege",    "Add machines to domain",                  { 0x0, 0x0006 }},
 101         {SE_TAKE_OWNERSHIP,     "SeTakeOwnershipPrivilege",     "Take ownership of files or other objects",{ 0x0, 0x0009 }},
 102         {SE_BACKUP,             "SeBackupPrivilege",            "Back up files and directories",           { 0x0, 0x0011 }},
 103         {SE_RESTORE,            "SeRestorePrivilege",           "Restore files and directories",           { 0x0, 0x0012 }},
 104         {SE_REMOTE_SHUTDOWN,    "SeRemoteShutdownPrivilege",    "Force shutdown from a remote system",     { 0x0, 0x0018 }},
 105 
 106         {SE_PRINT_OPERATOR,     "SePrintOperatorPrivilege",     "Manage printers",                         { 0x0, 0x1001 }},
 107         {SE_ADD_USERS,          "SeAddUsersPrivilege",          "Add users and groups to the domain",      { 0x0, 0x1002 }},
 108         {SE_DISK_OPERATOR,      "SeDiskOperatorPrivilege",      "Manage disk shares",                      { 0x0, 0x1003 }},
 109 
 110         {SE_END, "", "", { 0x0, 0x0 }}
 111 };
 112 
 113 /***************************************************************************
 114  copy an SE_PRIV structure
 115 ****************************************************************************/
 116 
 117 bool se_priv_copy( SE_PRIV *dst, const SE_PRIV *src )
     /* [<][>][^][v][top][bottom][index][help] */
 118 {
 119         if ( !dst || !src )
 120                 return False;
 121 
 122         memcpy( dst, src, sizeof(SE_PRIV) );
 123 
 124         return True;
 125 }
 126 
 127 /***************************************************************************
 128  put all privileges into a mask
 129 ****************************************************************************/
 130 
 131 bool se_priv_put_all_privileges(SE_PRIV *mask)
     /* [<][>][^][v][top][bottom][index][help] */
 132 {
 133         int i;
 134         uint32 num_privs = count_all_privileges();
 135 
 136         if (!se_priv_copy(mask, &se_priv_none)) {
 137                 return False;
 138         }
 139         for ( i=0; i<num_privs; i++ ) {
 140                 se_priv_add(mask, &privs[i].se_priv);
 141         }
 142         return True;
 143 }
 144 
 145 /***************************************************************************
 146  combine 2 SE_PRIV structures and store the resulting set in mew_mask
 147 ****************************************************************************/
 148 
 149 void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv )
     /* [<][>][^][v][top][bottom][index][help] */
 150 {
 151         int i;
 152 
 153         for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
 154                 mask->mask[i] |= addpriv->mask[i];
 155         }
 156 }
 157 
 158 /***************************************************************************
 159  remove one SE_PRIV sytucture from another and store the resulting set
 160  in mew_mask
 161 ****************************************************************************/
 162 
 163 void se_priv_remove( SE_PRIV *mask, const SE_PRIV *removepriv )
     /* [<][>][^][v][top][bottom][index][help] */
 164 {
 165         int i;
 166 
 167         for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
 168                 mask->mask[i] &= ~removepriv->mask[i];
 169         }
 170 }
 171 
 172 /***************************************************************************
 173  invert a given SE_PRIV and store the set in new_mask
 174 ****************************************************************************/
 175 
 176 static void se_priv_invert( SE_PRIV *new_mask, const SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
 177 {
 178         SE_PRIV allprivs;
 179 
 180         se_priv_copy( &allprivs, &se_priv_all );
 181         se_priv_remove( &allprivs, mask );
 182         se_priv_copy( new_mask, &allprivs );
 183 }
 184 
 185 /***************************************************************************
 186  check if 2 SE_PRIV structure are equal
 187 ****************************************************************************/
 188 
 189 bool se_priv_equal( const SE_PRIV *mask1, const SE_PRIV *mask2 )
     /* [<][>][^][v][top][bottom][index][help] */
 190 {
 191         return ( memcmp(mask1, mask2, sizeof(SE_PRIV)) == 0 );
 192 }
 193 
 194 /***************************************************************************
 195  check if a SE_PRIV has any assigned privileges
 196 ****************************************************************************/
 197 
 198 static bool se_priv_empty( const SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
 199 {
 200         SE_PRIV p1;
 201         int i;
 202 
 203         se_priv_copy( &p1, mask );
 204 
 205         for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
 206                 p1.mask[i] &= se_priv_all.mask[i];
 207         }
 208 
 209         return se_priv_equal( &p1, &se_priv_none );
 210 }
 211 
 212 /*********************************************************************
 213  Lookup the SE_PRIV value for a privilege name
 214 *********************************************************************/
 215 
 216 bool se_priv_from_name( const char *name, SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
 217 {
 218         int i;
 219 
 220         for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
 221                 if ( strequal( privs[i].name, name ) ) {
 222                         se_priv_copy( mask, &privs[i].se_priv );
 223                         return True;
 224                 }
 225         }
 226 
 227         return False;
 228 }
 229 
 230 /***************************************************************************
 231  dump an SE_PRIV structure to the log files
 232 ****************************************************************************/
 233 
 234 void dump_se_priv( int dbg_cl, int dbg_lvl, const SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
 235 {
 236         int i;
 237 
 238         DEBUGADDC( dbg_cl, dbg_lvl,("SE_PRIV "));
 239 
 240         for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
 241                 DEBUGADDC( dbg_cl, dbg_lvl,(" 0x%x", mask->mask[i] ));
 242         }
 243 
 244         DEBUGADDC( dbg_cl, dbg_lvl, ("\n"));
 245 }
 246 
 247 /****************************************************************************
 248  check if the privilege is in the privilege list
 249 ****************************************************************************/
 250 
 251 bool is_privilege_assigned(const SE_PRIV *privileges,
     /* [<][>][^][v][top][bottom][index][help] */
 252                            const SE_PRIV *check)
 253 {
 254         SE_PRIV p1, p2;
 255 
 256         if ( !privileges || !check )
 257                 return False;
 258 
 259         /* everyone has privileges if you aren't checking for any */
 260 
 261         if ( se_priv_empty( check ) ) {
 262                 DEBUG(1,("is_privilege_assigned: no privileges in check_mask!\n"));
 263                 return True;
 264         }
 265 
 266         se_priv_copy( &p1, check );
 267 
 268         /* invert the SE_PRIV we want to check for and remove that from the
 269            original set.  If we are left with the SE_PRIV we are checking
 270            for then return True */
 271 
 272         se_priv_invert( &p1, check );
 273         se_priv_copy( &p2, privileges );
 274         se_priv_remove( &p2, &p1 );
 275 
 276         return se_priv_equal( &p2, check );
 277 }
 278 
 279 /****************************************************************************
 280  check if the privilege is in the privilege list
 281 ****************************************************************************/
 282 
 283 static bool is_any_privilege_assigned( SE_PRIV *privileges, const SE_PRIV *check )
     /* [<][>][^][v][top][bottom][index][help] */
 284 {
 285         SE_PRIV p1, p2;
 286 
 287         if ( !privileges || !check )
 288                 return False;
 289 
 290         /* everyone has privileges if you aren't checking for any */
 291 
 292         if ( se_priv_empty( check ) ) {
 293                 DEBUG(1,("is_any_privilege_assigned: no privileges in check_mask!\n"));
 294                 return True;
 295         }
 296 
 297         se_priv_copy( &p1, check );
 298 
 299         /* invert the SE_PRIV we want to check for and remove that from the
 300            original set.  If we are left with the SE_PRIV we are checking
 301            for then return True */
 302 
 303         se_priv_invert( &p1, check );
 304         se_priv_copy( &p2, privileges );
 305         se_priv_remove( &p2, &p1 );
 306 
 307         /* see if we have any bits left */
 308 
 309         return !se_priv_empty( &p2 );
 310 }
 311 
 312 /*********************************************************************
 313  Generate the LUID_ATTR structure based on a bitmask
 314 *********************************************************************/
 315 
 316 const char* get_privilege_dispname( const char *name )
     /* [<][>][^][v][top][bottom][index][help] */
 317 {
 318         int i;
 319 
 320         if (!name) {
 321                 return NULL;
 322         }
 323 
 324         for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
 325 
 326                 if ( strequal( privs[i].name, name ) ) {
 327                         return privs[i].description;
 328                 }
 329         }
 330 
 331         return NULL;
 332 }
 333 
 334 /****************************************************************************
 335  initialise a privilege list and set the talloc context
 336  ****************************************************************************/
 337 
 338 /****************************************************************************
 339  Does the user have the specified privilege ?  We only deal with one privilege
 340  at a time here.
 341 *****************************************************************************/
 342 
 343 bool user_has_privileges(const NT_USER_TOKEN *token, const SE_PRIV *privilege)
     /* [<][>][^][v][top][bottom][index][help] */
 344 {
 345         if ( !token )
 346                 return False;
 347 
 348         return is_privilege_assigned( &token->privileges, privilege );
 349 }
 350 
 351 /****************************************************************************
 352  Does the user have any of the specified privileges ?  We only deal with one privilege
 353  at a time here.
 354 *****************************************************************************/
 355 
 356 bool user_has_any_privilege(NT_USER_TOKEN *token, const SE_PRIV *privilege)
     /* [<][>][^][v][top][bottom][index][help] */
 357 {
 358         if ( !token )
 359                 return False;
 360 
 361         return is_any_privilege_assigned( &token->privileges, privilege );
 362 }
 363 
 364 /*******************************************************************
 365  return the number of elements in the privlege array
 366 *******************************************************************/
 367 
 368 int count_all_privileges( void )
     /* [<][>][^][v][top][bottom][index][help] */
 369 {
 370         /*
 371          * The -1 is due to the weird SE_END record...
 372          */
 373         return (sizeof(privs) / sizeof(privs[0])) - 1;
 374 }
 375 
 376 
 377 /*********************************************************************
 378  Generate the LUID_ATTR structure based on a bitmask
 379  The assumption here is that the privilege has already been validated
 380  so we are guaranteed to find it in the list.
 381 *********************************************************************/
 382 
 383 LUID_ATTR get_privilege_luid( SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
 384 {
 385         LUID_ATTR priv_luid;
 386         int i;
 387 
 388         ZERO_STRUCT( priv_luid );
 389 
 390         for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
 391 
 392                 if ( se_priv_equal( &privs[i].se_priv, mask ) ) {
 393                         priv_luid.luid = privs[i].luid;
 394                         break;
 395                 }
 396         }
 397 
 398         return priv_luid;
 399 }
 400 
 401 /****************************************************************************
 402  Convert a LUID to a named string
 403 ****************************************************************************/
 404 
 405 const char *luid_to_privilege_name(const LUID *set)
     /* [<][>][^][v][top][bottom][index][help] */
 406 {
 407         int i;
 408 
 409         if (set->high != 0)
 410                 return NULL;
 411 
 412         for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
 413                 if ( set->low == privs[i].luid.low ) {
 414                         return privs[i].name;
 415                 }
 416         }
 417 
 418         return NULL;
 419 }
 420 
 421 
 422 /****************************************************************************
 423  add a privilege to a privilege array
 424  ****************************************************************************/
 425 
 426 static bool privilege_set_add(PRIVILEGE_SET *priv_set, LUID_ATTR set)
     /* [<][>][^][v][top][bottom][index][help] */
 427 {
 428         LUID_ATTR *new_set;
 429 
 430         /* we can allocate memory to add the new privilege */
 431 
 432         new_set = TALLOC_REALLOC_ARRAY(priv_set->mem_ctx, priv_set->set, LUID_ATTR, priv_set->count + 1);
 433         if ( !new_set ) {
 434                 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
 435                 return False;
 436         }
 437 
 438         new_set[priv_set->count].luid.high = set.luid.high;
 439         new_set[priv_set->count].luid.low = set.luid.low;
 440         new_set[priv_set->count].attr = set.attr;
 441 
 442         priv_set->count++;
 443         priv_set->set = new_set;
 444 
 445         return True;
 446 }
 447 
 448 /*******************************************************************
 449 *******************************************************************/
 450 
 451 bool se_priv_to_privilege_set( PRIVILEGE_SET *set, SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
 452 {
 453         int i;
 454         uint32 num_privs = count_all_privileges();
 455         LUID_ATTR luid;
 456 
 457         luid.attr = 0;
 458         luid.luid.high = 0;
 459 
 460         for ( i=0; i<num_privs; i++ ) {
 461                 if ( !is_privilege_assigned(mask, &privs[i].se_priv) )
 462                         continue;
 463 
 464                 luid.luid = privs[i].luid;
 465 
 466                 if ( !privilege_set_add( set, luid ) )
 467                         return False;
 468         }
 469 
 470         return True;
 471 }
 472 
 473 /*******************************************************************
 474 *******************************************************************/
 475 
 476 static bool luid_to_se_priv( struct lsa_LUID *luid, SE_PRIV *mask )
     /* [<][>][^][v][top][bottom][index][help] */
 477 {
 478         int i;
 479         uint32 num_privs = count_all_privileges();
 480 
 481         for ( i=0; i<num_privs; i++ ) {
 482                 if ( luid->low == privs[i].luid.low ) {
 483                         se_priv_copy( mask, &privs[i].se_priv );
 484                         return True;
 485                 }
 486         }
 487 
 488         return False;
 489 }
 490 
 491 /*******************************************************************
 492 *******************************************************************/
 493 
 494 bool privilege_set_to_se_priv( SE_PRIV *mask, struct lsa_PrivilegeSet *privset )
     /* [<][>][^][v][top][bottom][index][help] */
 495 {
 496         int i;
 497 
 498         ZERO_STRUCTP( mask );
 499 
 500         for ( i=0; i<privset->count; i++ ) {
 501                 SE_PRIV r;
 502 
 503                 /* sanity check for invalid privilege.  we really
 504                    only care about the low 32 bits */
 505 
 506                 if ( privset->set[i].luid.high != 0 )
 507                         return False;
 508 
 509                 if ( luid_to_se_priv( &privset->set[i].luid, &r ) )
 510                         se_priv_add( mask, &r );
 511         }
 512 
 513         return True;
 514 }
 515 

/* [<][>][^][v][top][bottom][index][help] */