LCOV - code coverage report
Current view: top level - libcli/security - privileges.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 107 121 88.4 %
Date: 2021-09-23 10:06:22 Functions: 19 19 100.0 %

          Line data    Source code
       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 "libcli/security/privileges_private.h"
      38             : #include "librpc/gen_ndr/security.h"
      39             : 
      40             : /* The use of strcasecmp here is safe, all the comparison strings are ASCII */
      41             : #undef strcasecmp
      42             : 
      43             : #define NUM_SHORT_LIST_PRIVS 9
      44             : 
      45             : static const struct {
      46             :         enum sec_privilege luid;
      47             :         uint64_t privilege_mask;
      48             :         const char *name;
      49             :         const char *description;
      50             : } privs[] = {
      51             : 
      52             :         {SEC_PRIV_MACHINE_ACCOUNT, SEC_PRIV_MACHINE_ACCOUNT_BIT,   "SeMachineAccountPrivilege",       "Add machines to domain"},
      53             :         {SEC_PRIV_TAKE_OWNERSHIP,  SEC_PRIV_TAKE_OWNERSHIP_BIT,    "SeTakeOwnershipPrivilege",    "Take ownership of files or other objects"},
      54             :         {SEC_PRIV_BACKUP,          SEC_PRIV_BACKUP_BIT,            "SeBackupPrivilege",           "Back up files and directories"},
      55             :         {SEC_PRIV_RESTORE,         SEC_PRIV_RESTORE_BIT,           "SeRestorePrivilege",          "Restore files and directories"},
      56             :         {SEC_PRIV_REMOTE_SHUTDOWN, SEC_PRIV_REMOTE_SHUTDOWN_BIT,   "SeRemoteShutdownPrivilege",       "Force shutdown from a remote system"},
      57             : 
      58             :         {SEC_PRIV_PRINT_OPERATOR,  SEC_PRIV_PRINT_OPERATOR_BIT,  "SePrintOperatorPrivilege",  "Manage printers"},
      59             :         {SEC_PRIV_ADD_USERS,       SEC_PRIV_ADD_USERS_BIT,       "SeAddUsersPrivilege",               "Add users and groups to the domain"},
      60             :         {SEC_PRIV_DISK_OPERATOR,   SEC_PRIV_DISK_OPERATOR_BIT,   "SeDiskOperatorPrivilege",   "Manage disk shares"},
      61             :         {SEC_PRIV_SECURITY,        SEC_PRIV_SECURITY_BIT,        "SeSecurityPrivilege",       "System security"},
      62             : 
      63             : 
      64             :         /* The list from here on is not displayed in the code from
      65             :          * source3, and is after index NUM_SHORT_LIST_PRIVS for that
      66             :          * reason */ 
      67             : 
      68             :         {SEC_PRIV_SYSTEMTIME,
      69             :          SEC_PRIV_SYSTEMTIME_BIT,
      70             :          "SeSystemtimePrivilege",
      71             :         "Set the system clock"},
      72             : 
      73             :         {SEC_PRIV_SHUTDOWN,
      74             :          SEC_PRIV_SHUTDOWN_BIT,
      75             :          "SeShutdownPrivilege",
      76             :         "Shutdown the system"},
      77             : 
      78             :         {SEC_PRIV_DEBUG,
      79             :          SEC_PRIV_DEBUG_BIT,
      80             :          "SeDebugPrivilege",
      81             :         "Debug processes"},
      82             : 
      83             :         {SEC_PRIV_SYSTEM_ENVIRONMENT,
      84             :          SEC_PRIV_SYSTEM_ENVIRONMENT_BIT,
      85             :          "SeSystemEnvironmentPrivilege",
      86             :         "Modify system environment"},
      87             : 
      88             :         {SEC_PRIV_SYSTEM_PROFILE,
      89             :          SEC_PRIV_SYSTEM_PROFILE_BIT,
      90             :          "SeSystemProfilePrivilege",
      91             :         "Profile the system"},
      92             : 
      93             :         {SEC_PRIV_PROFILE_SINGLE_PROCESS,
      94             :          SEC_PRIV_PROFILE_SINGLE_PROCESS_BIT,
      95             :          "SeProfileSingleProcessPrivilege",
      96             :         "Profile one process"},
      97             : 
      98             :         {SEC_PRIV_INCREASE_BASE_PRIORITY,
      99             :          SEC_PRIV_INCREASE_BASE_PRIORITY_BIT,
     100             :          "SeIncreaseBasePriorityPrivilege",
     101             :          "Increase base priority"},
     102             : 
     103             :         {SEC_PRIV_LOAD_DRIVER,
     104             :          SEC_PRIV_LOAD_DRIVER_BIT,
     105             :          "SeLoadDriverPrivilege",
     106             :         "Load drivers"},
     107             : 
     108             :         {SEC_PRIV_CREATE_PAGEFILE,
     109             :          SEC_PRIV_CREATE_PAGEFILE_BIT,
     110             :          "SeCreatePagefilePrivilege",
     111             :         "Create page files"},
     112             : 
     113             :         {SEC_PRIV_INCREASE_QUOTA,
     114             :          SEC_PRIV_INCREASE_QUOTA_BIT,
     115             :          "SeIncreaseQuotaPrivilege",
     116             :         "Increase quota"},
     117             : 
     118             :         {SEC_PRIV_CHANGE_NOTIFY,
     119             :          SEC_PRIV_CHANGE_NOTIFY_BIT,
     120             :          "SeChangeNotifyPrivilege",
     121             :         "Register for change notify"},
     122             : 
     123             :         {SEC_PRIV_UNDOCK,
     124             :          SEC_PRIV_UNDOCK_BIT,
     125             :          "SeUndockPrivilege",
     126             :         "Undock devices"},
     127             : 
     128             :         {SEC_PRIV_MANAGE_VOLUME,
     129             :          SEC_PRIV_MANAGE_VOLUME_BIT,
     130             :          "SeManageVolumePrivilege",
     131             :         "Manage system volumes"},
     132             : 
     133             :         {SEC_PRIV_IMPERSONATE,
     134             :          SEC_PRIV_IMPERSONATE_BIT,
     135             :          "SeImpersonatePrivilege",
     136             :         "Impersonate users"},
     137             : 
     138             :         {SEC_PRIV_CREATE_GLOBAL,
     139             :          SEC_PRIV_CREATE_GLOBAL_BIT,
     140             :          "SeCreateGlobalPrivilege",
     141             :         "Create global"},
     142             : 
     143             :         {SEC_PRIV_ENABLE_DELEGATION,
     144             :          SEC_PRIV_ENABLE_DELEGATION_BIT,
     145             :          "SeEnableDelegationPrivilege",
     146             :         "Enable Delegation"},
     147             : };
     148             : 
     149             : /* These are rights, not privileges, and should not be confused.  The
     150             :  * names are very similar, and they are quite similar in behaviour,
     151             :  * but they are not to be enumerated as a system-wide list or have an
     152             :  * LUID value */
     153             : static const struct {
     154             :         uint32_t right_mask;
     155             :         const char *name;
     156             :         const char *description;
     157             : } rights[] = {
     158             :         {LSA_POLICY_MODE_INTERACTIVE,
     159             :          "SeInteractiveLogonRight",
     160             :         "Interactive logon"},
     161             : 
     162             :         {LSA_POLICY_MODE_NETWORK,
     163             :          "SeNetworkLogonRight",
     164             :         "Network logon"},
     165             : 
     166             :         {LSA_POLICY_MODE_REMOTE_INTERACTIVE,
     167             :          "SeRemoteInteractiveLogonRight",
     168             :         "Remote Interactive logon"}
     169             : };
     170             : 
     171             : /*
     172             :   return a privilege mask given a privilege id
     173             : */
     174     1295199 : uint64_t sec_privilege_mask(enum sec_privilege privilege)
     175             : {
     176             :         int i;
     177    11770723 :         for (i=0;i<ARRAY_SIZE(privs);i++) {
     178    11770723 :                 if (privs[i].luid == privilege) {
     179     1295199 :                         return privs[i].privilege_mask;
     180             :                 }
     181             :         }
     182             : 
     183           0 :         return 0;
     184             : }
     185             : 
     186             : /***************************************************************************
     187             :  put all valid privileges into a mask
     188             : ****************************************************************************/
     189             : 
     190         119 : void se_priv_put_all_privileges(uint64_t *privilege_mask)
     191             : {
     192             :         int i;
     193             : 
     194         119 :         *privilege_mask = 0;
     195        3094 :         for ( i=0; i<ARRAY_SIZE(privs); i++ ) {
     196        2975 :                 *privilege_mask |= privs[i].privilege_mask;
     197             :         }
     198         119 : }
     199             : 
     200             : /*********************************************************************
     201             :  Lookup the uint64_t bitmask value for a privilege name
     202             : *********************************************************************/
     203             : 
     204          87 : bool se_priv_from_name( const char *name, uint64_t *privilege_mask )
     205             : {
     206             :         int i;
     207         363 :         for ( i=0; i<ARRAY_SIZE(privs); i++ ) {
     208         362 :                 if ( strequal( privs[i].name, name ) ) {
     209          86 :                         *privilege_mask = privs[i].privilege_mask;
     210          86 :                         return true;
     211             :                 }
     212             :         }
     213             : 
     214           1 :         return false;
     215             : }
     216             : 
     217          18 : const char* get_privilege_dispname( const char *name )
     218             : {
     219             :         int i;
     220             : 
     221          18 :         if (!name) {
     222           0 :                 return NULL;
     223             :         }
     224             : 
     225          90 :         for ( i=0; i<ARRAY_SIZE(privs); i++ ) {
     226          90 :                 if ( strequal( privs[i].name, name ) ) {
     227          18 :                         return privs[i].description;
     228             :                 }
     229             :         }
     230             : 
     231           0 :         return NULL;
     232             : }
     233             : 
     234             : /*******************************************************************
     235             :  return the number of elements in the 'short' privlege array (traditional source3 behaviour)
     236             : *******************************************************************/
     237             : 
     238           2 : int num_privileges_in_short_list( void )
     239             : {
     240           2 :         return NUM_SHORT_LIST_PRIVS;
     241             : }
     242             : 
     243             : /****************************************************************************
     244             :  add a privilege to a privilege array
     245             :  ****************************************************************************/
     246             : 
     247         154 : static bool privilege_set_add(PRIVILEGE_SET *priv_set, struct lsa_LUIDAttribute set)
     248             : {
     249             :         struct lsa_LUIDAttribute *new_set;
     250             : 
     251             :         /* we can allocate memory to add the new privilege */
     252             : 
     253         154 :         new_set = talloc_realloc(priv_set->mem_ctx, priv_set->set, struct lsa_LUIDAttribute, priv_set->count + 1);
     254         154 :         if ( !new_set ) {
     255           0 :                 DEBUG(0,("privilege_set_add: failed to allocate memory!\n"));
     256           0 :                 return false;
     257             :         }
     258             : 
     259         154 :         new_set[priv_set->count].luid.high = set.luid.high;
     260         154 :         new_set[priv_set->count].luid.low = set.luid.low;
     261         154 :         new_set[priv_set->count].attribute = set.attribute;
     262             : 
     263         154 :         priv_set->count++;
     264         154 :         priv_set->set = new_set;
     265             : 
     266         154 :         return true;
     267             : }
     268             : 
     269             : /*******************************************************************
     270             : *******************************************************************/
     271             : 
     272          40 : bool se_priv_to_privilege_set( PRIVILEGE_SET *set, uint64_t privilege_mask )
     273             : {
     274             :         int i;
     275             :         struct lsa_LUIDAttribute luid;
     276             : 
     277          40 :         luid.attribute = 0;
     278          40 :         luid.luid.high = 0;
     279             : 
     280        1040 :         for ( i=0; i<ARRAY_SIZE(privs); i++ ) {
     281        1000 :                 if ((privilege_mask & privs[i].privilege_mask) == 0)
     282         846 :                         continue;
     283             : 
     284         154 :                 luid.luid.high = 0;
     285         154 :                 luid.luid.low = privs[i].luid;
     286             : 
     287         154 :                 if ( !privilege_set_add( set, luid ) )
     288           0 :                         return false;
     289             :         }
     290             : 
     291          40 :         return true;
     292             : }
     293             : 
     294             : /*******************************************************************
     295             : *******************************************************************/
     296             : 
     297           4 : bool privilege_set_to_se_priv( uint64_t *privilege_mask, struct lsa_PrivilegeSet *privset )
     298             : {
     299             :         uint32_t i;
     300             : 
     301           4 :         ZERO_STRUCTP( privilege_mask );
     302             : 
     303           8 :         for ( i=0; i<privset->count; i++ ) {
     304             :                 uint64_t r;
     305             : 
     306             :                 /* sanity check for invalid privilege.  we really
     307             :                    only care about the low 32 bits */
     308             : 
     309           4 :                 if ( privset->set[i].luid.high != 0 )
     310           0 :                         return false;
     311             : 
     312           4 :                 r = sec_privilege_mask(privset->set[i].luid.low);
     313           4 :                 if (r) {
     314           4 :                         *privilege_mask |= r;
     315             :                 }
     316             :         }
     317             : 
     318           4 :         return true;
     319             : }
     320             : 
     321             : /*
     322             :   map a privilege id to the wire string constant
     323             : */
     324         573 : const char *sec_privilege_name(enum sec_privilege privilege)
     325             : {
     326             :         int i;
     327        5924 :         for (i=0;i<ARRAY_SIZE(privs);i++) {
     328        5924 :                 if (privs[i].luid == privilege) {
     329         573 :                         return privs[i].name;
     330             :                 }
     331             :         }
     332           0 :         return NULL;
     333             : }
     334             : 
     335             : /*
     336             :   map a privilege id to a privilege display name. Return NULL if not found
     337             : 
     338             :   TODO: this should use language mappings
     339             : */
     340         125 : const char *sec_privilege_display_name(enum sec_privilege privilege, uint16_t *language)
     341             : {
     342             :         int i;
     343        1625 :         for (i=0;i<ARRAY_SIZE(privs);i++) {
     344        1625 :                 if (privs[i].luid == privilege) {
     345         125 :                         return privs[i].description;
     346             :                 }
     347             :         }
     348           0 :         return NULL;
     349             : }
     350             : 
     351             : /*
     352             :   map a privilege name to a privilege id. Return SEC_PRIV_INVALID if not found
     353             : */
     354      712357 : enum sec_privilege sec_privilege_id(const char *name)
     355             : {
     356             :         int i;
     357    11785151 :         for (i=0;i<ARRAY_SIZE(privs);i++) {
     358    11670932 :                 if (strcasecmp(privs[i].name, name) == 0) {
     359      598138 :                         return privs[i].luid;
     360             :                 }
     361             :         }
     362      112080 :         return SEC_PRIV_INVALID;
     363             : }
     364             : 
     365             : /*
     366             :   map a 'right' name to it's bitmap value. Return 0 if not found
     367             : */
     368      114403 : uint32_t sec_right_bit(const char *name)
     369             : {
     370             :         int i;
     371      262731 :         for (i=0;i<ARRAY_SIZE(rights);i++) {
     372      262559 :                 if (strcasecmp(rights[i].name, name) == 0) {
     373      114231 :                         return rights[i].right_mask;
     374             :                 }
     375             :         }
     376         172 :         return 0;
     377             : }
     378             : 
     379             : /*
     380             :   assist in walking the table of privileges - return the LUID (low 32 bits) by index
     381             : */
     382         148 : enum sec_privilege sec_privilege_from_index(int idx)
     383             : {
     384         148 :         if (idx >= 0 && idx<ARRAY_SIZE(privs)) {
     385         143 :                 return privs[idx].luid;
     386             :         }
     387           5 :         return SEC_PRIV_INVALID;
     388             : }
     389             : 
     390             : /*
     391             :   assist in walking the table of privileges - return the string constant by index
     392             : */
     393          18 : const char *sec_privilege_name_from_index(int idx)
     394             : {
     395          18 :         if (idx >= 0 && idx<ARRAY_SIZE(privs)) {
     396          18 :                 return privs[idx].name;
     397             :         }
     398           0 :         return NULL;
     399             : }
     400             : 
     401             : 
     402             : 
     403             : /*
     404             :   return true if a security_token has a particular privilege bit set
     405             : */
     406      696604 : bool security_token_has_privilege(const struct security_token *token, enum sec_privilege privilege)
     407             : {
     408             :         uint64_t mask;
     409             : 
     410      696604 :         if (!token) {
     411           0 :                 return false;
     412             :         }
     413             : 
     414      696604 :         mask = sec_privilege_mask(privilege);
     415      696604 :         if (mask == 0) {
     416           0 :                 return false;
     417             :         }
     418             : 
     419      696604 :         if (token->privilege_mask & mask) {
     420      257457 :                 return true;
     421             :         }
     422      434457 :         return false;
     423             : }
     424             : 
     425         146 : bool security_token_system_privilege(const struct security_token *token)
     426             : {
     427         146 :         if (token == NULL) {
     428           0 :                 return false;
     429             :         }
     430             : 
     431         146 :         if (token->privilege_mask == (uint64_t)~0) {
     432         146 :                 return true;
     433             :         }
     434             : 
     435           0 :         return false;
     436             : }
     437             : 
     438             : /*
     439             :   set a bit in the privilege mask
     440             : */
     441      598573 : void security_token_set_privilege(struct security_token *token, enum sec_privilege privilege)
     442             : {
     443             :         /* Relies on the fact that an invalid privilage will return 0, so won't change this */
     444      598573 :         token->privilege_mask |= sec_privilege_mask(privilege);
     445      598573 : }
     446             : 
     447             : /*
     448             :   set a bit in the rights mask
     449             : */
     450      114167 : void security_token_set_right_bit(struct security_token *token, uint32_t right_bit)
     451             : {
     452      114167 :         token->rights_mask |= right_bit;
     453      114167 : }
     454             : 
     455      387280 : void security_token_debug_privileges(int dbg_class, int dbg_lev, const struct security_token *token)
     456             : {
     457      387280 :         DEBUGADDC(dbg_class, dbg_lev, (" Privileges (0x%16llX):\n",
     458             :                                        (unsigned long long) token->privilege_mask));
     459             : 
     460      387280 :         if (token->privilege_mask) {
     461      129846 :                 int idx = 0;
     462      129846 :                 int i = 0;
     463     3446171 :                 for (idx = 0; idx<ARRAY_SIZE(privs); idx++) {
     464     3316325 :                         if (token->privilege_mask & privs[idx].privilege_mask) {
     465     2516691 :                                 DEBUGADDC(dbg_class, dbg_lev,
     466             :                                           ("  Privilege[%3lu]: %s\n", (unsigned long)i++,
     467             :                                            privs[idx].name));
     468             :                         }
     469             :                 }
     470             :         }
     471      387280 :         DEBUGADDC(dbg_class, dbg_lev, (" Rights (0x%16lX):\n",
     472             :                                        (unsigned long) token->rights_mask));
     473             : 
     474      387280 :         if (token->rights_mask) {
     475      112906 :                 int idx = 0;
     476      112906 :                 int i = 0;
     477      458758 :                 for (idx = 0; idx<ARRAY_SIZE(rights); idx++) {
     478      345852 :                         if (token->rights_mask & rights[idx].right_mask) {
     479      317800 :                                 DEBUGADDC(dbg_class, dbg_lev,
     480             :                                           ("  Right[%3lu]: %s\n", (unsigned long)i++,
     481             :                                            rights[idx].name));
     482             :                         }
     483             :                 }
     484             :         }
     485      387280 : }

Generated by: LCOV version 1.13