#include "librpc/gen_ndr/ndr_smbXsrv.h"
#include "serverid.h"
#include "lib/util/tevent_ntstatus.h"
+#include "msg_channel.h"
struct smbXsrv_session_table {
struct {
struct {
struct db_context *db_ctx;
} global;
+ struct msg_channel *close_channel;
};
static struct db_context *smbXsrv_session_global_db_ctx = NULL;
return NT_STATUS_OK;
}
+static void smbXsrv_session_close_loop(struct tevent_req *subreq);
+
static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn,
uint32_t lowest_id,
uint32_t highest_id)
{
struct smbXsrv_session_table *table;
NTSTATUS status;
+ struct tevent_req *subreq;
+ int ret;
table = talloc_zero(conn, struct smbXsrv_session_table);
if (table == NULL) {
table->global.db_ctx = smbXsrv_session_global_db_ctx;
+ dbwrap_watch_db(table->global.db_ctx, conn->msg_ctx);
+
+ ret = msg_channel_init(table, conn->msg_ctx,
+ MSG_SMBXSRV_SESSION_CLOSE,
+ &table->close_channel);
+ if (ret != 0) {
+ status = map_nt_error_from_unix_common(errno);
+ TALLOC_FREE(table);
+ return status;
+ }
+
+ subreq = msg_read_send(table, conn->ev_ctx, table->close_channel);
+ if (subreq == NULL) {
+ TALLOC_FREE(table);
+ return NT_STATUS_NO_MEMORY;
+ }
+ tevent_req_set_callback(subreq, smbXsrv_session_close_loop, conn);
+
conn->session_table = table;
return NT_STATUS_OK;
}
+static void smbXsrv_session_close_loop(struct tevent_req *subreq)
+{
+ struct smbXsrv_connection *conn =
+ tevent_req_callback_data(subreq,
+ struct smbXsrv_connection);
+ struct smbXsrv_session_table *table = conn->session_table;
+ int ret;
+ struct messaging_rec *rec = NULL;
+ struct smbXsrv_session_globalB global_blob;
+ enum ndr_err_code ndr_err;
+ struct smbXsrv_session_global0 *global = NULL;
+ struct smbXsrv_session *session = NULL;
+ NTSTATUS status;
+ struct timeval tv = timeval_current();
+ NTTIME now = timeval_to_nttime(&tv);
+ struct connection_struct *cur_conn, *next_conn;
+
+ ret = msg_read_recv(subreq, talloc_tos(), &rec);
+ TALLOC_FREE(subreq);
+ if (ret != 0) {
+ goto next;
+ }
+
+ ndr_err = ndr_pull_struct_blob_all(&rec->buf, rec, &global_blob,
+ (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ goto next;
+ }
+
+ DEBUG(0,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
+ NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
+
+ if (global_blob.version != SMBXSRV_VERSION_0) {
+ goto next;
+ }
+
+ global = global_blob.info.info0;
+
+ status = smb2srv_session_lookup(conn, global->session_wire_id,
+ now, &session);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
+ goto next;
+ }
+ if (!NT_STATUS_IS_OK(status) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
+ goto next;
+ }
+
+ /*
+ * TODO: cancel all outstanding requests on the session
+ */
+ file_close_user(conn->sconn, session->compat->vuid);
+
+ for (cur_conn=conn->sconn->connections; cur_conn; cur_conn=next_conn) {
+ struct smbXsrv_tcon *tcon;
+
+ next_conn = cur_conn->next;
+ tcon = cur_conn->tcon;
+
+ if (cur_conn->vuid != session->compat->vuid) {
+ continue;
+ }
+
+ set_current_service(cur_conn, 0, True);
+ close_cnum(cur_conn, cur_conn->vuid);
+
+ TALLOC_FREE(tcon);
+ }
+
+ invalidate_vuid(conn->sconn, session->compat->vuid);
+ session->compat = NULL;
+
+ session->status = NT_STATUS_USER_SESSION_DELETED;
+ talloc_steal(rec, session);
+
+next:
+ TALLOC_FREE(rec);
+
+ subreq = msg_read_send(table, conn->ev_ctx, table->close_channel);
+ if (subreq == NULL) {
+ // TODO disconnect
+ return;
+ }
+ tevent_req_set_callback(subreq, smbXsrv_session_close_loop, conn);
+}
+
struct smb1srv_session_local_allocate_state {
const uint32_t lowest_id;
const uint32_t highest_id;