Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/smbd/conn_msg.c
Line
Count
Source (jump to first uncovered line)
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
26
/****************************************************************************
27
 Receive a smbcontrol message to forcibly unmount a share.
28
 The message contains just a share name and all instances of that
29
 share are unmounted.
30
 The special sharename '*' forces unmount of all shares.
31
****************************************************************************/
32
33
struct force_tdis_state {
34
  const char *sharename;
35
};
36
37
static bool force_tdis_check(
38
  struct connection_struct *conn,
39
  void *private_data)
40
0
{
41
0
  struct force_tdis_state *state = private_data;
42
0
  const struct loadparm_substitution *lp_sub =
43
0
    loadparm_s3_global_substitution();
44
0
  char *servicename = NULL;
45
0
  bool do_close;
46
47
0
  if (strcmp(state->sharename, "*") == 0) {
48
0
    DBG_WARNING("Forcing close of all shares\n");
49
0
    return true;
50
0
  }
51
52
0
  servicename = lp_servicename(talloc_tos(), lp_sub, SNUM(conn));
53
0
  do_close = strequal(servicename, state->sharename);
54
55
0
  TALLOC_FREE(servicename);
56
57
0
  return do_close;
58
0
}
59
60
void msg_force_tdis(struct messaging_context *msg,
61
        void *private_data,
62
        uint32_t msg_type,
63
        struct server_id server_id,
64
        DATA_BLOB *data)
65
0
{
66
0
  struct force_tdis_state state = {
67
0
    .sharename = (const char *)data->data,
68
0
  };
69
0
  struct smbd_server_connection *sconn =
70
0
    talloc_get_type_abort(private_data,
71
0
    struct smbd_server_connection);
72
73
0
  if ((data->length == 0) || (data->data[data->length-1] != 0)) {
74
0
    DBG_WARNING("Ignoring invalid sharename\n");
75
0
    return;
76
0
  }
77
78
0
  conn_force_tdis(sconn, force_tdis_check, &state);
79
0
}
80
81
static bool force_tdis_denied_check(
82
  struct connection_struct *conn,
83
  void *private_data)
84
0
{
85
0
  bool do_close;
86
0
  uint32_t share_access;
87
0
  bool read_only;
88
0
  NTSTATUS status;
89
90
0
  do_close = force_tdis_check(conn, private_data);
91
0
  if (!do_close) {
92
0
    return false;
93
0
  }
94
95
0
  status = check_user_share_access(
96
0
    conn,
97
0
    conn->session_info,
98
0
    &share_access,
99
0
    &read_only);
100
0
  if (!NT_STATUS_IS_OK(status)) {
101
0
    DBG_DEBUG("check_user_share_access returned %s\n",
102
0
        nt_errstr(status));
103
0
    return true;  /* close the share */
104
0
  }
105
106
0
  if (conn->share_access != share_access) {
107
0
    DBG_DEBUG("share_access changed from %"PRIx32" to %"PRIx32"\n",
108
0
        conn->share_access, share_access);
109
0
    return true;  /* close the share */
110
0
  }
111
112
0
  if (conn->read_only != read_only) {
113
0
    DBG_DEBUG("read_only changed from %s to %s\n",
114
0
        conn->read_only ? "true" : "false",
115
0
        read_only ? "true" : "false");
116
0
    return true;  /* close the share */
117
0
  }
118
119
  /*
120
   * all still ok, keep the connection open
121
   */
122
0
  return false;
123
0
}
124
125
void msg_force_tdis_denied(
126
  struct messaging_context *msg,
127
  void *private_data,
128
  uint32_t msg_type,
129
  struct server_id server_id,
130
  DATA_BLOB *data)
131
0
{
132
0
  struct force_tdis_state state = {
133
0
    .sharename = (const char *)data->data,
134
0
  };
135
0
  struct smbd_server_connection *sconn =
136
0
    talloc_get_type_abort(private_data,
137
0
    struct smbd_server_connection);
138
139
0
  if ((data->length == 0) || (data->data[data->length-1] != 0)) {
140
0
    DBG_WARNING("Ignoring invalid sharename\n");
141
0
    return;
142
0
  }
143
144
0
  change_to_root_user();
145
0
  reload_services(sconn, conn_snum_used, false);
146
147
0
  conn_force_tdis(sconn, force_tdis_denied_check, &state);
148
0
}