smbd: Add close-denied-share message
authorVolker Lendecke <vl@samba.org>
Mon, 13 Jan 2020 14:19:58 +0000 (15:19 +0100)
committerJeremy Allison <jra@samba.org>
Wed, 15 Jan 2020 21:25:35 +0000 (21:25 +0000)
This is like close-share, but kicks out only active users where share
access controls are changed such that now access would be denied

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
docs-xml/manpages/smbcontrol.1.xml
librpc/idl/messaging.idl
source3/smbd/conn_msg.c
source3/smbd/process.c
source3/smbd/proto.h
source3/smbd/server.c
source3/utils/smbcontrol.c

index 77a2054c449b8fe214aa889ceef89b8c7155f667..935713b46a06d47197841249dc7ea49e5f32baad 100644 (file)
        </listitem>
        </varlistentry>
 
+       <varlistentry><term>close-denied-share</term>
+       <listitem><para>Behave like <constant>close-share</constant>,
+       but don't disconnect users that are still allowed to access
+       the share. It can safely be sent to all smbds after changing
+       share access controls. It will only affect users who have been
+       denied access since having connected initially. This message
+       can only be sent to <constant>smbd</constant>.</para>
+       </listitem>
+       </varlistentry>
+
        <varlistentry>
        <term>debug</term>
        <listitem><para>Set debug level to the value specified by the 
index f355c7503d9435478c6d3d2f6401b96336ffcca5..8160c76149cc0fa5b5b535eeb1ab00b4aa4eadd2 100644 (file)
@@ -111,6 +111,9 @@ interface messaging
                MSG_SMB_NOTIFY_STARTED          = 0x031F,
                MSG_SMB_SLEEP                   = 0x0320,
 
+               /* smbd message */
+               MSG_SMB_FORCE_TDIS_DENIED       = 0x0321,
+
                /* winbind messages */
                MSG_WINBIND_FINISHED            = 0x0401,
                MSG_WINBIND_FORGET_STATE        = 0x0402,
index 3d27121b7432cfc137a25b2390eb2f24dfe02e56..9435d3885086656b069e672c225805dee5f9b8b4 100644 (file)
@@ -77,3 +77,72 @@ void msg_force_tdis(struct messaging_context *msg,
 
        conn_force_tdis(sconn, force_tdis_check, &state);
 }
+
+static bool force_tdis_denied_check(
+       struct connection_struct *conn,
+       void *private_data)
+{
+       bool do_close;
+       uint32_t share_access;
+       bool read_only;
+       NTSTATUS status;
+
+       do_close = force_tdis_check(conn, private_data);
+       if (!do_close) {
+               return false;
+       }
+
+       status = check_user_share_access(
+               conn,
+               conn->session_info,
+               &share_access,
+               &read_only);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_DEBUG("check_user_share_access returned %s\n",
+                         nt_errstr(status));
+               return true;    /* close the share */
+       }
+
+       if (conn->share_access != share_access) {
+               DBG_DEBUG("share_access changed from %"PRIx32" to %"PRIx32"\n",
+                         conn->share_access, share_access);
+               return true;    /* close the share */
+       }
+
+       if (conn->read_only != read_only) {
+               DBG_DEBUG("read_only changed from %s to %s\n",
+                         conn->read_only ? "true" : "false",
+                         read_only ? "true" : "false");
+               return true;    /* close the share */
+       }
+
+       /*
+        * all still ok, keep the connection open
+        */
+       return false;
+}
+
+void msg_force_tdis_denied(
+       struct messaging_context *msg,
+       void *private_data,
+       uint32_t msg_type,
+       struct server_id server_id,
+       DATA_BLOB *data)
+{
+       struct force_tdis_state state = {
+               .sharename = (const char *)data->data,
+       };
+       struct smbd_server_connection *sconn =
+               talloc_get_type_abort(private_data,
+               struct smbd_server_connection);
+
+       if ((data->length == 0) || (data->data[data->length-1] != 0)) {
+               DBG_WARNING("Ignoring invalid sharename\n");
+               return;
+       }
+
+       change_to_root_user();
+       reload_services(sconn, conn_snum_used, false);
+
+       conn_force_tdis(sconn, force_tdis_denied_check, &state);
+}
index f6eeafc88cfc17bb20d36e5182907f66fc5f9df7..70398b4967e329512646380a07abdff3d453b449 100644 (file)
@@ -4096,6 +4096,11 @@ void smbd_process(struct tevent_context *ev_ctx,
        /* register our message handlers */
        messaging_register(sconn->msg_ctx, sconn,
                           MSG_SMB_FORCE_TDIS, msg_force_tdis);
+       messaging_register(
+               sconn->msg_ctx,
+               sconn,
+               MSG_SMB_FORCE_TDIS_DENIED,
+               msg_force_tdis_denied);
        messaging_register(sconn->msg_ctx, sconn,
                           MSG_SMB_CLOSE_FILE, msg_close_file);
        messaging_register(sconn->msg_ctx, sconn,
index 88becd7df7287f2d878a22bd0b0c81950cb00d8a..de4a53c6187003181cacf5eb1fa8b9e4d582cef0 100644 (file)
@@ -164,6 +164,12 @@ void msg_force_tdis(struct messaging_context *msg,
                    uint32_t msg_type,
                    struct server_id server_id,
                    DATA_BLOB *data);
+void msg_force_tdis_denied(
+       struct messaging_context *msg,
+       void *private_data,
+       uint32_t msg_type,
+       struct server_id server_id,
+       DATA_BLOB *data);
 
 /* The following definitions come from smbd/connection.c  */
 
index 8fd4752ea4557a7c3e29d238d312be8baa815b51..cedd2b312a332c1d64e8e09dc2f1f6692b02ee15 100644 (file)
@@ -1254,6 +1254,8 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
        messaging_register(msg_ctx, NULL, MSG_DEBUG, smbd_msg_debug);
        messaging_register(msg_ctx, NULL, MSG_SMB_FORCE_TDIS,
                           smb_parent_send_to_children);
+       messaging_register(msg_ctx, NULL, MSG_SMB_FORCE_TDIS_DENIED,
+                          smb_parent_send_to_children);
        messaging_register(msg_ctx, NULL, MSG_SMB_KILL_CLIENT_IP,
                           smb_parent_send_to_children);
        messaging_register(msg_ctx, NULL, MSG_SMB_TELL_NUM_CHILDREN,
index 35cb7d39a02196cce0cd2ee4b37c980c70cef6a3..d779f0d14ea7b5e2bd62da382bbe4a0ca3b1bbb8 100644 (file)
@@ -807,6 +807,30 @@ static bool do_closeshare(struct tevent_context *ev_ctx,
                            strlen(argv[1]) + 1);
 }
 
+/*
+ * Close a share if access denied by now
+ **/
+
+static bool do_close_denied_share(
+       struct tevent_context *ev_ctx,
+       struct messaging_context *msg_ctx,
+       const struct server_id pid,
+       const int argc, const char **argv)
+{
+       if (argc != 2) {
+               fprintf(stderr, "Usage: smbcontrol <dest> close-denied-share "
+                       "<sharename>\n");
+               return False;
+       }
+
+       return send_message(
+               msg_ctx,
+               pid,
+               MSG_SMB_FORCE_TDIS_DENIED,
+               argv[1],
+               strlen(argv[1]) + 1);
+}
+
 /* Kill a client by IP address */
 static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
                                 struct messaging_context *msg_ctx,
@@ -1433,6 +1457,11 @@ static const struct {
                .fn   = do_closeshare,
                .help = "Forcibly disconnect a share",
        },
+       {
+               .name = "close-denied-share",
+               .fn   = do_close_denied_share,
+               .help = "Forcibly disconnect users from shares disallowed now",
+       },
        {
                .name = "kill-client-ip",
                .fn   = do_kill_client_by_ip,