LCOV - code coverage report
Current view: top level - source3/smbd - smb2_service.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 257 420 61.2 %
Date: 2024-06-13 04:01:37 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    service (connection) opening and closing
       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/filesys.h"
      22             : #include "system/passwd.h" /* uid_wrapper */
      23             : #include "../lib/tsocket/tsocket.h"
      24             : #include "smbd/smbd.h"
      25             : #include "smbd/globals.h"
      26             : #include "../librpc/gen_ndr/netlogon.h"
      27             : #include "../libcli/security/security.h"
      28             : #include "printing/pcap.h"
      29             : #include "passdb/lookup_sid.h"
      30             : #include "auth.h"
      31             : #include "../auth/auth_util.h"
      32             : #include "lib/param/loadparm.h"
      33             : #include "messages.h"
      34             : #include "lib/afs/afs_funcs.h"
      35             : #include "lib/util_path.h"
      36             : #include "lib/util/string_wrappers.h"
      37             : #include "source3/lib/substitute.h"
      38             : 
      39       13589 : bool canonicalize_connect_path(connection_struct *conn)
      40             : {
      41             :         bool ret;
      42       13589 :         struct smb_filename con_fname = { .base_name = conn->connectpath };
      43       13589 :         struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
      44             :                                                 &con_fname);
      45       13589 :         if (resolved_fname == NULL) {
      46           0 :                 return false;
      47             :         }
      48       13589 :         ret = set_conn_connectpath(conn,resolved_fname->base_name);
      49       13589 :         TALLOC_FREE(resolved_fname);
      50       13589 :         return ret;
      51             : }
      52             : 
      53             : /****************************************************************************
      54             :  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
      55             :  absolute path stating in / and not ending in /.
      56             : ****************************************************************************/
      57             : 
      58       21555 : bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
      59             : {
      60             :         char *destname;
      61             : 
      62       21555 :         if (connectpath == NULL || connectpath[0] == '\0') {
      63           0 :                 return false;
      64             :         }
      65             : 
      66       21555 :         destname = canonicalize_absolute_path(conn, connectpath);
      67       21555 :         if (destname == NULL) {
      68           0 :                 return false;
      69             :         }
      70             : 
      71       21555 :         DBG_DEBUG("service %s, connectpath = %s\n",
      72             :                   lp_const_servicename(SNUM(conn)), destname);
      73             : 
      74       21555 :         talloc_free(conn->connectpath);
      75       21555 :         conn->connectpath = destname;
      76             :         /*
      77             :          * Ensure conn->cwd_fsp->fsp_name is initialized.
      78             :          * start as conn->connectpath.
      79             :          */
      80       21555 :         TALLOC_FREE(conn->cwd_fsp->fsp_name);
      81       28220 :         conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn,
      82       21555 :                                 conn->connectpath,
      83             :                                 NULL,
      84             :                                 NULL,
      85             :                                 0,
      86             :                                 0);
      87       21555 :         if (conn->cwd_fsp->fsp_name == NULL) {
      88           0 :                 return false;
      89             :         }
      90       21555 :         return true;
      91             : }
      92             : 
      93             : /****************************************************************************
      94             :  Load parameters specific to a connection/service.
      95             : ****************************************************************************/
      96             : 
      97          12 : void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
      98             : {
      99             :         int snum;
     100             :         enum remote_arch_types ra_type;
     101             : 
     102          12 :         SMB_ASSERT(conn != NULL);
     103             : 
     104          12 :         snum = SNUM(conn);
     105             : 
     106          12 :         if ((conn == last_conn) && (last_flags == flags)) {
     107           2 :                 return;
     108             :         }
     109             : 
     110          10 :         last_conn = conn;
     111          10 :         last_flags = flags;
     112             : 
     113             :         /*
     114             :          * Obey the client case sensitivity requests - only for clients that
     115             :          * support it. */
     116          10 :         switch (lp_case_sensitive(snum)) {
     117          10 :         case Auto:
     118             :                 /*
     119             :                  * We need this uglyness due to DOS/Win9x clients that lie
     120             :                  * about case insensitivity. */
     121          10 :                 ra_type = get_remote_arch();
     122          10 :                 if (conn->sconn->using_smb2) {
     123           0 :                         conn->case_sensitive = false;
     124          10 :                 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
     125             :                         /*
     126             :                          * Client can't support per-packet case sensitive
     127             :                          * pathnames. */
     128           0 :                         conn->case_sensitive = false;
     129             :                 } else {
     130          10 :                         conn->case_sensitive =
     131          10 :                                         !(flags & FLAG_CASELESS_PATHNAMES);
     132             :                 }
     133          10 :         break;
     134           0 :         case True:
     135           0 :                 conn->case_sensitive = true;
     136           0 :                 break;
     137           0 :         default:
     138           0 :                 conn->case_sensitive = false;
     139           0 :                 break;
     140             :         }
     141          10 :         return;
     142             : }
     143             : 
     144      139479 : bool chdir_current_service(connection_struct *conn)
     145             : {
     146      247605 :         const struct smb_filename connectpath_fname = {
     147      139479 :                 .base_name = conn->connectpath,
     148             :         };
     149      139479 :         int saved_errno = 0;
     150      139479 :         char *utok_str = NULL;
     151             :         int ret;
     152             : 
     153      139479 :         conn->lastused_count++;
     154             : 
     155      139479 :         ret = vfs_ChDir(conn, &connectpath_fname);
     156      139479 :         if (ret == 0) {
     157      139447 :                 return true;
     158             :         }
     159          32 :         saved_errno = errno;
     160             : 
     161          32 :         utok_str = utok_string(talloc_tos(),
     162          32 :                                conn->session_info->unix_token);
     163          32 :         if (utok_str == NULL) {
     164           0 :                 errno = saved_errno;
     165           0 :                 return false;
     166             :         }
     167             : 
     168          32 :         DBG_ERR("vfs_ChDir(%s) failed: %s. Current token: %s\n",
     169             :                 conn->connectpath,
     170             :                 strerror(saved_errno),
     171             :                 utok_str);
     172             : 
     173          32 :         if (saved_errno != 0) {
     174          32 :                 errno = saved_errno;
     175             :         }
     176          32 :         return false;
     177             : }
     178             : 
     179             : /****************************************************************************
     180             :  do some basic sainity checks on the share.  
     181             :  This function modifies dev, ecode.
     182             : ****************************************************************************/
     183             : 
     184        5635 : static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
     185             :                                     const char *rhost,
     186             :                                     int snum,
     187             :                                     fstring dev)
     188             : {
     189             :         char *raddr;
     190             : 
     191        5635 :         raddr = tsocket_address_inet_addr_string(remote_address,
     192             :                                                  talloc_tos());
     193        5635 :         if (raddr == NULL) {
     194           0 :                 return NT_STATUS_NO_MEMORY;
     195             :         }
     196             : 
     197        9457 :         if (!lp_snum_ok(snum) ||
     198        5635 :             !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
     199             :                           rhost, raddr)) {
     200           0 :                 return NT_STATUS_ACCESS_DENIED;
     201             :         }
     202             : 
     203        5635 :         if (dev[0] == '?' || !dev[0]) {
     204        5635 :                 if (lp_printable(snum)) {
     205           0 :                         fstrcpy(dev,"LPT1:");
     206        5635 :                 } else if (strequal(lp_fstype(snum), "IPC")) {
     207        4069 :                         fstrcpy(dev, "IPC");
     208             :                 } else {
     209        1566 :                         fstrcpy(dev,"A:");
     210             :                 }
     211             :         }
     212             : 
     213        5635 :         if (!strupper_m(dev)) {
     214           0 :                 DEBUG(2,("strupper_m %s failed\n", dev));
     215           0 :                 return NT_STATUS_INVALID_PARAMETER;
     216             :         }
     217             : 
     218        5635 :         if (lp_printable(snum)) {
     219           0 :                 if (!strequal(dev, "LPT1:")) {
     220           0 :                         return NT_STATUS_BAD_DEVICE_TYPE;
     221             :                 }
     222        5635 :         } else if (strequal(lp_fstype(snum), "IPC")) {
     223        4069 :                 if (!strequal(dev, "IPC")) {
     224           0 :                         return NT_STATUS_BAD_DEVICE_TYPE;
     225             :                 }
     226        1566 :         } else if (!strequal(dev, "A:")) {
     227           0 :                 return NT_STATUS_BAD_DEVICE_TYPE;
     228             :         }
     229             : 
     230             :         /* Behave as a printer if we are supposed to */
     231        5635 :         if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
     232           0 :                 fstrcpy(dev, "LPT1:");
     233             :         }
     234             : 
     235        5635 :         return NT_STATUS_OK;
     236             : }
     237             : 
     238             : /*
     239             :  * Go through lookup_name etc to find the force'd group.  
     240             :  *
     241             :  * Create a new token from src_token, replacing the primary group sid with the
     242             :  * one found.
     243             :  */
     244             : 
     245          42 : static NTSTATUS find_forced_group(bool force_user,
     246             :                                   int snum, const char *username,
     247             :                                   struct dom_sid *pgroup_sid,
     248             :                                   gid_t *pgid)
     249             : {
     250          42 :         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
     251          42 :         TALLOC_CTX *frame = talloc_stackframe();
     252          23 :         const struct loadparm_substitution *lp_sub =
     253          19 :                 loadparm_s3_global_substitution();
     254             :         struct dom_sid group_sid;
     255             :         enum lsa_SidType type;
     256             :         char *groupname;
     257          42 :         bool user_must_be_member = False;
     258             :         gid_t gid;
     259             : 
     260          42 :         groupname = lp_force_group(talloc_tos(), lp_sub, snum);
     261          42 :         if (groupname == NULL) {
     262           0 :                 DEBUG(1, ("talloc_strdup failed\n"));
     263           0 :                 result = NT_STATUS_NO_MEMORY;
     264           0 :                 goto done;
     265             :         }
     266             : 
     267          42 :         if (groupname[0] == '+') {
     268           0 :                 user_must_be_member = True;
     269           0 :                 groupname += 1;
     270             :         }
     271             : 
     272          42 :         groupname = talloc_string_sub(talloc_tos(), groupname,
     273             :                                       "%S", lp_const_servicename(snum));
     274          42 :         if (groupname == NULL) {
     275           0 :                 DEBUG(1, ("talloc_string_sub failed\n"));
     276           0 :                 result = NT_STATUS_NO_MEMORY;
     277           0 :                 goto done;
     278             :         }
     279             : 
     280          42 :         if (!lookup_name_smbconf(talloc_tos(), groupname,
     281             :                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
     282             :                          NULL, NULL, &group_sid, &type)) {
     283           0 :                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
     284             :                            groupname));
     285           0 :                 goto done;
     286             :         }
     287             : 
     288          42 :         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
     289           0 :             (type != SID_NAME_WKN_GRP)) {
     290           0 :                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
     291             :                            sid_type_lookup(type)));
     292           0 :                 goto done;
     293             :         }
     294             : 
     295          42 :         if (!sid_to_gid(&group_sid, &gid)) {
     296             :                 struct dom_sid_buf buf;
     297           0 :                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
     298             :                            dom_sid_str_buf(&group_sid, &buf), groupname));
     299           0 :                 goto done;
     300             :         }
     301             : 
     302             :         /*
     303             :          * If the user has been forced and the forced group starts with a '+',
     304             :          * then we only set the group to be the forced group if the forced
     305             :          * user is a member of that group.  Otherwise, the meaning of the '+'
     306             :          * would be ignored.
     307             :          */
     308             : 
     309          42 :         if (force_user && user_must_be_member) {
     310           0 :                 if (user_in_group_sid(username, &group_sid)) {
     311           0 :                         sid_copy(pgroup_sid, &group_sid);
     312           0 :                         *pgid = gid;
     313           0 :                         DEBUG(3,("Forced group %s for member %s\n",
     314             :                                  groupname, username));
     315             :                 } else {
     316           0 :                         DEBUG(0,("find_forced_group: forced user %s is not a member "
     317             :                                 "of forced group %s. Disallowing access.\n",
     318             :                                 username, groupname ));
     319           0 :                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
     320           0 :                         goto done;
     321             :                 }
     322             :         } else {
     323          42 :                 sid_copy(pgroup_sid, &group_sid);
     324          42 :                 *pgid = gid;
     325          42 :                 DEBUG(3,("Forced group %s\n", groupname));
     326             :         }
     327             : 
     328          42 :         result = NT_STATUS_OK;
     329          42 :  done:
     330          42 :         TALLOC_FREE(frame);
     331          42 :         return result;
     332             : }
     333             : 
     334             : /****************************************************************************
     335             :   Create an auth_session_info structure for a connection_struct
     336             : ****************************************************************************/
     337             : 
     338        5635 : static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
     339             :                                               TALLOC_CTX *mem_ctx, int snum,
     340             :                                               struct auth_session_info *session_info,
     341             :                                               struct auth_session_info **presult)
     342             : {
     343             :         struct auth_session_info *result;
     344             : 
     345        5635 :         if (lp_guest_only(snum)) {
     346          42 :                 return make_session_info_guest(mem_ctx, presult);
     347             :         }
     348             : 
     349             :         /*
     350             :          * This is the normal security != share case where we have a
     351             :          * valid vuid from the session setup.                 */
     352             : 
     353        5593 :         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
     354         469 :                 if (!lp_guest_ok(snum)) {
     355           0 :                         DBG_WARNING("guest user (from session setup) "
     356             :                                   "not permitted to access this share "
     357             :                                   "(%s)\n", lp_const_servicename(snum));
     358           0 :                         return NT_STATUS_ACCESS_DENIED;
     359             :                 }
     360             :         } else {
     361        5124 :                 if (!user_ok_token(session_info->unix_info->unix_name,
     362        5124 :                                    session_info->info->domain_name,
     363        5124 :                                    session_info->security_token, snum)) {
     364          12 :                         DBG_WARNING("user '%s' (from session setup) not "
     365             :                                   "permitted to access this share "
     366             :                                   "(%s)\n",
     367             :                                   session_info->unix_info->unix_name,
     368             :                                   lp_const_servicename(snum));
     369          12 :                         return NT_STATUS_ACCESS_DENIED;
     370             :                 }
     371             :         }
     372             : 
     373        5581 :         result = copy_session_info(mem_ctx, session_info);
     374        5581 :         if (result == NULL) {
     375           0 :                 return NT_STATUS_NO_MEMORY;
     376             :         }
     377             : 
     378        5581 :         *presult = result;
     379        5581 :         return NT_STATUS_OK;
     380             : }
     381             : 
     382             : /****************************************************************************
     383             :   Set relevant user and group settings corresponding to force user/group
     384             :   configuration for the given snum.
     385             : ****************************************************************************/
     386             : 
     387        5623 : NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
     388             : {
     389        3816 :         const struct loadparm_substitution *lp_sub =
     390        1807 :                 loadparm_s3_global_substitution();
     391             :         NTSTATUS status;
     392             : 
     393        5623 :         if (*lp_force_user(talloc_tos(), lp_sub, snum)) {
     394             : 
     395             :                 /*
     396             :                  * Replace conn->session_info with a completely faked up one
     397             :                  * from the username we are forced into :-)
     398             :                  */
     399             : 
     400             :                 char *fuser;
     401             :                 char *sanitized_username;
     402             :                 struct auth_session_info *forced_serverinfo;
     403             :                 bool guest;
     404             : 
     405          74 :                 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), lp_sub, snum), "%S",
     406             :                                           lp_const_servicename(snum));
     407          74 :                 if (fuser == NULL) {
     408           0 :                         return NT_STATUS_NO_MEMORY;
     409             :                 }
     410             : 
     411          74 :                 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
     412             : 
     413          74 :                 status = make_session_info_from_username(
     414             :                         conn, fuser,
     415             :                         guest,
     416             :                         &forced_serverinfo);
     417          74 :                 if (!NT_STATUS_IS_OK(status)) {
     418           0 :                         return status;
     419             :                 }
     420             : 
     421             :                 /* We don't want to replace the original sanitized_username
     422             :                    as it is the original user given in the connect attempt.
     423             :                    This is used in '%U' substitutions. */
     424          74 :                 sanitized_username = discard_const_p(char,
     425             :                         forced_serverinfo->unix_info->sanitized_username);
     426          74 :                 TALLOC_FREE(sanitized_username);
     427         148 :                 forced_serverinfo->unix_info->sanitized_username =
     428         115 :                         talloc_move(forced_serverinfo->unix_info,
     429             :                                 &conn->session_info->unix_info->sanitized_username);
     430             : 
     431          74 :                 TALLOC_FREE(conn->session_info);
     432          74 :                 conn->session_info = forced_serverinfo;
     433             : 
     434          74 :                 conn->force_user = true;
     435          74 :                 DEBUG(3,("Forced user %s\n", fuser));
     436             :         }
     437             : 
     438             :         /*
     439             :          * If force group is true, then override
     440             :          * any groupid stored for the connecting user.
     441             :          */
     442             : 
     443        5623 :         if (*lp_force_group(talloc_tos(), lp_sub, snum)) {
     444             : 
     445         111 :                 status = find_forced_group(
     446          65 :                         conn->force_user, snum, conn->session_info->unix_info->unix_name,
     447          42 :                         &conn->session_info->security_token->sids[1],
     448          42 :                         &conn->session_info->unix_token->gid);
     449             : 
     450          42 :                 if (!NT_STATUS_IS_OK(status)) {
     451           0 :                         return status;
     452             :                 }
     453             : 
     454             :                 /*
     455             :                  * We need to cache this gid, to use within
     456             :                  * change_to_user() separately from the conn->session_info
     457             :                  * struct. We only use conn->session_info directly if
     458             :                  * "force_user" was set.
     459             :                  */
     460          42 :                 conn->force_group_gid = conn->session_info->unix_token->gid;
     461             :         }
     462             : 
     463        5623 :         return NT_STATUS_OK;
     464             : }
     465             : 
     466        1554 : static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
     467             : {
     468             :         NTSTATUS status;
     469             : 
     470        1554 :         if (sconn->notify_ctx != NULL) {
     471          10 :                 return NT_STATUS_OK;
     472             :         }
     473             : 
     474        1544 :         sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
     475             :                                         sconn, notify_callback);
     476        1544 :         if (sconn->notify_ctx == NULL) {
     477           0 :                 return NT_STATUS_NO_MEMORY;
     478             :         }
     479             : 
     480        1544 :         status = messaging_register(sconn->msg_ctx, sconn,
     481             :                                     MSG_SMB_NOTIFY_CANCEL_DELETED,
     482             :                                     smbd_notify_cancel_deleted);
     483        1544 :         if (!NT_STATUS_IS_OK(status)) {
     484           0 :                 DBG_DEBUG("messaging_register failed: %s\n",
     485             :                           nt_errstr(status));
     486           0 :                 TALLOC_FREE(sconn->notify_ctx);
     487           0 :                 return status;
     488             :         }
     489             : 
     490        1544 :         status = messaging_register(sconn->msg_ctx, sconn,
     491             :                                     MSG_SMB_NOTIFY_STARTED,
     492             :                                     smbd_notifyd_restarted);
     493        1544 :         if (!NT_STATUS_IS_OK(status)) {
     494           0 :                 DBG_DEBUG("messaging_register failed: %s\n",
     495             :                           nt_errstr(status));
     496           0 :                 messaging_deregister(sconn->msg_ctx,
     497             :                                      MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
     498           0 :                 TALLOC_FREE(sconn->notify_ctx);
     499           0 :                 return status;
     500             :         }
     501             : 
     502        1544 :         return NT_STATUS_OK;
     503             : }
     504             : 
     505             : /****************************************************************************
     506             :   Make a connection, given the snum to connect to, and the vuser of the
     507             :   connecting user if appropriate.
     508             : ****************************************************************************/
     509             : 
     510        5635 : NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
     511             :                               connection_struct *conn,
     512             :                               int snum,
     513             :                               struct smbXsrv_session *session,
     514             :                               const char *pdev)
     515             : {
     516        5635 :         struct smbd_server_connection *sconn = xconn->client->sconn;
     517        3822 :         const struct loadparm_substitution *lp_sub =
     518        1813 :                 loadparm_s3_global_substitution();
     519        5635 :         struct smb_filename *smb_fname_cpath = NULL;
     520             :         fstring dev;
     521             :         int ret;
     522        5635 :         bool on_err_call_dis_hook = false;
     523             :         uid_t effuid;
     524             :         gid_t effgid;
     525             :         NTSTATUS status;
     526             :         bool ok;
     527             : 
     528        5635 :         fstrcpy(dev, pdev);
     529             : 
     530        5635 :         status = share_sanity_checks(sconn->remote_address,
     531             :                                        sconn->remote_hostname,
     532             :                                        snum,
     533             :                                        dev);
     534        5635 :         if (NT_STATUS_IS_ERR(status)) {
     535           0 :                 goto err_root_exit;
     536             :         }
     537             : 
     538        5635 :         conn->params->service = snum;
     539             : 
     540        9457 :         status = create_connection_session_info(sconn,
     541        5635 :                 conn, snum, session->global->auth_session_info,
     542             :                 &conn->session_info);
     543             : 
     544        5635 :         if (!NT_STATUS_IS_OK(status)) {
     545          12 :                 DEBUG(1, ("create_connection_session_info failed: %s\n",
     546             :                           nt_errstr(status)));
     547          12 :                 goto err_root_exit;
     548             :         }
     549             : 
     550        5623 :         if (lp_guest_only(snum)) {
     551          42 :                 conn->force_user = true;
     552             :         }
     553             : 
     554        5623 :         conn->num_files_open = 0;
     555        5623 :         conn->lastused = conn->lastused_count = time(NULL);
     556        5623 :         conn->printer = (strncmp(dev,"LPT",3) == 0);
     557        9951 :         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
     558        1554 :                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
     559             : 
     560             :         /* Case options for the share. */
     561        5623 :         conn_setup_case_options(conn);
     562             : 
     563        5623 :         conn->encrypt_level = lp_server_smb_encrypt(snum);
     564        5623 :         if (conn->encrypt_level > SMB_ENCRYPTION_OFF) {
     565           0 :                 if (lp_server_smb_encrypt(-1) == SMB_ENCRYPTION_OFF) {
     566           0 :                         if (conn->encrypt_level == SMB_ENCRYPTION_REQUIRED) {
     567           0 :                                 DBG_ERR("Service [%s] requires encryption, but "
     568             :                                         "it is disabled globally!\n",
     569             :                                         lp_const_servicename(snum));
     570           0 :                                 status = NT_STATUS_ACCESS_DENIED;
     571           0 :                                 goto err_root_exit;
     572             :                         }
     573           0 :                         conn->encrypt_level = SMB_ENCRYPTION_OFF;
     574             :                 }
     575             :         }
     576             : 
     577        5623 :         conn->veto_list = NULL;
     578        5623 :         conn->hide_list = NULL;
     579        5623 :         conn->veto_oplock_list = NULL;
     580        5623 :         conn->aio_write_behind_list = NULL;
     581             : 
     582        5623 :         conn->read_only = lp_read_only(SNUM(conn));
     583             : 
     584        5623 :         status = set_conn_force_user_group(conn, snum);
     585        5623 :         if (!NT_STATUS_IS_OK(status)) {
     586           0 :                 goto err_root_exit;
     587             :         }
     588             : 
     589        5623 :         conn->vuid = session->global->session_wire_id;
     590             : 
     591             :         {
     592       20887 :                 char *s = talloc_sub_full(talloc_tos(),
     593        5623 :                                         lp_const_servicename(SNUM(conn)),
     594        5623 :                                         conn->session_info->unix_info->unix_name,
     595        5623 :                                         conn->connectpath,
     596        5623 :                                         conn->session_info->unix_token->gid,
     597        5623 :                                         conn->session_info->unix_info->sanitized_username,
     598        5623 :                                         conn->session_info->info->domain_name,
     599        5623 :                                         lp_path(talloc_tos(), lp_sub, snum));
     600        5623 :                 if (!s) {
     601           0 :                         status = NT_STATUS_NO_MEMORY;
     602           0 :                         goto err_root_exit;
     603             :                 }
     604             : 
     605        5623 :                 if (!set_conn_connectpath(conn,s)) {
     606           0 :                         TALLOC_FREE(s);
     607           0 :                         status = NT_STATUS_NO_MEMORY;
     608           0 :                         goto err_root_exit;
     609             :                 }
     610        5623 :                 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
     611             :                            lp_const_servicename(snum));
     612        5623 :                 TALLOC_FREE(s);
     613             :         }
     614             : 
     615             :         /*
     616             :          * Set up the share security descriptor.
     617             :          * NOTE - we use the *INCOMING USER* session_info
     618             :          * here, as does (indirectly) change_to_user(),
     619             :          * which can be called on any incoming packet.
     620             :          * This way we set up the share access based
     621             :          * on the authenticated user, not the forced
     622             :          * user. See bug:
     623             :          *
     624             :          * https://bugzilla.samba.org/show_bug.cgi?id=9878
     625             :          */
     626             : 
     627        9439 :         status = check_user_share_access(conn,
     628        5623 :                                         session->global->auth_session_info,
     629             :                                         &conn->share_access,
     630             :                                         &conn->read_only);
     631        5623 :         if (!NT_STATUS_IS_OK(status)) {
     632           0 :                 goto err_root_exit;
     633             :         }
     634             : 
     635             :         /* Initialise VFS function pointers */
     636             : 
     637        5623 :         if (!smbd_vfs_init(conn)) {
     638           0 :                 DBG_ERR("vfs_init failed for service %s\n",
     639             :                         lp_const_servicename(snum));
     640           0 :                 status = NT_STATUS_BAD_NETWORK_NAME;
     641           0 :                 goto err_root_exit;
     642             :         }
     643             : 
     644             : /* ROOT Activities: */
     645             :         /* explicitly check widelinks here so that we can correctly warn
     646             :          * in the logs. */
     647        5623 :         widelinks_warning(snum);
     648             : 
     649             :         /* Invoke VFS make connection hook - this must be the first
     650             :            filesystem operation that we do. */
     651             : 
     652        5623 :         if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
     653             :                             conn->session_info->unix_info->unix_name) < 0) {
     654           0 :                 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
     655             :                             lp_const_servicename(snum), conn->connectpath,
     656             :                             strerror(errno));
     657           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     658           0 :                 goto err_root_exit;
     659             :         }
     660             : 
     661             :         /* Any error exit after here needs to call the disconnect hook. */
     662        5623 :         on_err_call_dis_hook = true;
     663             : 
     664        7177 :         if ((!conn->printer) && (!conn->ipc) &&
     665        1554 :             lp_change_notify()) {
     666             : 
     667        1554 :                 status = notify_init_sconn(sconn);
     668        1554 :                 if (!NT_STATUS_IS_OK(status)) {
     669           0 :                         goto err_root_exit;
     670             :                 }
     671             :         }
     672             : 
     673        5623 :         if (lp_kernel_oplocks(snum)) {
     674           0 :                 init_kernel_oplocks(conn->sconn);
     675             :         }
     676             : 
     677             :         /*
     678             :          * Fix compatibility issue pointed out by Volker.
     679             :          * We pass the conn->connectpath to the preexec
     680             :          * scripts as a parameter, so attempt to canonicalize
     681             :          * it here before calling the preexec scripts.
     682             :          * We ignore errors here, as it is possible that
     683             :          * the conn->connectpath doesn't exist yet and
     684             :          * the preexec scripts will create them.
     685             :          */
     686             : 
     687        5623 :         (void)canonicalize_connect_path(conn);
     688             : 
     689             :         /* Preexecs are done here as they might make the dir we are to ChDir
     690             :          * to below */
     691             :         /* execute any "root preexec = " line */
     692        5623 :         if (*lp_root_preexec(talloc_tos(), lp_sub, snum)) {
     693           0 :                 char *cmd = talloc_sub_full(talloc_tos(),
     694           0 :                                         lp_const_servicename(SNUM(conn)),
     695           0 :                                         conn->session_info->unix_info->unix_name,
     696           0 :                                         conn->connectpath,
     697           0 :                                         conn->session_info->unix_token->gid,
     698           0 :                                         conn->session_info->unix_info->sanitized_username,
     699           0 :                                         conn->session_info->info->domain_name,
     700           0 :                                         lp_root_preexec(talloc_tos(), lp_sub, snum));
     701           0 :                 DEBUG(5,("cmd=%s\n",cmd));
     702           0 :                 ret = smbrun(cmd, NULL, NULL);
     703           0 :                 TALLOC_FREE(cmd);
     704           0 :                 if (ret != 0 && lp_root_preexec_close(snum)) {
     705           0 :                         DEBUG(1,("root preexec gave %d - failing "
     706             :                                  "connection\n", ret));
     707           0 :                         status = NT_STATUS_ACCESS_DENIED;
     708           0 :                         goto err_root_exit;
     709             :                 }
     710             :         }
     711             : 
     712             : /* USER Activites: */
     713        5623 :         if (!change_to_user_and_service(conn, conn->vuid)) {
     714             :                 /* No point continuing if they fail the basic checks */
     715           0 :                 DEBUG(0,("Can't become connected user!\n"));
     716           0 :                 status = NT_STATUS_LOGON_FAILURE;
     717           0 :                 goto err_root_exit;
     718             :         }
     719             : 
     720        5623 :         effuid = geteuid();
     721        5623 :         effgid = getegid();
     722             : 
     723             :         /* Remember that a different vuid can connect later without these
     724             :          * checks... */
     725             : 
     726             :         /* Preexecs are done here as they might make the dir we are to ChDir
     727             :          * to below */
     728             : 
     729             :         /* execute any "preexec = " line */
     730        5623 :         if (*lp_preexec(talloc_tos(), lp_sub, snum)) {
     731           0 :                 char *cmd = talloc_sub_full(talloc_tos(),
     732           0 :                                         lp_const_servicename(SNUM(conn)),
     733           0 :                                         conn->session_info->unix_info->unix_name,
     734           0 :                                         conn->connectpath,
     735           0 :                                         conn->session_info->unix_token->gid,
     736           0 :                                         conn->session_info->unix_info->sanitized_username,
     737           0 :                                         conn->session_info->info->domain_name,
     738           0 :                                         lp_preexec(talloc_tos(), lp_sub, snum));
     739           0 :                 ret = smbrun(cmd, NULL, NULL);
     740           0 :                 TALLOC_FREE(cmd);
     741           0 :                 if (ret != 0 && lp_preexec_close(snum)) {
     742           0 :                         DEBUG(1,("preexec gave %d - failing connection\n",
     743             :                                  ret));
     744           0 :                         status = NT_STATUS_ACCESS_DENIED;
     745           0 :                         goto err_root_exit;
     746             :                 }
     747             :         }
     748             : 
     749             : #ifdef WITH_FAKE_KASERVER
     750             :         if (lp_afs_share(snum)) {
     751             :                 afs_login(conn);
     752             :         }
     753             : #endif
     754             : 
     755             :         /*
     756             :          * we've finished with the user stuff - go back to root
     757             :          * so the SMB_VFS_STAT call will only fail on path errors,
     758             :          * not permission problems.
     759             :          */
     760        5623 :         change_to_root_user();
     761             : /* ROOT Activites: */
     762             : 
     763             :         /*
     764             :          * Canonicalise the connect
     765             :          * path here to ensure we don't have any symlinks in the
     766             :          * connectpath. We will be checking all paths on this connection are
     767             :          * below this directory. We must do this after the VFS init as we
     768             :          * depend on the realpath() pointer in the vfs table. JRA.
     769             :          */
     770        5623 :         ok = canonicalize_connect_path(conn);
     771        5623 :         if (!ok) {
     772           0 :                 DBG_ERR("canonicalize_connect_path failed "
     773             :                 "for service %s, path %s\n",
     774             :                         lp_const_servicename(snum),
     775             :                         conn->connectpath);
     776           0 :                 status = NT_STATUS_BAD_NETWORK_NAME;
     777           0 :                 goto err_root_exit;
     778             :         }
     779             : 
     780             :         /* Add veto/hide lists */
     781        5623 :         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
     782        1554 :                 set_namearray( &conn->veto_list,
     783        1554 :                                lp_veto_files(talloc_tos(), lp_sub, snum));
     784        1554 :                 set_namearray( &conn->hide_list,
     785        1554 :                                lp_hide_files(talloc_tos(), lp_sub, snum));
     786        1554 :                 set_namearray( &conn->veto_oplock_list,
     787        1554 :                                lp_veto_oplock_files(talloc_tos(), lp_sub, snum));
     788        1554 :                 set_namearray( &conn->aio_write_behind_list,
     789        1554 :                                 lp_aio_write_behind(talloc_tos(), lp_sub, snum));
     790             :         }
     791        5623 :         smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
     792        5623 :                                         conn->connectpath,
     793             :                                         NULL,
     794             :                                         NULL,
     795             :                                         0,
     796             :                                         0);
     797        5623 :         if (smb_fname_cpath == NULL) {
     798           0 :                 status = NT_STATUS_NO_MEMORY;
     799           0 :                 goto err_root_exit;
     800             :         }
     801             : 
     802             :         /* win2000 does not check the permissions on the directory
     803             :            during the tree connect, instead relying on permission
     804             :            check during individual operations. To match this behaviour
     805             :            I have disabled this chdir check (tridge) */
     806             :         /* the alternative is just to check the directory exists */
     807             : 
     808        9439 :         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
     809        5623 :             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
     810           0 :                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
     811           0 :                         DBG_ERR("'%s' is not a directory, when connecting to "
     812             :                                  "[%s]\n", conn->connectpath,
     813             :                                  lp_const_servicename(snum));
     814             :                 } else {
     815           0 :                         DBG_ERR("'%s' does not exist or permission denied "
     816             :                                  "when connecting to [%s] Error was %s\n",
     817             :                                  conn->connectpath,
     818             :                                  lp_const_servicename(snum),
     819             :                                  strerror(errno));
     820             :                 }
     821           0 :                 status = NT_STATUS_BAD_NETWORK_NAME;
     822           0 :                 goto err_root_exit;
     823             :         }
     824        5623 :         conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
     825             : 
     826             :         /* Figure out the characteristics of the underlying filesystem. This
     827             :          * assumes that all the filesystem mounted within a share path have
     828             :          * the same characteristics, which is likely but not guaranteed.
     829             :          */
     830             : 
     831        5623 :         if(!IS_IPC(conn) ){
     832        1554 :                 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
     833             :         }
     834             :         /*
     835             :          * Print out the 'connected as' stuff here as we need
     836             :          * to know the effective uid and gid we will be using
     837             :          * (at least initially).
     838             :          */
     839             : 
     840        5623 :         if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
     841             :                 bool signing_active;
     842             : 
     843           0 :                 dbgtext( "%s (%s) ", get_remote_machine_name(),
     844           0 :                          tsocket_address_string(conn->sconn->remote_address,
     845             :                                                 talloc_tos()) );
     846             : #if defined(WITH_SMB1SERVER)
     847           0 :                 if (sconn->using_smb2) {
     848             : #endif
     849           0 :                         signing_active = smb2_signing_key_valid(
     850           0 :                                                 session->global->encryption_key);
     851             : #if defined(WITH_SMB1SERVER)
     852             :                 } else {
     853           0 :                         signing_active = smb1_srv_is_signing_active(xconn);
     854             :                 }
     855             : #endif
     856           0 :                 dbgtext( "%s", signing_active ? "signed " : "");
     857           0 :                 dbgtext( "connect to service %s ",
     858             :                          lp_const_servicename(snum) );
     859           0 :                 dbgtext( "initially as user %s ",
     860           0 :                          conn->session_info->unix_info->unix_name );
     861           0 :                 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
     862           0 :                 dbgtext( "(pid %d)\n", (int)getpid() );
     863             :         }
     864             : 
     865        5623 :         conn->tcon_done = true;
     866        5623 :         return NT_STATUS_OK;
     867             : 
     868          12 :   err_root_exit:
     869             : 
     870          12 :         TALLOC_FREE(smb_fname_cpath);
     871             :         /* We must exit this function as root. */
     872          12 :         if (geteuid() != 0) {
     873           0 :                 change_to_root_user();
     874             :         }
     875          12 :         if (on_err_call_dis_hook) {
     876             :                 /* Call VFS disconnect hook */
     877           0 :                 SMB_VFS_DISCONNECT(conn);
     878             :         }
     879          12 :         return status;
     880             : }
     881             : 
     882             : /****************************************************************************
     883             :  Make a connection to a service from SMB2. External SMB2 interface.
     884             :  We must set cnum before claiming connection.
     885             : ****************************************************************************/
     886             : 
     887        5607 : connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
     888             :                                         struct smbXsrv_tcon *tcon,
     889             :                                         int snum,
     890             :                                         const char *pdev,
     891             :                                         NTSTATUS *pstatus)
     892             : {
     893        5607 :         struct smbd_server_connection *sconn = req->sconn;
     894        5607 :         connection_struct *conn = conn_new(sconn);
     895        5607 :         if (!conn) {
     896           0 :                 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
     897           0 :                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
     898           0 :                 return NULL;
     899             :         }
     900             : 
     901        5607 :         conn->cnum = tcon->global->tcon_wire_id;
     902        5607 :         conn->tcon = tcon;
     903             : 
     904        5607 :         *pstatus = make_connection_snum(req->xconn,
     905             :                                         conn,
     906             :                                         snum,
     907             :                                         req->session,
     908             :                                         pdev);
     909        5607 :         if (!NT_STATUS_IS_OK(*pstatus)) {
     910          12 :                 conn_free(conn);
     911          12 :                 return NULL;
     912             :         }
     913        5595 :         return conn;
     914             : }
     915             : 
     916             : /****************************************************************************
     917             :  Close a cnum.
     918             : ****************************************************************************/
     919             : 
     920        5623 : void close_cnum(connection_struct *conn,
     921             :                 uint64_t vuid,
     922             :                 enum file_close_type close_type)
     923             : {
     924        5623 :         char rootpath[2] = { '/', '\0'};
     925        5623 :         struct smb_filename root_fname = { .base_name = rootpath };
     926        3816 :         const struct loadparm_substitution *lp_sub =
     927        1807 :                 loadparm_s3_global_substitution();
     928             : 
     929        5623 :         file_close_conn(conn, close_type);
     930             : 
     931        5623 :         change_to_root_user();
     932             : 
     933        5623 :         DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
     934             :                                  get_remote_machine_name(),
     935             :                                  tsocket_address_string(conn->sconn->remote_address,
     936             :                                                         talloc_tos()),
     937             :                                  lp_const_servicename(SNUM(conn))));
     938             : 
     939             :         /* make sure we leave the directory available for unmount */
     940        5623 :         vfs_ChDir(conn, &root_fname);
     941             : 
     942             :         /* Call VFS disconnect hook */
     943        5623 :         SMB_VFS_DISCONNECT(conn);
     944             : 
     945             :         /* execute any "postexec = " line */
     946        5623 :         if (*lp_postexec(talloc_tos(), lp_sub, SNUM(conn)) &&
     947           0 :             change_to_user_and_service(conn, vuid))  {
     948           0 :                 char *cmd = talloc_sub_full(talloc_tos(),
     949           0 :                                         lp_const_servicename(SNUM(conn)),
     950           0 :                                         conn->session_info->unix_info->unix_name,
     951           0 :                                         conn->connectpath,
     952           0 :                                         conn->session_info->unix_token->gid,
     953           0 :                                         conn->session_info->unix_info->sanitized_username,
     954           0 :                                         conn->session_info->info->domain_name,
     955           0 :                                         lp_postexec(talloc_tos(), lp_sub, SNUM(conn)));
     956           0 :                 smbrun(cmd, NULL, NULL);
     957           0 :                 TALLOC_FREE(cmd);
     958           0 :                 change_to_root_user();
     959             :         }
     960             : 
     961        5623 :         change_to_root_user();
     962             :         /* execute any "root postexec = " line */
     963        5623 :         if (*lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)))  {
     964           0 :                 char *cmd = talloc_sub_full(talloc_tos(),
     965           0 :                                         lp_const_servicename(SNUM(conn)),
     966           0 :                                         conn->session_info->unix_info->unix_name,
     967           0 :                                         conn->connectpath,
     968           0 :                                         conn->session_info->unix_token->gid,
     969           0 :                                         conn->session_info->unix_info->sanitized_username,
     970           0 :                                         conn->session_info->info->domain_name,
     971           0 :                                         lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)));
     972           0 :                 smbrun(cmd, NULL, NULL);
     973           0 :                 TALLOC_FREE(cmd);
     974             :         }
     975             : 
     976        5623 :         conn_free(conn);
     977        5623 : }

Generated by: LCOV version 1.13