/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 | } |