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

Generated by: LCOV version 1.13