LCOV - code coverage report
Current view: top level - source3/smbd - conn.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 79 103 76.7 %
Date: 2021-08-25 13:27:56 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Manage connections_struct structures
       4             :    Copyright (C) Andrew Tridgell 1998
       5             :    Copyright (C) Alexander Bokovoy 2002
       6             :    Copyright (C) Jeremy Allison 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "smbd/smbd.h"
      24             : #include "smbd/globals.h"
      25             : #include "lib/util/bitmap.h"
      26             : 
      27             : /****************************************************************************
      28             :  Return the number of open connections.
      29             : ****************************************************************************/
      30             : 
      31        8333 : int conn_num_open(struct smbd_server_connection *sconn)
      32             : {
      33        8333 :         return sconn->num_connections;
      34             : }
      35             : 
      36             : /****************************************************************************
      37             :  Check if a snum is in use.
      38             : ****************************************************************************/
      39             : 
      40       65439 : bool conn_snum_used(struct smbd_server_connection *sconn,
      41             :                     int snum)
      42             : {
      43             :         struct connection_struct *conn;
      44             : 
      45      113544 :         for (conn=sconn->connections; conn; conn=conn->next) {
      46       48748 :                 if (conn->params->service == snum) {
      47         643 :                         return true;
      48             :                 }
      49             :         }
      50             : 
      51       64796 :         return false;
      52             : }
      53             : 
      54             : /****************************************************************************
      55             :  Find first available connection slot, starting from a random position.
      56             :  The randomisation stops problems with the server dieing and clients
      57             :  thinking the server is still available.
      58             : ****************************************************************************/
      59             : 
      60       46913 : connection_struct *conn_new(struct smbd_server_connection *sconn)
      61             : {
      62       46913 :         connection_struct *conn = NULL;
      63             : 
      64       46913 :         conn = talloc_zero(NULL, connection_struct);
      65       46913 :         if (conn == NULL) {
      66           0 :                 DBG_ERR("talloc_zero failed\n");
      67           0 :                 return NULL;
      68             :         }
      69       46913 :         conn->params = talloc(conn, struct share_params);
      70       46913 :         if (conn->params == NULL) {
      71           0 :                 DBG_ERR("talloc_zero failed\n");
      72           0 :                 TALLOC_FREE(conn);
      73           0 :                 return NULL;
      74             :         }
      75       46913 :         conn->vuid_cache = talloc_zero(conn, struct vuid_cache);
      76       46913 :         if (conn->vuid_cache == NULL) {
      77           0 :                 DBG_ERR("talloc_zero failed\n");
      78           0 :                 TALLOC_FREE(conn);
      79           0 :                 return NULL;
      80             :         }
      81       46913 :         conn->connectpath = talloc_strdup(conn, "");
      82       46913 :         if (conn->connectpath == NULL) {
      83           0 :                 DBG_ERR("talloc_zero failed\n");
      84           0 :                 TALLOC_FREE(conn);
      85           0 :                 return NULL;
      86             :         }
      87       46913 :         conn->cwd_fsp = talloc_zero(conn, struct files_struct);
      88       46913 :         if (conn->cwd_fsp == NULL) {
      89           0 :                 DBG_ERR("talloc_zero failed\n");
      90           0 :                 TALLOC_FREE(conn);
      91           0 :                 return NULL;
      92             :         }
      93       46913 :         conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn->cwd_fsp,
      94             :                                                       ".",
      95             :                                                       NULL,
      96             :                                                       NULL,
      97             :                                                       0,
      98             :                                                       0);
      99       46913 :         if (conn->cwd_fsp->fsp_name == NULL) {
     100           0 :                 TALLOC_FREE(conn);
     101           0 :                 return NULL;
     102             :         }
     103       46913 :         conn->cwd_fsp->fh = fd_handle_create(conn->cwd_fsp);
     104       46913 :         if (conn->cwd_fsp->fh == NULL) {
     105           0 :                 DBG_ERR("talloc_zero failed\n");
     106           0 :                 TALLOC_FREE(conn);
     107           0 :                 return NULL;
     108             :         }
     109       46913 :         conn->sconn = sconn;
     110       46913 :         conn->force_group_gid = (gid_t)-1;
     111       46913 :         fsp_set_fd(conn->cwd_fsp, -1);
     112       46913 :         conn->cwd_fsp->fnum = FNUM_FIELD_INVALID;
     113       46913 :         conn->cwd_fsp->conn = conn;
     114             : 
     115       46913 :         DLIST_ADD(sconn->connections, conn);
     116       46913 :         sconn->num_connections++;
     117             : 
     118       46913 :         return conn;
     119             : }
     120             : 
     121             : /****************************************************************************
     122             :  Clear a vuid out of the connection's vuid cache
     123             : ****************************************************************************/
     124             : 
     125         277 : static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
     126             : {
     127             :         int i;
     128             : 
     129        9141 :         for (i=0; i<VUID_CACHE_SIZE; i++) {
     130             :                 struct vuid_cache_entry *ent;
     131             : 
     132        8864 :                 ent = &conn->vuid_cache->array[i];
     133             : 
     134        8864 :                 if (ent->vuid == vuid) {
     135         202 :                         ent->vuid = UID_FIELD_INVALID;
     136             :                         /*
     137             :                          * We need to keep conn->session_info around
     138             :                          * if it's equal to ent->session_info as a SMBulogoff
     139             :                          * is often followed by a SMBtdis (with an invalid
     140             :                          * vuid). The debug code (or regular code in
     141             :                          * vfs_full_audit) wants to refer to the
     142             :                          * conn->session_info pointer to print debug
     143             :                          * statements. Theoretically this is a bug,
     144             :                          * as once the vuid is gone the session_info
     145             :                          * on the conn struct isn't valid any more,
     146             :                          * but there's enough code that assumes
     147             :                          * conn->session_info is never null that
     148             :                          * it's easier to hold onto the old pointer
     149             :                          * until we get a new sessionsetupX.
     150             :                          * As everything is hung off the
     151             :                          * conn pointer as a talloc context we're not
     152             :                          * leaking memory here. See bug #6315. JRA.
     153             :                          */
     154         202 :                         if (conn->session_info == ent->session_info) {
     155         202 :                                 ent->session_info = NULL;
     156             :                         } else {
     157           0 :                                 TALLOC_FREE(ent->session_info);
     158             :                         }
     159         202 :                         ent->read_only = False;
     160         202 :                         ent->share_access = 0;
     161             :                 }
     162             :         }
     163         277 : }
     164             : 
     165             : /****************************************************************************
     166             :  Clear a vuid out of the validity cache, and as the 'owner' of a connection.
     167             : 
     168             :  Called from invalidate_vuid()
     169             : ****************************************************************************/
     170             : 
     171       25644 : void conn_clear_vuid_caches(struct smbd_server_connection *sconn, uint64_t vuid)
     172             : {
     173             :         connection_struct *conn;
     174             : 
     175       25921 :         for (conn=sconn->connections; conn;conn=conn->next) {
     176         277 :                 if (conn->vuid == vuid) {
     177         202 :                         conn->vuid = UID_FIELD_INVALID;
     178             :                 }
     179         277 :                 conn_clear_vuid_cache(conn, vuid);
     180             :         }
     181       25644 : }
     182             : 
     183             : /****************************************************************************
     184             :  Free a conn structure - internal part.
     185             : ****************************************************************************/
     186             : 
     187       46827 : static void conn_free_internal(connection_struct *conn)
     188             : {
     189       46827 :         vfs_handle_struct *handle = NULL, *thandle = NULL;
     190       46827 :         struct trans_state *state = NULL;
     191             : 
     192             :         /* Free vfs_connection_struct */
     193       46827 :         handle = conn->vfs_handles;
     194      391008 :         while(handle) {
     195      297354 :                 thandle = handle->next;
     196      297354 :                 DLIST_REMOVE(conn->vfs_handles, handle);
     197      297354 :                 if (handle->free_data)
     198       42674 :                         handle->free_data(&handle->data);
     199      293617 :                 handle = thandle;
     200             :         }
     201             : 
     202             :         /* Free any pending transactions stored on this conn. */
     203       46827 :         for (state = conn->pending_trans; state; state = state->next) {
     204             :                 /* state->setup is a talloc child of state. */
     205           0 :                 SAFE_FREE(state->param);
     206           0 :                 SAFE_FREE(state->data);
     207             :         }
     208             : 
     209       46827 :         free_namearray(conn->veto_list);
     210       46827 :         free_namearray(conn->hide_list);
     211       46827 :         free_namearray(conn->veto_oplock_list);
     212       46827 :         free_namearray(conn->aio_write_behind_list);
     213             : 
     214       46827 :         ZERO_STRUCTP(conn);
     215       46827 :         talloc_destroy(conn);
     216       46827 : }
     217             : 
     218             : /****************************************************************************
     219             :  Free a conn structure.
     220             : ****************************************************************************/
     221             : 
     222       46827 : void conn_free(connection_struct *conn)
     223             : {
     224       46827 :         if (conn->sconn == NULL) {
     225           0 :                 conn_free_internal(conn);
     226           0 :                 return;
     227             :         }
     228             : 
     229       46827 :         DLIST_REMOVE(conn->sconn->connections, conn);
     230       46827 :         SMB_ASSERT(conn->sconn->num_connections > 0);
     231       46827 :         conn->sconn->num_connections--;
     232             : 
     233       46827 :         conn_free_internal(conn);
     234             : }
     235             : 
     236             : /*
     237             :  * Correctly initialize a share with case options.
     238             :  */
     239       46847 : void conn_setup_case_options(connection_struct *conn)
     240             : {
     241       46847 :         int snum = conn->params->service;
     242             : 
     243       46847 :         if (lp_case_sensitive(snum) == Auto) {
     244             :                 /* We will be setting this per packet. Set to be case
     245             :                 * insensitive for now. */
     246       46735 :                 conn->case_sensitive = false;
     247             :         } else {
     248         112 :                 conn->case_sensitive = (bool)lp_case_sensitive(snum);
     249             :         }
     250             : 
     251       46847 :         conn->case_preserve = lp_preserve_case(snum);
     252       46847 :         conn->short_case_preserve = lp_short_preserve_case(snum);
     253       46847 : }

Generated by: LCOV version 1.13