LCOV - code coverage report
Current view: top level - source3/smbd - uid.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 251 297 84.5 %
Date: 2024-05-31 13:13:24 Functions: 24 24 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    uid/user handling
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/passwd.h"
      22             : #include "smbd/smbd.h"
      23             : #include "smbd/globals.h"
      24             : #include "source3/smbd/smbXsrv_session.h"
      25             : #include "../librpc/gen_ndr/netlogon.h"
      26             : #include "libcli/security/security.h"
      27             : #include "passdb/lookup_sid.h"
      28             : #include "auth.h"
      29             : #include "../auth/auth_util.h"
      30             : #include "source3/lib/substitute.h"
      31             : 
      32             : /* what user is current? */
      33             : extern struct current_user current_user;
      34             : 
      35             : /****************************************************************************
      36             :  Become the guest user without changing the security context stack.
      37             : ****************************************************************************/
      38             : 
      39          18 : bool change_to_guest(void)
      40             : {
      41           0 :         struct passwd *pass;
      42             : 
      43          18 :         pass = Get_Pwnam_alloc(talloc_tos(), lp_guest_account());
      44          18 :         if (!pass) {
      45           0 :                 return false;
      46             :         }
      47             : 
      48             : #ifdef AIX
      49             :         /* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before 
      50             :            setting IDs */
      51             :         initgroups(pass->pw_name, pass->pw_gid);
      52             : #endif
      53             : 
      54          18 :         set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
      55             : 
      56          18 :         current_user.conn = NULL;
      57          18 :         current_user.vuid = UID_FIELD_INVALID;
      58             : 
      59          18 :         TALLOC_FREE(pass);
      60             : 
      61          18 :         return true;
      62             : }
      63             : 
      64             : /****************************************************************************
      65             :  talloc free the conn->session_info if not used in the vuid cache.
      66             : ****************************************************************************/
      67             : 
      68      106650 : static void free_conn_session_info_if_unused(connection_struct *conn)
      69             : {
      70        1622 :         unsigned int i;
      71             : 
      72     1715806 :         for (i = 0; i < VUID_CACHE_SIZE; i++) {
      73       26515 :                 struct vuid_cache_entry *ent;
      74     1665520 :                 ent = &conn->vuid_cache->array[i];
      75     1665520 :                 if (ent->vuid != UID_FIELD_INVALID &&
      76      106554 :                                 conn->session_info == ent->session_info) {
      77       55545 :                         return;
      78             :                 }
      79             :         }
      80             :         /* Not used, safe to free. */
      81       50286 :         TALLOC_FREE(conn->session_info);
      82             : }
      83             : 
      84             : /****************************************************************************
      85             :   Setup the share access mask for a connection.
      86             : ****************************************************************************/
      87             : 
      88      100330 : static uint32_t create_share_access_mask(int snum,
      89             :                                 bool readonly_share,
      90             :                                 const struct security_token *token)
      91             : {
      92      100330 :         uint32_t share_access = 0;
      93             : 
      94      100330 :         share_access_check(token,
      95             :                         lp_const_servicename(snum),
      96             :                         MAXIMUM_ALLOWED_ACCESS,
      97             :                         &share_access);
      98             : 
      99      100330 :         if (readonly_share) {
     100       55328 :                 share_access &=
     101             :                         ~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA |
     102             :                           SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE |
     103             :                           SEC_DIR_DELETE_CHILD );
     104             :         }
     105             : 
     106      100330 :         if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
     107       15316 :                 share_access |= SEC_FLAG_SYSTEM_SECURITY;
     108             :         }
     109      100330 :         if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
     110       16780 :                 share_access |= SEC_RIGHTS_PRIV_RESTORE;
     111             :         }
     112      100330 :         if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
     113       15300 :                 share_access |= SEC_RIGHTS_PRIV_BACKUP;
     114             :         }
     115      100330 :         if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
     116       15300 :                 share_access |= SEC_STD_WRITE_OWNER;
     117             :         }
     118             : 
     119      100330 :         return share_access;
     120             : }
     121             : 
     122             : /*******************************************************************
     123             :  Calculate access mask and if this user can access this share.
     124             : ********************************************************************/
     125             : 
     126      100330 : NTSTATUS check_user_share_access(connection_struct *conn,
     127             :                                 const struct auth_session_info *session_info,
     128             :                                 uint32_t *p_share_access,
     129             :                                 bool *p_readonly_share)
     130             : {
     131      100330 :         int snum = SNUM(conn);
     132      100330 :         uint32_t share_access = 0;
     133      100330 :         bool readonly_share = false;
     134             : 
     135      100330 :         if (!user_ok_token(session_info->unix_info->unix_name,
     136      100330 :                            session_info->info->domain_name,
     137      100330 :                            session_info->security_token, snum)) {
     138           0 :                 return NT_STATUS_ACCESS_DENIED;
     139             :         }
     140             : 
     141      101912 :         readonly_share = is_share_read_only_for_token(
     142      100330 :                 session_info->unix_info->unix_name,
     143      100330 :                 session_info->info->domain_name,
     144      100330 :                 session_info->security_token,
     145             :                 conn);
     146             : 
     147      101912 :         share_access = create_share_access_mask(snum,
     148             :                                         readonly_share,
     149      100330 :                                         session_info->security_token);
     150             : 
     151      100330 :         if ((share_access & (FILE_READ_DATA|FILE_WRITE_DATA)) == 0) {
     152             :                 /* No access, read or write. */
     153           6 :                 DBG_NOTICE("user %s connection to %s denied due to share "
     154             :                          "security descriptor.\n",
     155             :                          session_info->unix_info->unix_name,
     156             :                          lp_const_servicename(snum));
     157           6 :                 return NT_STATUS_ACCESS_DENIED;
     158             :         }
     159             : 
     160      100324 :         if (!readonly_share &&
     161       44996 :             !(share_access & FILE_WRITE_DATA)) {
     162             :                 /* smb.conf allows r/w, but the security descriptor denies
     163             :                  * write. Fall back to looking at readonly. */
     164           6 :                 readonly_share = true;
     165           6 :                 DBG_INFO("falling back to read-only access-evaluation due to "
     166             :                          "security descriptor\n");
     167             :         }
     168             : 
     169      100324 :         *p_share_access = share_access;
     170      100324 :         *p_readonly_share = readonly_share;
     171             : 
     172      100324 :         return NT_STATUS_OK;
     173             : }
     174             : 
     175             : /*******************************************************************
     176             :  Check if a username is OK.
     177             : 
     178             :  This sets up conn->session_info with a copy related to this vuser that
     179             :  later code can then mess with.
     180             : ********************************************************************/
     181             : 
     182      106650 : static bool check_user_ok(connection_struct *conn,
     183             :                         uint64_t vuid,
     184             :                         const struct auth_session_info *session_info,
     185             :                         int snum)
     186             : {
     187        1622 :         unsigned int i;
     188      106650 :         bool readonly_share = false;
     189      106650 :         bool admin_user = false;
     190      106650 :         struct vuid_cache_entry *ent = NULL;
     191      106650 :         uint32_t share_access = 0;
     192        1622 :         NTSTATUS status;
     193             : 
     194     1716250 :         for (i=0; i<VUID_CACHE_SIZE; i++) {
     195     1665950 :                 ent = &conn->vuid_cache->array[i];
     196     1665950 :                 if (ent->vuid == vuid) {
     197       59550 :                         if (vuid == UID_FIELD_INVALID) {
     198             :                                 /*
     199             :                                  * Slow path, we don't care
     200             :                                  * about the array traversal.
     201             :                                 */
     202        3200 :                                 continue;
     203             :                         }
     204       56350 :                         free_conn_session_info_if_unused(conn);
     205       56350 :                         conn->session_info = ent->session_info;
     206       56350 :                         conn->read_only = ent->read_only;
     207       56350 :                         conn->share_access = ent->share_access;
     208       56350 :                         conn->vuid = ent->vuid;
     209       56350 :                         return(True);
     210             :                 }
     211             :         }
     212             : 
     213       50300 :         status = check_user_share_access(conn,
     214             :                                         session_info,
     215             :                                         &share_access,
     216             :                                         &readonly_share);
     217       50300 :         if (!NT_STATUS_IS_OK(status)) {
     218           0 :                 return false;
     219             :         }
     220             : 
     221       50300 :         admin_user = token_contains_name_in_list(
     222       50300 :                 session_info->unix_info->unix_name,
     223       50300 :                 session_info->info->domain_name,
     224       50300 :                 NULL, session_info->security_token, lp_admin_users(snum));
     225             : 
     226       50300 :         ent = &conn->vuid_cache->array[conn->vuid_cache->next_entry];
     227             : 
     228       50300 :         conn->vuid_cache->next_entry =
     229       50300 :                 (conn->vuid_cache->next_entry + 1) % VUID_CACHE_SIZE;
     230             : 
     231       50300 :         TALLOC_FREE(ent->session_info);
     232             : 
     233             :         /*
     234             :          * If force_user was set, all session_info's are based on the same
     235             :          * username-based faked one.
     236             :          */
     237             : 
     238       50300 :         ent->session_info = copy_session_info(
     239       50300 :                 conn, conn->force_user ? conn->session_info : session_info);
     240             : 
     241       50300 :         if (ent->session_info == NULL) {
     242           0 :                 ent->vuid = UID_FIELD_INVALID;
     243           0 :                 return false;
     244             :         }
     245             : 
     246       50300 :         if (admin_user) {
     247          88 :                 DEBUG(2,("check_user_ok: user %s is an admin user. "
     248             :                         "Setting uid as %d\n",
     249             :                         ent->session_info->unix_info->unix_name,
     250             :                         sec_initial_uid() ));
     251          88 :                 ent->session_info->unix_token->uid = sec_initial_uid();
     252             :         }
     253             : 
     254             :         /*
     255             :          * It's actually OK to call check_user_ok() with
     256             :          * vuid == UID_FIELD_INVALID as called from become_user_by_session().
     257             :          * All this will do is throw away one entry in the cache.
     258             :          */
     259             : 
     260       50300 :         ent->vuid = vuid;
     261       50300 :         ent->read_only = readonly_share;
     262       50300 :         ent->share_access = share_access;
     263       50300 :         free_conn_session_info_if_unused(conn);
     264       50300 :         conn->session_info = ent->session_info;
     265       50300 :         conn->vuid = ent->vuid;
     266       50300 :         if (vuid == UID_FIELD_INVALID) {
     267             :                 /*
     268             :                  * Not strictly needed, just make it really
     269             :                  * clear this entry is actually an unused one.
     270             :                  */
     271         100 :                 ent->read_only = false;
     272         100 :                 ent->share_access = 0;
     273         100 :                 ent->session_info = NULL;
     274             :         }
     275             : 
     276       50300 :         conn->read_only = readonly_share;
     277       50300 :         conn->share_access = share_access;
     278             : 
     279       50300 :         return(True);
     280             : }
     281             : 
     282     1850492 : static void print_impersonation_info(connection_struct *conn)
     283             : {
     284     1850492 :         struct smb_filename *cwdfname = NULL;
     285             : 
     286     1850492 :         if (!CHECK_DEBUGLVL(DBGLVL_INFO)) {
     287     1833351 :                 return;
     288             :         }
     289             : 
     290           0 :         cwdfname = vfs_GetWd(talloc_tos(), conn);
     291           0 :         if (cwdfname == NULL) {
     292           0 :                 return;
     293             :         }
     294             : 
     295           0 :         DBG_INFO("Impersonated user: uid=(%d,%d), gid=(%d,%d), cwd=[%s]\n",
     296             :                  (int)getuid(),
     297             :                  (int)geteuid(),
     298             :                  (int)getgid(),
     299             :                  (int)getegid(),
     300             :                  cwdfname->base_name);
     301           0 :         TALLOC_FREE(cwdfname);
     302             : }
     303             : 
     304             : /****************************************************************************
     305             :  Become the user of a connection number without changing the security context
     306             :  stack, but modify the current_user entries.
     307             : ****************************************************************************/
     308             : 
     309     1850704 : static bool change_to_user_impersonate(connection_struct *conn,
     310             :                                        const struct auth_session_info *session_info,
     311             :                                        uint64_t vuid)
     312             : {
     313       17141 :         const struct loadparm_substitution *lp_sub =
     314     1850704 :                 loadparm_s3_global_substitution();
     315       17141 :         int snum;
     316       17141 :         gid_t gid;
     317       17141 :         uid_t uid;
     318       17141 :         const char *force_group_name;
     319       17141 :         char group_c;
     320     1850704 :         int num_groups = 0;
     321     1850704 :         gid_t *group_list = NULL;
     322       17141 :         bool ok;
     323             : 
     324     1850704 :         if ((current_user.conn == conn) &&
     325     1744111 :             (current_user.vuid == vuid) &&
     326     1744107 :             (current_user.ut.uid == session_info->unix_token->uid))
     327             :         {
     328     1744054 :                 DBG_INFO("Skipping user change - already user\n");
     329     1744054 :                 return true;
     330             :         }
     331             : 
     332      106650 :         set_current_user_info(session_info->unix_info->sanitized_username,
     333      106650 :                               session_info->unix_info->unix_name,
     334      106650 :                               session_info->info->domain_name);
     335             : 
     336      106650 :         snum = SNUM(conn);
     337             : 
     338      106650 :         ok = check_user_ok(conn, vuid, session_info, snum);
     339      106650 :         if (!ok) {
     340           0 :                 DBG_WARNING("SMB user %s (unix user %s) "
     341             :                          "not permitted access to share %s.\n",
     342             :                          session_info->unix_info->sanitized_username,
     343             :                          session_info->unix_info->unix_name,
     344             :                          lp_const_servicename(snum));
     345           0 :                 return false;
     346             :         }
     347             : 
     348      106650 :         uid = conn->session_info->unix_token->uid;
     349      106650 :         gid = conn->session_info->unix_token->gid;
     350      106650 :         num_groups = conn->session_info->unix_token->ngroups;
     351      106650 :         group_list  = conn->session_info->unix_token->groups;
     352             : 
     353             :         /*
     354             :          * See if we should force group for this service. If so this overrides
     355             :          * any group set in the force user code.
     356             :          */
     357      106650 :         force_group_name = lp_force_group(talloc_tos(), lp_sub, snum);
     358      106650 :         group_c = *force_group_name;
     359             : 
     360      106650 :         if ((group_c != '\0') && (conn->force_group_gid == (gid_t)-1)) {
     361             :                 /*
     362             :                  * This can happen if "force group" is added to a
     363             :                  * share definition whilst an existing connection
     364             :                  * to that share exists. In that case, don't change
     365             :                  * the existing credentials for force group, only
     366             :                  * do so for new connections.
     367             :                  *
     368             :                  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13690
     369             :                  */
     370           5 :                 DBG_INFO("Not forcing group %s on existing connection to "
     371             :                         "share %s for SMB user %s (unix user %s)\n",
     372             :                         force_group_name,
     373             :                         lp_const_servicename(snum),
     374             :                         session_info->unix_info->sanitized_username,
     375             :                         session_info->unix_info->unix_name);
     376             :         }
     377             : 
     378      106650 :         if((group_c != '\0') && (conn->force_group_gid != (gid_t)-1)) {
     379             :                 /*
     380             :                  * Only force group for connections where
     381             :                  * conn->force_group_gid has already been set
     382             :                  * to the correct value (i.e. the connection
     383             :                  * happened after the 'force group' definition
     384             :                  * was added to the share definition. Connections
     385             :                  * that were made before force group was added
     386             :                  * should stay with their existing credentials.
     387             :                  *
     388             :                  * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13690
     389             :                  */
     390             : 
     391         252 :                 if (group_c == '+') {
     392             :                         int i;
     393             : 
     394             :                         /*
     395             :                          * Only force group if the user is a member of the
     396             :                          * service group. Check the group memberships for this
     397             :                          * user (we already have this) to see if we should force
     398             :                          * the group.
     399             :                          */
     400           0 :                         for (i = 0; i < num_groups; i++) {
     401           0 :                                 if (group_list[i] == conn->force_group_gid) {
     402           0 :                                         conn->session_info->unix_token->gid =
     403           0 :                                                 conn->force_group_gid;
     404           0 :                                         gid = conn->force_group_gid;
     405           0 :                                         gid_to_sid(&conn->session_info->security_token
     406           0 :                                                    ->sids[1], gid);
     407           0 :                                         break;
     408             :                                 }
     409             :                         }
     410             :                 } else {
     411         252 :                         conn->session_info->unix_token->gid = conn->force_group_gid;
     412         252 :                         gid = conn->force_group_gid;
     413         252 :                         gid_to_sid(&conn->session_info->security_token->sids[1],
     414             :                                    gid);
     415             :                 }
     416             :         }
     417             : 
     418      106650 :         set_sec_ctx(uid,
     419             :                     gid,
     420             :                     num_groups,
     421             :                     group_list,
     422      106650 :                     conn->session_info->security_token);
     423             : 
     424      106650 :         current_user.conn = conn;
     425      106650 :         current_user.vuid = vuid;
     426      106650 :         return true;
     427             : }
     428             : 
     429             : /**
     430             :  * Impersonate user and change directory to service
     431             :  *
     432             :  * change_to_user_and_service() is used to impersonate the user associated with
     433             :  * the given vuid and to change the working directory of the process to the
     434             :  * service base directory.
     435             :  **/
     436     1850609 : bool change_to_user_and_service(connection_struct *conn, uint64_t vuid)
     437             : {
     438     1850609 :         int snum = SNUM(conn);
     439     1850609 :         struct auth_session_info *si = NULL;
     440       17142 :         NTSTATUS status;
     441       17142 :         bool ok;
     442             : 
     443     1850609 :         if (conn == NULL) {
     444           0 :                 DBG_WARNING("Connection not open\n");
     445           0 :                 return false;
     446             :         }
     447             : 
     448     1850609 :         status = smbXsrv_session_info_lookup(conn->sconn->client,
     449             :                                              vuid,
     450             :                                              &si);
     451     1850609 :         if (!NT_STATUS_IS_OK(status)) {
     452          17 :                 DBG_WARNING("Invalid vuid %llu used on share %s.\n",
     453             :                             (unsigned long long)vuid,
     454             :                             lp_const_servicename(snum));
     455          17 :                 return false;
     456             :         }
     457             : 
     458     1850592 :         ok = change_to_user_impersonate(conn, si, vuid);
     459     1850592 :         if (!ok) {
     460           0 :                 return false;
     461             :         }
     462             : 
     463     1850592 :         if (conn->tcon_done) {
     464     1800586 :                 ok = chdir_current_service(conn);
     465     1800586 :                 if (!ok) {
     466         100 :                         return false;
     467             :                 }
     468             :         }
     469             : 
     470     1850492 :         print_impersonation_info(conn);
     471     1850492 :         return true;
     472             : }
     473             : 
     474             : /**
     475             :  * Impersonate user and change directory to service
     476             :  *
     477             :  * change_to_user_and_service_by_fsp() is used to impersonate the user
     478             :  * associated with the given vuid and to change the working directory of the
     479             :  * process to the service base directory.
     480             :  **/
     481       91839 : bool change_to_user_and_service_by_fsp(struct files_struct *fsp)
     482             : {
     483       91839 :         return change_to_user_and_service(fsp->conn, fsp->vuid);
     484             : }
     485             : 
     486             : /****************************************************************************
     487             :  Go back to being root without changing the security context stack,
     488             :  but modify the current_user entries.
     489             : ****************************************************************************/
     490             : 
     491      803403 : bool smbd_change_to_root_user(void)
     492             : {
     493      803403 :         set_root_sec_ctx();
     494             : 
     495      803403 :         DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
     496             :                 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
     497             : 
     498      803403 :         current_user.conn = NULL;
     499      803403 :         current_user.vuid = UID_FIELD_INVALID;
     500             : 
     501      803403 :         return(True);
     502             : }
     503             : 
     504             : /****************************************************************************
     505             :  Become the user of an authenticated connected named pipe.
     506             :  When this is called we are currently running as the connection
     507             :  user. Doesn't modify current_user.
     508             : ****************************************************************************/
     509             : 
     510      613648 : bool smbd_become_authenticated_pipe_user(struct auth_session_info *session_info)
     511             : {
     512      613648 :         if (!push_sec_ctx())
     513           0 :                 return False;
     514             : 
     515      613648 :         set_current_user_info(session_info->unix_info->sanitized_username,
     516      613648 :                               session_info->unix_info->unix_name,
     517      613648 :                               session_info->info->domain_name);
     518             : 
     519      613648 :         set_sec_ctx(session_info->unix_token->uid, session_info->unix_token->gid,
     520      613648 :                     session_info->unix_token->ngroups, session_info->unix_token->groups,
     521      613648 :                     session_info->security_token);
     522             : 
     523      613648 :         DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
     524             :                  (int)getuid(),
     525             :                  (int)geteuid(),
     526             :                  (int)getgid(),
     527             :                  (int)getegid()));
     528             : 
     529      613648 :         return True;
     530             : }
     531             : 
     532             : /****************************************************************************
     533             :  Unbecome the user of an authenticated connected named pipe.
     534             :  When this is called we are running as the authenticated pipe
     535             :  user and need to go back to being the connection user. Doesn't modify
     536             :  current_user.
     537             : ****************************************************************************/
     538             : 
     539      613648 : bool smbd_unbecome_authenticated_pipe_user(void)
     540             : {
     541      613648 :         return pop_sec_ctx();
     542             : }
     543             : 
     544             : /****************************************************************************
     545             :  Utility functions used by become_xxx/unbecome_xxx.
     546             : ****************************************************************************/
     547             : 
     548     3959335 : static void push_conn_ctx(void)
     549             : {
     550        7724 :         struct conn_ctx *ctx_p;
     551        7724 :         extern userdom_struct current_user_info;
     552             : 
     553             :         /* Check we don't overflow our stack */
     554             : 
     555     3959335 :         if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
     556           0 :                 DEBUG(0, ("Connection context stack overflow!\n"));
     557           0 :                 smb_panic("Connection context stack overflow!\n");
     558             :         }
     559             : 
     560             :         /* Store previous user context */
     561     3959335 :         ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
     562             : 
     563     3959335 :         ctx_p->conn = current_user.conn;
     564     3959335 :         ctx_p->vuid = current_user.vuid;
     565     3959335 :         ctx_p->user_info = current_user_info;
     566             : 
     567     3959335 :         DEBUG(4, ("push_conn_ctx(%llu) : conn_ctx_stack_ndx = %d\n",
     568             :                 (unsigned long long)ctx_p->vuid, conn_ctx_stack_ndx));
     569             : 
     570     3959335 :         conn_ctx_stack_ndx++;
     571     3959335 : }
     572             : 
     573     3959329 : static void pop_conn_ctx(void)
     574             : {
     575        7724 :         struct conn_ctx *ctx_p;
     576             : 
     577             :         /* Check for stack underflow. */
     578             : 
     579     3959329 :         if (conn_ctx_stack_ndx == 0) {
     580           0 :                 DEBUG(0, ("Connection context stack underflow!\n"));
     581           0 :                 smb_panic("Connection context stack underflow!\n");
     582             :         }
     583             : 
     584     3959329 :         conn_ctx_stack_ndx--;
     585     3959329 :         ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
     586             : 
     587     3959329 :         set_current_user_info(ctx_p->user_info.smb_name,
     588     3959329 :                               ctx_p->user_info.unix_name,
     589     3959329 :                               ctx_p->user_info.domain);
     590             : 
     591     3959329 :         current_user.conn = ctx_p->conn;
     592     3959329 :         current_user.vuid = ctx_p->vuid;
     593             : 
     594     3959329 :         *ctx_p = (struct conn_ctx) {
     595             :                 .vuid = UID_FIELD_INVALID,
     596             :         };
     597     3959329 : }
     598             : 
     599             : /****************************************************************************
     600             :  Temporarily become a root user.  Must match with unbecome_root(). Saves and
     601             :  restores the connection context.
     602             : ****************************************************************************/
     603             : 
     604     3959223 : void smbd_become_root(void)
     605             : {
     606             :          /*
     607             :           * no good way to handle push_sec_ctx() failing without changing
     608             :           * the prototype of become_root()
     609             :           */
     610     3959223 :         if (!push_sec_ctx()) {
     611           0 :                 smb_panic("become_root: push_sec_ctx failed");
     612             :         }
     613     3959223 :         push_conn_ctx();
     614     3959223 :         set_root_sec_ctx();
     615     3959223 : }
     616             : 
     617             : /* Unbecome the root user */
     618             : 
     619     3959223 : void smbd_unbecome_root(void)
     620             : {
     621     3959223 :         pop_sec_ctx();
     622     3959223 :         pop_conn_ctx();
     623     3959223 : }
     624             : 
     625             : /****************************************************************************
     626             :  Push the current security context then force a change via change_to_user().
     627             :  Saves and restores the connection context.
     628             : ****************************************************************************/
     629             : 
     630          12 : bool become_user_without_service(connection_struct *conn, uint64_t vuid)
     631             : {
     632          12 :         struct auth_session_info *session_info = NULL;
     633          12 :         int snum = SNUM(conn);
     634           0 :         NTSTATUS status;
     635           0 :         bool ok;
     636             : 
     637          12 :         if (conn == NULL) {
     638           0 :                 DBG_WARNING("Connection not open\n");
     639           0 :                 return false;
     640             :         }
     641             : 
     642          12 :         status = smbXsrv_session_info_lookup(conn->sconn->client,
     643             :                                              vuid,
     644             :                                              &session_info);
     645          12 :         if (!NT_STATUS_IS_OK(status)) {
     646             :                 /* Invalid vuid sent */
     647           0 :                 DBG_WARNING("Invalid vuid %llu used on share %s.\n",
     648             :                             (unsigned long long)vuid,
     649             :                             lp_const_servicename(snum));
     650           0 :                 return false;
     651             :         }
     652             : 
     653          12 :         ok = push_sec_ctx();
     654          12 :         if (!ok) {
     655           0 :                 return false;
     656             :         }
     657             : 
     658          12 :         push_conn_ctx();
     659             : 
     660          12 :         ok = change_to_user_impersonate(conn, session_info, vuid);
     661          12 :         if (!ok) {
     662           0 :                 pop_sec_ctx();
     663           0 :                 pop_conn_ctx();
     664           0 :                 return false;
     665             :         }
     666             : 
     667          12 :         return true;
     668             : }
     669             : 
     670          12 : bool become_user_without_service_by_fsp(struct files_struct *fsp)
     671             : {
     672          12 :         return become_user_without_service(fsp->conn, fsp->vuid);
     673             : }
     674             : 
     675         100 : bool become_user_without_service_by_session(connection_struct *conn,
     676             :                             const struct auth_session_info *session_info)
     677             : {
     678           0 :         bool ok;
     679             : 
     680         100 :         SMB_ASSERT(conn != NULL);
     681         100 :         SMB_ASSERT(session_info != NULL);
     682             : 
     683         100 :         ok = push_sec_ctx();
     684         100 :         if (!ok) {
     685           0 :                 return false;
     686             :         }
     687             : 
     688         100 :         push_conn_ctx();
     689             : 
     690         100 :         ok = change_to_user_impersonate(conn, session_info, UID_FIELD_INVALID);
     691         100 :         if (!ok) {
     692           0 :                 pop_sec_ctx();
     693           0 :                 pop_conn_ctx();
     694           0 :                 return false;
     695             :         }
     696             : 
     697         100 :         return true;
     698             : }
     699             : 
     700         106 : bool unbecome_user_without_service(void)
     701             : {
     702         106 :         pop_sec_ctx();
     703         106 :         pop_conn_ctx();
     704         106 :         return True;
     705             : }
     706             : 
     707             : /****************************************************************************
     708             :  Return the current user we are running effectively as on this connection.
     709             :  I'd like to make this return conn->session_info->unix_token->uid, but become_root()
     710             :  doesn't alter this value.
     711             : ****************************************************************************/
     712             : 
     713     1212429 : uid_t get_current_uid(connection_struct *conn)
     714             : {
     715     1212429 :         return current_user.ut.uid;
     716             : }
     717             : 
     718             : /****************************************************************************
     719             :  Return the current group we are running effectively as on this connection.
     720             :  I'd like to make this return conn->session_info->unix_token->gid, but become_root()
     721             :  doesn't alter this value.
     722             : ****************************************************************************/
     723             : 
     724        5450 : gid_t get_current_gid(connection_struct *conn)
     725             : {
     726        5450 :         return current_user.ut.gid;
     727             : }
     728             : 
     729             : /****************************************************************************
     730             :  Return the UNIX token we are running effectively as on this connection.
     731             :  I'd like to make this return &conn->session_info->unix_token-> but become_root()
     732             :  doesn't alter this value.
     733             : ****************************************************************************/
     734             : 
     735      171107 : const struct security_unix_token *get_current_utok(connection_struct *conn)
     736             : {
     737      171107 :         return &current_user.ut;
     738             : }
     739             : 
     740             : /****************************************************************************
     741             :  Return the Windows token we are running effectively as on this connection.
     742             :  If this is currently a NULL token as we're inside become_root() - a temporary
     743             :  UNIX security override, then we search up the stack for the previous active
     744             :  token.
     745             : ****************************************************************************/
     746             : 
     747      672675 : const struct security_token *get_current_nttok(connection_struct *conn)
     748             : {
     749      672675 :         if (current_user.nt_user_token) {
     750      670872 :                 return current_user.nt_user_token;
     751             :         }
     752           0 :         return sec_ctx_active_token();
     753             : }

Generated by: LCOV version 1.14