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

Generated by: LCOV version 1.14