LCOV - code coverage report
Current view: top level - source3/smbd - smb1_service.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 43 99 43.4 %
Date: 2024-06-13 04:01:37 Functions: 2 2 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             : /****************************************************************************
      40             :  Make a connection to a service from SMB1. Internal interface.
      41             : ****************************************************************************/
      42             : 
      43          28 : static connection_struct *make_connection_smb1(struct smb_request *req,
      44             :                                         NTTIME now,
      45             :                                         int snum,
      46             :                                         const char *pdev,
      47             :                                         NTSTATUS *pstatus)
      48             : {
      49          23 :         const struct loadparm_substitution *lp_sub =
      50           5 :                 loadparm_s3_global_substitution();
      51             :         uint32_t session_global_id;
      52          28 :         char *share_name = NULL;
      53             :         struct smbXsrv_tcon *tcon;
      54             :         NTSTATUS status;
      55             :         struct connection_struct *conn;
      56             : 
      57          28 :         session_global_id = req->session->global->session_global_id;
      58          28 :         share_name = lp_servicename(talloc_tos(), lp_sub, snum);
      59          28 :         if (share_name == NULL) {
      60           0 :                 *pstatus = NT_STATUS_NO_MEMORY;
      61           0 :                 return NULL;
      62             :         }
      63             : 
      64          28 :         if ((lp_max_connections(snum) > 0)
      65           0 :             && (count_current_connections(lp_const_servicename(snum), true) >=
      66           0 :                 lp_max_connections(snum))) {
      67             : 
      68           0 :                 DBG_WARNING("Max connections (%d) exceeded for [%s][%s]\n",
      69             :                           lp_max_connections(snum),
      70             :                           lp_const_servicename(snum), share_name);
      71           0 :                 TALLOC_FREE(share_name);
      72           0 :                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
      73           0 :                 return NULL;
      74             :         }
      75             : 
      76          28 :         status = smb1srv_tcon_create(req->xconn,
      77             :                                      session_global_id,
      78             :                                      share_name,
      79             :                                      now, &tcon);
      80          28 :         if (!NT_STATUS_IS_OK(status)) {
      81           0 :                 DEBUG(0,("make_connection_smb1: Couldn't find free tcon for [%s] - %s\n",
      82             :                          share_name, nt_errstr(status)));
      83           0 :                 TALLOC_FREE(share_name);
      84           0 :                 *pstatus = status;
      85           0 :                 return NULL;
      86             :         }
      87          28 :         TALLOC_FREE(share_name);
      88             : 
      89          28 :         conn = conn_new(req->sconn);
      90          28 :         if (!conn) {
      91           0 :                 TALLOC_FREE(tcon);
      92             : 
      93           0 :                 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
      94           0 :                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
      95           0 :                 return NULL;
      96             :         }
      97             : 
      98          28 :         conn->cnum = tcon->global->tcon_wire_id;
      99          28 :         conn->tcon = tcon;
     100             : 
     101          28 :         *pstatus = make_connection_snum(req->xconn,
     102             :                                         conn,
     103             :                                         snum,
     104             :                                         req->session,
     105             :                                         pdev);
     106          28 :         if (!NT_STATUS_IS_OK(*pstatus)) {
     107           0 :                 conn_free(conn);
     108           0 :                 TALLOC_FREE(tcon);
     109           0 :                 return NULL;
     110             :         }
     111             : 
     112          28 :         tcon->compat = talloc_move(tcon, &conn);
     113          28 :         tcon->status = NT_STATUS_OK;
     114             : 
     115          28 :         *pstatus = NT_STATUS_OK;
     116             : 
     117          28 :         return tcon->compat;
     118             : }
     119             : 
     120             : /****************************************************************************
     121             :  Make a connection to a service. External SMB1 interface.
     122             :  *
     123             :  * @param service
     124             : ****************************************************************************/
     125             : 
     126          28 : connection_struct *make_connection(struct smb_request *req,
     127             :                                    NTTIME now,
     128             :                                    const char *service_in,
     129             :                                    const char *pdev, uint64_t vuid,
     130             :                                    NTSTATUS *status)
     131             : {
     132          28 :         struct smbd_server_connection *sconn = req->sconn;
     133          28 :         struct smbXsrv_session *session = req->session;
     134          23 :         const struct loadparm_substitution *lp_sub =
     135           5 :                 loadparm_s3_global_substitution();
     136             :         uid_t euid;
     137          28 :         char *service = NULL;
     138             :         fstring dev;
     139          28 :         int snum = -1;
     140             : 
     141          28 :         fstrcpy(dev, pdev);
     142             : 
     143             :         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
     144             :          * root. */
     145          28 :         if (!non_root_mode() && (euid = geteuid()) != 0) {
     146           0 :                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
     147             :                          "(%u)\n", (unsigned int)euid ));
     148           0 :                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
     149             :         }
     150             : 
     151          28 :         if (conn_num_open(sconn) > 2047) {
     152           0 :                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
     153           0 :                 return NULL;
     154             :         }
     155             : 
     156          28 :         if (session == NULL) {
     157           0 :                 DEBUG(1,("make_connection: refusing to connect with "
     158             :                          "no session setup\n"));
     159           0 :                 *status = NT_STATUS_ACCESS_DENIED;
     160           0 :                 return NULL;
     161             :         }
     162             : 
     163             :         /* Logic to try and connect to the correct [homes] share, preferably
     164             :            without too many getpwnam() lookups.  This is particulary nasty for
     165             :            winbind usernames, where the share name isn't the same as unix
     166             :            username.
     167             :         */
     168             : 
     169          28 :         if (strequal(service_in,HOMES_NAME)) {
     170           0 :                 if (session->homes_snum == -1) {
     171           0 :                         DEBUG(2, ("[homes] share not available for "
     172             :                                   "this user because it was not found "
     173             :                                   "or created at session setup "
     174             :                                   "time\n"));
     175           0 :                         *status = NT_STATUS_BAD_NETWORK_NAME;
     176           0 :                         return NULL;
     177             :                 }
     178           0 :                 DEBUG(5, ("making a connection to [homes] service "
     179             :                           "created at session setup time\n"));
     180           0 :                 return make_connection_smb1(req, now,
     181           0 :                                             session->homes_snum,
     182             :                                             dev, status);
     183          28 :         } else if ((session->homes_snum != -1)
     184           0 :                    && strequal(service_in,
     185           0 :                                lp_const_servicename(session->homes_snum))) {
     186           0 :                 DEBUG(5, ("making a connection to 'homes' service [%s] "
     187             :                           "created at session setup time\n", service_in));
     188           0 :                 return make_connection_smb1(req, now,
     189           0 :                                             session->homes_snum,
     190             :                                             dev, status);
     191             :         }
     192             : 
     193          28 :         service = talloc_strdup(talloc_tos(), service_in);
     194          28 :         if (!service) {
     195           0 :                 *status = NT_STATUS_NO_MEMORY;
     196           0 :                 return NULL;
     197             :         }
     198             : 
     199          28 :         if (!strlower_m(service)) {
     200           0 :                 DEBUG(2, ("strlower_m %s failed\n", service));
     201           0 :                 *status = NT_STATUS_INVALID_PARAMETER;
     202           0 :                 return NULL;
     203             :         }
     204             : 
     205          28 :         snum = find_service(talloc_tos(), service, &service);
     206          28 :         if (!service) {
     207           0 :                 *status = NT_STATUS_NO_MEMORY;
     208           0 :                 return NULL;
     209             :         }
     210             : 
     211          28 :         if (snum < 0) {
     212           0 :                 if (strequal(service,"IPC$") ||
     213           0 :                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
     214           0 :                         DEBUG(3,("refusing IPC connection to %s\n", service));
     215           0 :                         *status = NT_STATUS_ACCESS_DENIED;
     216           0 :                         return NULL;
     217             :                 }
     218             : 
     219           0 :                 DEBUG(3,("%s (%s) couldn't find service %s\n",
     220             :                         get_remote_machine_name(),
     221             :                         tsocket_address_string(
     222             :                                 sconn->remote_address, talloc_tos()),
     223             :                         service));
     224           0 :                 *status = NT_STATUS_BAD_NETWORK_NAME;
     225           0 :                 return NULL;
     226             :         }
     227             : 
     228             :         /* Handle non-Dfs clients attempting connections to msdfs proxy */
     229          28 :         if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), lp_sub, snum) != '\0'))  {
     230           0 :                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
     231             :                           "(pointing to %s)\n",
     232             :                         service, lp_msdfs_proxy(talloc_tos(), lp_sub, snum)));
     233           0 :                 *status = NT_STATUS_BAD_NETWORK_NAME;
     234           0 :                 return NULL;
     235             :         }
     236             : 
     237          28 :         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
     238             : 
     239          28 :         return make_connection_smb1(req, now, snum,
     240             :                                     dev, status);
     241             : }

Generated by: LCOV version 1.13