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

Generated by: LCOV version 1.14