LCOV - code coverage report
Current view: top level - libcli/security - privileges.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 80 140 57.1 %
Date: 2024-04-21 15:09:00 Functions: 13 19 68.4 %

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

Generated by: LCOV version 1.14