smb2_server: make sure we detect stale smbXsrv_connection pointers in smbXsrv_channel...
authorStefan Metzmacher <metze@samba.org>
Fri, 4 Oct 2019 08:02:56 +0000 (10:02 +0200)
committerGünther Deschner <gd@samba.org>
Fri, 15 May 2020 09:04:36 +0000 (09:04 +0000)
Pointer values can be reused (yes, I hit that during my testing!).
Introduce a channel_id to identify connections and also add
some timestamps to make debugging easier.

This makes smbXsrv_session_find_channel() much more robust.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
source3/librpc/idl/smbXsrv.idl
source3/smbd/globals.h
source3/smbd/process.c
source3/smbd/smb2_sesssetup.c
source3/smbd/smbXsrv_client.c
source3/smbd/smbXsrv_session.c

index 4d9249fb3bb18833c6b550622babce52a9eb365f..bdab9345342aebf4abc9ea3bbbf53032da557299 100644 (file)
@@ -141,6 +141,7 @@ interface smbXsrv
                 */
                [ignore] struct smbXsrv_connection      *connections;
                boolean8                server_multi_channel_enabled;
                 */
                [ignore] struct smbXsrv_connection      *connections;
                boolean8                server_multi_channel_enabled;
+               hyper                   next_channel_id;
        } smbXsrv_client;
 
        typedef union {
        } smbXsrv_client;
 
        typedef union {
@@ -200,6 +201,8 @@ interface smbXsrv
 
        typedef struct {
                server_id                               server_id;
 
        typedef struct {
                server_id                               server_id;
+               hyper                                   channel_id;
+               NTTIME                                  creation_time;
                [charset(UTF8),string] char             local_address[];
                [charset(UTF8),string] char             remote_address[];
                [charset(UTF8),string] char             remote_name[];
                [charset(UTF8),string] char             local_address[];
                [charset(UTF8),string] char             remote_address[];
                [charset(UTF8),string] char             remote_name[];
index 79086b3c81c9470903442df598e36b45c2f7bf62..77911f051dfa0656099246fd81925258f97c1d4f 100644 (file)
@@ -231,7 +231,7 @@ bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size);
 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req);
 
 NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd,
 bool smbd_smb2_is_compound(const struct smbd_smb2_request *req);
 
 NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd,
-                            struct smbXsrv_connection **_xconn);
+                            NTTIME now, struct smbXsrv_connection **_xconn);
 
 NTSTATUS reply_smb2002(struct smb_request *req, uint16_t choice);
 NTSTATUS reply_smb20ff(struct smb_request *req, uint16_t choice);
 
 NTSTATUS reply_smb2002(struct smb_request *req, uint16_t choice);
 NTSTATUS reply_smb20ff(struct smb_request *req, uint16_t choice);
@@ -347,6 +347,8 @@ struct smbXsrv_connection {
 
        struct smbXsrv_client *client;
 
 
        struct smbXsrv_client *client;
 
+       NTTIME connect_time;
+       uint64_t channel_id;
        const struct tsocket_address *local_address;
        const struct tsocket_address *remote_address;
        const char *remote_hostname;
        const struct tsocket_address *local_address;
        const struct tsocket_address *remote_address;
        const char *remote_hostname;
@@ -547,6 +549,7 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
                                struct smbXsrv_session **_session);
 NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
                                     struct smbXsrv_connection *conn,
                                struct smbXsrv_session **_session);
 NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
                                     struct smbXsrv_connection *conn,
+                                    NTTIME now,
                                     struct smbXsrv_channel_global0 **_c);
 NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session);
 struct smbXsrv_channel_global0;
                                     struct smbXsrv_channel_global0 **_c);
 NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session);
 struct smbXsrv_channel_global0;
index 2ea721f24c0991bddea45e6de22f0d1c58fb7725..161672bd51671d371b08137cd99330989c82b232 100644 (file)
@@ -3720,7 +3720,7 @@ const char *smbXsrv_connection_dbg(const struct smbXsrv_connection *xconn)
 }
 
 NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd,
 }
 
 NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd,
-                            struct smbXsrv_connection **_xconn)
+                            NTTIME now, struct smbXsrv_connection **_xconn)
 {
        TALLOC_CTX *frame = talloc_stackframe();
        struct smbXsrv_connection *xconn;
 {
        TALLOC_CTX *frame = talloc_stackframe();
        struct smbXsrv_connection *xconn;
@@ -3750,6 +3750,10 @@ NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd,
                return NT_STATUS_NO_MEMORY;
        }
        talloc_steal(frame, xconn);
                return NT_STATUS_NO_MEMORY;
        }
        talloc_steal(frame, xconn);
+       xconn->connect_time = now;
+       if (client->next_channel_id != 0) {
+               xconn->channel_id = client->next_channel_id++;
+       }
 
        xconn->transport.sock = sock_fd;
        smbd_echo_init(xconn);
 
        xconn->transport.sock = sock_fd;
        smbd_echo_init(xconn);
@@ -3994,7 +3998,7 @@ void smbd_process(struct tevent_context *ev_ctx,
                smbd_setup_sig_hup_handler(sconn);
        }
 
                smbd_setup_sig_hup_handler(sconn);
        }
 
-       status = smbd_add_connection(client, sock_fd, &xconn);
+       status = smbd_add_connection(client, sock_fd, now, &xconn);
        if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
                /*
                 * send a negative session response "not listening on calling
        if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
                /*
                 * send a negative session response "not listening on calling
index 3fa1a15910ed17d0cf1bdbab329b3ebedbb216d0..f9c8819327c054ca1814698a20327c8553c1000e 100644 (file)
@@ -912,6 +912,7 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
 
                status = smbXsrv_session_add_channel(smb2req->session,
                                                     smb2req->xconn,
 
                status = smbXsrv_session_add_channel(smb2req->session,
                                                     smb2req->xconn,
+                                                    now,
                                                     &c);
                if (!NT_STATUS_IS_OK(status)) {
                        tevent_req_nterror(req, status);
                                                     &c);
                if (!NT_STATUS_IS_OK(status)) {
                        tevent_req_nterror(req, status);
index ec5b5f1d04c24d60a034e868802b3f8acff488df..c6114d4b8dcfce6089e2d201a3d7b67401dfc6d2 100644 (file)
@@ -523,7 +523,9 @@ NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx,
        client->msg_ctx = msg_ctx;
 
        client->server_multi_channel_enabled = lp_server_multi_channel_support();
        client->msg_ctx = msg_ctx;
 
        client->server_multi_channel_enabled = lp_server_multi_channel_support();
-
+       if (client->server_multi_channel_enabled) {
+               client->next_channel_id = 1;
+       }
        client->table = talloc_move(client, &table);
        table = client->table;
 
        client->table = talloc_move(client, &table);
        table = client->table;
 
@@ -673,7 +675,10 @@ static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq)
 
        DBG_ERR("got connection sockfd[%d]\n", sock_fd);
        NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
 
        DBG_ERR("got connection sockfd[%d]\n", sock_fd);
        NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
-       status = smbd_add_connection(client, sock_fd, &xconn);
+       status = smbd_add_connection(client,
+                                    sock_fd,
+                                    pass_info0->initial_connect_time,
+                                    &xconn);
        if (!NT_STATUS_IS_OK(status)) {
                close(sock_fd);
                sock_fd = -1;
        if (!NT_STATUS_IS_OK(status)) {
                close(sock_fd);
                sock_fd = -1;
index 7d63efb758fbf624011b6617605574bb3b73b336..1ebed144afdb47b2cee0af0d8caf141c626bc77e 100644 (file)
@@ -1293,7 +1293,7 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
        global->creation_time = now;
        global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
 
        global->creation_time = now;
        global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
 
-       status = smbXsrv_session_add_channel(session, conn, &channel);
+       status = smbXsrv_session_add_channel(session, conn, now, &channel);
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(session);
                return status;
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(session);
                return status;
@@ -1338,6 +1338,7 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
 
 NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
                                     struct smbXsrv_connection *conn,
 
 NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
                                     struct smbXsrv_connection *conn,
+                                    NTTIME now,
                                     struct smbXsrv_channel_global0 **_c)
 {
        struct smbXsrv_session_global0 *global = session->global;
                                     struct smbXsrv_channel_global0 **_c)
 {
        struct smbXsrv_session_global0 *global = session->global;
@@ -1363,6 +1364,8 @@ NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
        ZERO_STRUCTP(c);
 
        c->server_id = messaging_server_id(conn->client->msg_ctx);
        ZERO_STRUCTP(c);
 
        c->server_id = messaging_server_id(conn->client->msg_ctx);
+       c->channel_id = conn->channel_id;
+       c->creation_time = now;
        c->local_address = tsocket_address_string(conn->local_address,
                                                  global->channels);
        if (c->local_address == NULL) {
        c->local_address = tsocket_address_string(conn->local_address,
                                                  global->channels);
        if (c->local_address == NULL) {
@@ -1438,10 +1441,16 @@ NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
        for (i=0; i < session->global->num_channels; i++) {
                struct smbXsrv_channel_global0 *c = &session->global->channels[i];
 
        for (i=0; i < session->global->num_channels; i++) {
                struct smbXsrv_channel_global0 *c = &session->global->channels[i];
 
-               if (c->connection == conn) {
-                       *_c = c;
-                       return NT_STATUS_OK;
+               if (c->channel_id != conn->channel_id) {
+                       continue;
+               }
+
+               if (c->connection != conn) {
+                       continue;
                }
                }
+
+               *_c = c;
+               return NT_STATUS_OK;
        }
 
        return NT_STATUS_USER_SESSION_DELETED;
        }
 
        return NT_STATUS_USER_SESSION_DELETED;