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 :
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 72 : static bool force_tdis_check(
38 : struct connection_struct *conn,
39 : void *private_data)
40 : {
41 72 : struct force_tdis_state *state = private_data;
42 0 : const struct loadparm_substitution *lp_sub =
43 72 : loadparm_s3_global_substitution();
44 72 : char *servicename = NULL;
45 0 : bool do_close;
46 :
47 72 : if (strcmp(state->sharename, "*") == 0) {
48 0 : DBG_WARNING("Forcing close of all shares\n");
49 0 : return true;
50 : }
51 :
52 72 : servicename = lp_servicename(talloc_tos(), lp_sub, SNUM(conn));
53 72 : do_close = strequal(servicename, state->sharename);
54 :
55 72 : TALLOC_FREE(servicename);
56 :
57 72 : return do_close;
58 : }
59 :
60 66 : 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 : {
66 66 : struct force_tdis_state state = {
67 66 : .sharename = (const char *)data->data,
68 : };
69 0 : struct smbd_server_connection *sconn =
70 66 : talloc_get_type_abort(private_data,
71 : struct smbd_server_connection);
72 :
73 66 : if ((data->length == 0) || (data->data[data->length-1] != 0)) {
74 0 : DBG_WARNING("Ignoring invalid sharename\n");
75 0 : return;
76 : }
77 :
78 66 : conn_force_tdis(sconn, force_tdis_check, &state);
79 : }
80 :
81 4 : static bool force_tdis_denied_check(
82 : struct connection_struct *conn,
83 : void *private_data)
84 : {
85 0 : bool do_close;
86 0 : uint32_t share_access;
87 0 : bool read_only;
88 0 : NTSTATUS status;
89 :
90 4 : do_close = force_tdis_check(conn, private_data);
91 4 : if (!do_close) {
92 0 : return false;
93 : }
94 :
95 4 : status = check_user_share_access(
96 : conn,
97 4 : conn->session_info,
98 : &share_access,
99 : &read_only);
100 4 : if (!NT_STATUS_IS_OK(status)) {
101 2 : DBG_DEBUG("check_user_share_access returned %s\n",
102 : nt_errstr(status));
103 2 : return true; /* close the share */
104 : }
105 :
106 2 : if (conn->share_access != share_access) {
107 0 : DBG_DEBUG("share_access changed from %"PRIx32" to %"PRIx32"\n",
108 : conn->share_access, share_access);
109 0 : return true; /* close the share */
110 : }
111 :
112 2 : if (conn->read_only != read_only) {
113 0 : DBG_DEBUG("read_only changed from %s to %s\n",
114 : conn->read_only ? "true" : "false",
115 : read_only ? "true" : "false");
116 0 : return true; /* close the share */
117 : }
118 :
119 : /*
120 : * all still ok, keep the connection open
121 : */
122 2 : return false;
123 : }
124 :
125 4 : 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 : {
132 4 : struct force_tdis_state state = {
133 4 : .sharename = (const char *)data->data,
134 : };
135 0 : struct smbd_server_connection *sconn =
136 4 : talloc_get_type_abort(private_data,
137 : struct smbd_server_connection);
138 :
139 4 : if ((data->length == 0) || (data->data[data->length-1] != 0)) {
140 0 : DBG_WARNING("Ignoring invalid sharename\n");
141 0 : return;
142 : }
143 :
144 4 : change_to_root_user();
145 4 : reload_services(sconn, conn_snum_used, false);
146 :
147 4 : conn_force_tdis(sconn, force_tdis_denied_check, &state);
148 : }
|