LCOV - code coverage report
Current view: top level - source3/smbd - smbXsrv_session.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 839 1191 70.4 %
Date: 2024-04-21 15:09:00 Functions: 50 54 92.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Stefan Metzmacher 2011-2012
       5             :    Copyright (C) Michael Adam 2012
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "smbXsrv_session.h"
      23             : #include "system/filesys.h"
      24             : #include <tevent.h>
      25             : #include "lib/util/server_id.h"
      26             : #include "smbd/smbd.h"
      27             : #include "smbd/globals.h"
      28             : #include "dbwrap/dbwrap.h"
      29             : #include "dbwrap/dbwrap_rbt.h"
      30             : #include "dbwrap/dbwrap_open.h"
      31             : #include "dbwrap/dbwrap_watch.h"
      32             : #include "session.h"
      33             : #include "auth.h"
      34             : #include "auth/gensec/gensec.h"
      35             : #include "../lib/tsocket/tsocket.h"
      36             : #include "../libcli/security/security.h"
      37             : #include "messages.h"
      38             : #include "lib/util/util_tdb.h"
      39             : #include "librpc/gen_ndr/ndr_smbXsrv.h"
      40             : #include "serverid.h"
      41             : #include "lib/util/tevent_ntstatus.h"
      42             : #include "lib/global_contexts.h"
      43             : #include "source3/include/util_tdb.h"
      44             : 
      45             : struct smbXsrv_session_table {
      46             :         struct {
      47             :                 struct db_context *db_ctx;
      48             :                 uint32_t lowest_id;
      49             :                 uint32_t highest_id;
      50             :                 uint32_t max_sessions;
      51             :                 uint32_t num_sessions;
      52             :         } local;
      53             :         struct {
      54             :                 struct db_context *db_ctx;
      55             :         } global;
      56             : };
      57             : 
      58             : static struct db_context *smbXsrv_session_global_db_ctx = NULL;
      59             : 
      60       30905 : NTSTATUS smbXsrv_session_global_init(struct messaging_context *msg_ctx)
      61             : {
      62       30905 :         char *global_path = NULL;
      63       30905 :         struct db_context *backend = NULL;
      64       30905 :         struct db_context *db_ctx = NULL;
      65             : 
      66       30905 :         if (smbXsrv_session_global_db_ctx != NULL) {
      67       30883 :                 return NT_STATUS_OK;
      68             :         }
      69             : 
      70             :         /*
      71             :          * This contains secret information like session keys!
      72             :          */
      73          22 :         global_path = lock_path(talloc_tos(), "smbXsrv_session_global.tdb");
      74          22 :         if (global_path == NULL) {
      75           0 :                 return NT_STATUS_NO_MEMORY;
      76             :         }
      77             : 
      78          22 :         backend = db_open(NULL, global_path,
      79             :                           SMBD_VOLATILE_TDB_HASH_SIZE,
      80             :                           SMBD_VOLATILE_TDB_FLAGS,
      81             :                           O_RDWR | O_CREAT, 0600,
      82             :                           DBWRAP_LOCK_ORDER_1,
      83             :                           DBWRAP_FLAG_NONE);
      84          22 :         TALLOC_FREE(global_path);
      85          22 :         if (backend == NULL) {
      86           0 :                 NTSTATUS status;
      87             : 
      88           0 :                 status = map_nt_error_from_unix_common(errno);
      89             : 
      90           0 :                 return status;
      91             :         }
      92             : 
      93          22 :         db_ctx = db_open_watched(NULL, &backend, global_messaging_context());
      94          22 :         if (db_ctx == NULL) {
      95           0 :                 TALLOC_FREE(backend);
      96           0 :                 return NT_STATUS_NO_MEMORY;
      97             :         }
      98             : 
      99          22 :         smbXsrv_session_global_db_ctx = db_ctx;
     100             : 
     101          22 :         return NT_STATUS_OK;
     102             : }
     103             : 
     104             : /*
     105             :  * NOTE:
     106             :  * We need to store the keys in big endian so that dbwrap_rbt's memcmp
     107             :  * has the same result as integer comparison between the uint32_t
     108             :  * values.
     109             :  *
     110             :  * TODO: implement string based key
     111             :  */
     112             : 
     113             : #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
     114             : 
     115      197188 : static TDB_DATA smbXsrv_session_global_id_to_key(uint32_t id,
     116             :                                                  uint8_t *key_buf)
     117             : {
     118        4300 :         TDB_DATA key;
     119             : 
     120      197188 :         RSIVAL(key_buf, 0, id);
     121             : 
     122      197188 :         key = make_tdb_data(key_buf, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE);
     123             : 
     124      197188 :         return key;
     125             : }
     126             : 
     127             : #if 0
     128             : static NTSTATUS smbXsrv_session_global_key_to_id(TDB_DATA key, uint32_t *id)
     129             : {
     130             :         if (id == NULL) {
     131             :                 return NT_STATUS_INVALID_PARAMETER;
     132             :         }
     133             : 
     134             :         if (key.dsize != SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE) {
     135             :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     136             :         }
     137             : 
     138             :         *id = RIVAL(key.dptr, 0);
     139             : 
     140             :         return NT_STATUS_OK;
     141             : }
     142             : #endif
     143             : 
     144             : #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
     145             : 
     146     4001372 : static TDB_DATA smbXsrv_session_local_id_to_key(uint32_t id,
     147             :                                                 uint8_t *key_buf)
     148             : {
     149       37045 :         TDB_DATA key;
     150             : 
     151     4001372 :         RSIVAL(key_buf, 0, id);
     152             : 
     153     4001372 :         key = make_tdb_data(key_buf, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE);
     154             : 
     155     4001372 :         return key;
     156             : }
     157             : 
     158           0 : static NTSTATUS smbXsrv_session_local_key_to_id(TDB_DATA key, uint32_t *id)
     159             : {
     160           0 :         if (id == NULL) {
     161           0 :                 return NT_STATUS_INVALID_PARAMETER;
     162             :         }
     163             : 
     164           0 :         if (key.dsize != SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE) {
     165           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     166             :         }
     167             : 
     168           0 :         *id = RIVAL(key.dptr, 0);
     169             : 
     170           0 :         return NT_STATUS_OK;
     171             : }
     172             : 
     173      197188 : static struct db_record *smbXsrv_session_global_fetch_locked(
     174             :                         struct db_context *db,
     175             :                         uint32_t id,
     176             :                         TALLOC_CTX *mem_ctx)
     177             : {
     178        4300 :         TDB_DATA key;
     179        4300 :         uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE];
     180      197188 :         struct db_record *rec = NULL;
     181             : 
     182      197188 :         key = smbXsrv_session_global_id_to_key(id, key_buf);
     183             : 
     184      197188 :         rec = dbwrap_fetch_locked(db, mem_ctx, key);
     185             : 
     186      197188 :         if (rec == NULL) {
     187           0 :                 DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id,
     188             :                           tdb_data_dbg(key));
     189             :         }
     190             : 
     191      197188 :         return rec;
     192             : }
     193             : 
     194       35589 : static struct db_record *smbXsrv_session_local_fetch_locked(
     195             :                         struct db_context *db,
     196             :                         uint32_t id,
     197             :                         TALLOC_CTX *mem_ctx)
     198             : {
     199         781 :         TDB_DATA key;
     200         781 :         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
     201       35589 :         struct db_record *rec = NULL;
     202             : 
     203       35589 :         key = smbXsrv_session_local_id_to_key(id, key_buf);
     204             : 
     205       35589 :         rec = dbwrap_fetch_locked(db, mem_ctx, key);
     206             : 
     207       35589 :         if (rec == NULL) {
     208           0 :                 DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id,
     209             :                           tdb_data_dbg(key));
     210             :         }
     211             : 
     212       35589 :         return rec;
     213             : }
     214             : 
     215             : static void smbXsrv_session_close_loop(struct tevent_req *subreq);
     216             : 
     217       30863 : static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn,
     218             :                                            uint32_t lowest_id,
     219             :                                            uint32_t highest_id,
     220             :                                            uint32_t max_sessions)
     221             : {
     222       30863 :         struct smbXsrv_client *client = conn->client;
     223         834 :         struct smbXsrv_session_table *table;
     224         834 :         NTSTATUS status;
     225         834 :         struct tevent_req *subreq;
     226         834 :         uint64_t max_range;
     227             : 
     228       30863 :         if (lowest_id > highest_id) {
     229           0 :                 return NT_STATUS_INTERNAL_ERROR;
     230             :         }
     231             : 
     232       30863 :         max_range = highest_id;
     233       30863 :         max_range -= lowest_id;
     234       30863 :         max_range += 1;
     235             : 
     236       30863 :         if (max_sessions > max_range) {
     237           0 :                 return NT_STATUS_INTERNAL_ERROR;
     238             :         }
     239             : 
     240       30863 :         table = talloc_zero(client, struct smbXsrv_session_table);
     241       30863 :         if (table == NULL) {
     242           0 :                 return NT_STATUS_NO_MEMORY;
     243             :         }
     244             : 
     245       30863 :         table->local.db_ctx = db_open_rbt(table);
     246       30863 :         if (table->local.db_ctx == NULL) {
     247           0 :                 TALLOC_FREE(table);
     248           0 :                 return NT_STATUS_NO_MEMORY;
     249             :         }
     250       30863 :         table->local.lowest_id = lowest_id;
     251       30863 :         table->local.highest_id = highest_id;
     252       30863 :         table->local.max_sessions = max_sessions;
     253             : 
     254       30863 :         status = smbXsrv_session_global_init(client->msg_ctx);
     255       30863 :         if (!NT_STATUS_IS_OK(status)) {
     256           0 :                 TALLOC_FREE(table);
     257           0 :                 return status;
     258             :         }
     259             : 
     260       30863 :         table->global.db_ctx = smbXsrv_session_global_db_ctx;
     261             : 
     262       30863 :         subreq = messaging_read_send(table,
     263             :                                      client->raw_ev_ctx,
     264             :                                      client->msg_ctx,
     265             :                                      MSG_SMBXSRV_SESSION_CLOSE);
     266       30863 :         if (subreq == NULL) {
     267           0 :                 TALLOC_FREE(table);
     268           0 :                 return NT_STATUS_NO_MEMORY;
     269             :         }
     270       30863 :         tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
     271             : 
     272       30863 :         client->session_table = table;
     273       30863 :         return NT_STATUS_OK;
     274             : }
     275             : 
     276             : static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq);
     277             : 
     278          54 : static void smbXsrv_session_close_loop(struct tevent_req *subreq)
     279             : {
     280           4 :         struct smbXsrv_client *client =
     281          54 :                 tevent_req_callback_data(subreq,
     282             :                 struct smbXsrv_client);
     283          54 :         struct smbXsrv_session_table *table = client->session_table;
     284           4 :         int ret;
     285          54 :         struct messaging_rec *rec = NULL;
     286           4 :         struct smbXsrv_session_closeB close_blob;
     287           4 :         enum ndr_err_code ndr_err;
     288          54 :         struct smbXsrv_session_close0 *close_info0 = NULL;
     289          54 :         struct smbXsrv_session *session = NULL;
     290           4 :         NTSTATUS status;
     291          54 :         struct timeval tv = timeval_current();
     292          54 :         NTTIME now = timeval_to_nttime(&tv);
     293             : 
     294          54 :         ret = messaging_read_recv(subreq, talloc_tos(), &rec);
     295          54 :         TALLOC_FREE(subreq);
     296          54 :         if (ret != 0) {
     297           0 :                 goto next;
     298             :         }
     299             : 
     300          54 :         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &close_blob,
     301             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_closeB);
     302          54 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     303           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     304           0 :                 DBG_WARNING("ndr_pull_struct_blob - %s\n", nt_errstr(status));
     305           0 :                 goto next;
     306             :         }
     307             : 
     308          54 :         DBG_DEBUG("MSG_SMBXSRV_SESSION_CLOSE\n");
     309          54 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     310           0 :                 NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     311             :         }
     312             : 
     313          54 :         if (close_blob.version != SMBXSRV_VERSION_0) {
     314           0 :                 DBG_ERR("ignore invalid version %u\n", close_blob.version);
     315           0 :                 NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     316           0 :                 goto next;
     317             :         }
     318             : 
     319          54 :         close_info0 = close_blob.info.info0;
     320          54 :         if (close_info0 == NULL) {
     321           0 :                 DBG_ERR("ignore NULL info %u\n", close_blob.version);
     322           0 :                 NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     323           0 :                 goto next;
     324             :         }
     325             : 
     326          54 :         status = smb2srv_session_lookup_client(client,
     327             :                                                close_info0->old_session_wire_id,
     328             :                                                now, &session);
     329          54 :         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
     330           0 :                 DBG_INFO("old_session_wire_id %" PRIu64 " not found\n",
     331             :                          close_info0->old_session_wire_id);
     332           0 :                 if (DEBUGLVL(DBGLVL_INFO)) {
     333           0 :                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     334             :                 }
     335           0 :                 goto next;
     336             :         }
     337          54 :         if (!NT_STATUS_IS_OK(status) &&
     338           0 :             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
     339           0 :             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
     340           0 :                 DBG_WARNING("old_session_wire_id %" PRIu64 " - %s\n",
     341             :                             close_info0->old_session_wire_id,
     342             :                             nt_errstr(status));
     343           0 :                 if (DEBUGLVL(DBGLVL_WARNING)) {
     344           0 :                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     345             :                 }
     346           0 :                 goto next;
     347             :         }
     348             : 
     349          54 :         if (session->global->session_global_id != close_info0->old_session_global_id) {
     350           0 :                 DBG_WARNING("old_session_wire_id %" PRIu64 " - "
     351             :                             "global %" PRIu32 " != %" PRIu32 "\n",
     352             :                             close_info0->old_session_wire_id,
     353             :                             session->global->session_global_id,
     354             :                             close_info0->old_session_global_id);
     355           0 :                 if (DEBUGLVL(DBGLVL_WARNING)) {
     356           0 :                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     357             :                 }
     358           0 :                 goto next;
     359             :         }
     360             : 
     361          54 :         if (session->global->creation_time != close_info0->old_creation_time) {
     362           0 :                 DBG_WARNING("old_session_wire_id %" PRIu64 " - "
     363             :                             "creation %s (%" PRIu64 ") != %s (%" PRIu64 ")\n",
     364             :                             close_info0->old_session_wire_id,
     365             :                             nt_time_string(rec,
     366             :                                            session->global->creation_time),
     367             :                             session->global->creation_time,
     368             :                             nt_time_string(rec,
     369             :                                            close_info0->old_creation_time),
     370             :                             close_info0->old_creation_time);
     371           0 :                 if (DEBUGLVL(DBGLVL_WARNING)) {
     372           0 :                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     373             :                 }
     374           0 :                 goto next;
     375             :         }
     376             : 
     377          54 :         subreq = smb2srv_session_shutdown_send(session, client->raw_ev_ctx,
     378             :                                                session, NULL);
     379          54 :         if (subreq == NULL) {
     380           0 :                 status = NT_STATUS_NO_MEMORY;
     381           0 :                 DBG_ERR("smb2srv_session_shutdown_send(%" PRIu64
     382             :                         ") failed: %s\n",
     383             :                         session->global->session_wire_id,
     384             :                         nt_errstr(status));
     385           0 :                 if (DEBUGLVL(DBGLVL_WARNING)) {
     386           0 :                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     387             :                 }
     388           0 :                 goto next;
     389             :         }
     390          54 :         tevent_req_set_callback(subreq,
     391             :                                 smbXsrv_session_close_shutdown_done,
     392             :                                 session);
     393             : 
     394          54 : next:
     395          54 :         TALLOC_FREE(rec);
     396             : 
     397          54 :         subreq = messaging_read_send(table,
     398             :                                      client->raw_ev_ctx,
     399             :                                      client->msg_ctx,
     400             :                                      MSG_SMBXSRV_SESSION_CLOSE);
     401          54 :         if (subreq == NULL) {
     402           0 :                 const char *r;
     403           0 :                 r = "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
     404           0 :                 exit_server_cleanly(r);
     405             :                 return;
     406             :         }
     407          54 :         tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
     408             : }
     409             : 
     410          54 : static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq)
     411             : {
     412           4 :         struct smbXsrv_session *session =
     413          54 :                 tevent_req_callback_data(subreq,
     414             :                 struct smbXsrv_session);
     415           4 :         NTSTATUS status;
     416             : 
     417          54 :         status = smb2srv_session_shutdown_recv(subreq);
     418          54 :         TALLOC_FREE(subreq);
     419          54 :         if (!NT_STATUS_IS_OK(status)) {
     420           0 :                 DBG_ERR("smb2srv_session_shutdown_recv(%" PRIu64
     421             :                         ") failed: %s\n",
     422             :                         session->global->session_wire_id,
     423             :                         nt_errstr(status));
     424             :         }
     425             : 
     426          54 :         status = smbXsrv_session_logoff(session);
     427          54 :         if (!NT_STATUS_IS_OK(status)) {
     428           0 :                 DBG_ERR("smbXsrv_session_logoff(%" PRIu64 ") failed: %s\n",
     429             :                         session->global->session_wire_id,
     430             :                         nt_errstr(status));
     431             :         }
     432             : 
     433          54 :         TALLOC_FREE(session);
     434          54 : }
     435             : 
     436             : struct smb1srv_session_local_allocate_state {
     437             :         const uint32_t lowest_id;
     438             :         const uint32_t highest_id;
     439             :         uint32_t last_id;
     440             :         uint32_t useable_id;
     441             :         NTSTATUS status;
     442             : };
     443             : 
     444           0 : static int smb1srv_session_local_allocate_traverse(struct db_record *rec,
     445             :                                                    void *private_data)
     446             : {
     447           0 :         struct smb1srv_session_local_allocate_state *state =
     448             :                 (struct smb1srv_session_local_allocate_state *)private_data;
     449           0 :         TDB_DATA key = dbwrap_record_get_key(rec);
     450           0 :         uint32_t id = 0;
     451           0 :         NTSTATUS status;
     452             : 
     453           0 :         status = smbXsrv_session_local_key_to_id(key, &id);
     454           0 :         if (!NT_STATUS_IS_OK(status)) {
     455           0 :                 state->status = status;
     456           0 :                 return -1;
     457             :         }
     458             : 
     459           0 :         if (id <= state->last_id) {
     460           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     461           0 :                 return -1;
     462             :         }
     463           0 :         state->last_id = id;
     464             : 
     465           0 :         if (id > state->useable_id) {
     466           0 :                 state->status = NT_STATUS_OK;
     467           0 :                 return -1;
     468             :         }
     469             : 
     470           0 :         if (state->useable_id == state->highest_id) {
     471           0 :                 state->status = NT_STATUS_INSUFFICIENT_RESOURCES;
     472           0 :                 return -1;
     473             :         }
     474             : 
     475           0 :         state->useable_id +=1;
     476           0 :         return 0;
     477             : }
     478             : 
     479        7046 : static NTSTATUS smb1srv_session_local_allocate_id(struct db_context *db,
     480             :                                                   uint32_t lowest_id,
     481             :                                                   uint32_t highest_id,
     482             :                                                   TALLOC_CTX *mem_ctx,
     483             :                                                   struct db_record **_rec,
     484             :                                                   uint32_t *_id)
     485             : {
     486        7046 :         struct smb1srv_session_local_allocate_state state = {
     487             :                 .lowest_id = lowest_id,
     488             :                 .highest_id = highest_id,
     489             :                 .last_id = 0,
     490             :                 .useable_id = lowest_id,
     491             :                 .status = NT_STATUS_INTERNAL_ERROR,
     492             :         };
     493         133 :         uint32_t i;
     494         133 :         uint32_t range;
     495         133 :         NTSTATUS status;
     496        7046 :         int count = 0;
     497             : 
     498        7046 :         *_rec = NULL;
     499        7046 :         *_id = 0;
     500             : 
     501        7046 :         if (lowest_id > highest_id) {
     502           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
     503             :         }
     504             : 
     505             :         /*
     506             :          * first we try randomly
     507             :          */
     508        7046 :         range = (highest_id - lowest_id) + 1;
     509             : 
     510        7046 :         for (i = 0; i < (range / 2); i++) {
     511         133 :                 uint32_t id;
     512         133 :                 TDB_DATA val;
     513        7046 :                 struct db_record *rec = NULL;
     514             : 
     515        7046 :                 id = generate_random() % range;
     516        7046 :                 id += lowest_id;
     517             : 
     518        7046 :                 if (id < lowest_id) {
     519           0 :                         id = lowest_id;
     520             :                 }
     521        7046 :                 if (id > highest_id) {
     522           0 :                         id = highest_id;
     523             :                 }
     524             : 
     525        7046 :                 rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
     526        7046 :                 if (rec == NULL) {
     527           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     528             :                 }
     529             : 
     530        7046 :                 val = dbwrap_record_get_value(rec);
     531        7046 :                 if (val.dsize != 0) {
     532           0 :                         TALLOC_FREE(rec);
     533           0 :                         continue;
     534             :                 }
     535             : 
     536        7046 :                 *_rec = rec;
     537        7046 :                 *_id = id;
     538        7046 :                 return NT_STATUS_OK;
     539             :         }
     540             : 
     541             :         /*
     542             :          * if the range is almost full,
     543             :          * we traverse the whole table
     544             :          * (this relies on sorted behavior of dbwrap_rbt)
     545             :          */
     546           0 :         status = dbwrap_traverse_read(db, smb1srv_session_local_allocate_traverse,
     547             :                                       &state, &count);
     548           0 :         if (NT_STATUS_IS_OK(status)) {
     549           0 :                 if (NT_STATUS_IS_OK(state.status)) {
     550           0 :                         return NT_STATUS_INTERNAL_ERROR;
     551             :                 }
     552             : 
     553           0 :                 if (!NT_STATUS_EQUAL(state.status, NT_STATUS_INTERNAL_ERROR)) {
     554           0 :                         return state.status;
     555             :                 }
     556             : 
     557           0 :                 if (state.useable_id <= state.highest_id) {
     558           0 :                         state.status = NT_STATUS_OK;
     559             :                 } else {
     560           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     561             :                 }
     562           0 :         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_CORRUPTION)) {
     563             :                 /*
     564             :                  * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
     565             :                  *
     566             :                  * If we get anything else it is an error, because it
     567             :                  * means we did not manage to find a free slot in
     568             :                  * the db.
     569             :                  */
     570           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
     571             :         }
     572             : 
     573           0 :         if (NT_STATUS_IS_OK(state.status)) {
     574           0 :                 uint32_t id;
     575           0 :                 TDB_DATA val;
     576           0 :                 struct db_record *rec = NULL;
     577             : 
     578           0 :                 id = state.useable_id;
     579             : 
     580           0 :                 rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
     581           0 :                 if (rec == NULL) {
     582           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     583             :                 }
     584             : 
     585           0 :                 val = dbwrap_record_get_value(rec);
     586           0 :                 if (val.dsize != 0) {
     587           0 :                         TALLOC_FREE(rec);
     588           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     589             :                 }
     590             : 
     591           0 :                 *_rec = rec;
     592           0 :                 *_id = id;
     593           0 :                 return NT_STATUS_OK;
     594             :         }
     595             : 
     596           0 :         return state.status;
     597             : }
     598             : 
     599             : struct smbXsrv_session_local_fetch_state {
     600             :         struct smbXsrv_session *session;
     601             :         NTSTATUS status;
     602             : };
     603             : 
     604     3964709 : static void smbXsrv_session_local_fetch_parser(TDB_DATA key, TDB_DATA data,
     605             :                                                void *private_data)
     606             : {
     607     3964709 :         struct smbXsrv_session_local_fetch_state *state =
     608             :                 (struct smbXsrv_session_local_fetch_state *)private_data;
     609       36098 :         void *ptr;
     610             : 
     611     3964709 :         if (data.dsize != sizeof(ptr)) {
     612           0 :                 state->status = NT_STATUS_INTERNAL_DB_ERROR;
     613           0 :                 return;
     614             :         }
     615             : 
     616     3964709 :         memcpy(&ptr, data.dptr, data.dsize);
     617     3964709 :         state->session = talloc_get_type_abort(ptr, struct smbXsrv_session);
     618     3964709 :         state->status = NT_STATUS_OK;
     619             : }
     620             : 
     621     2168541 : static NTSTATUS smbXsrv_session_local_lookup(struct smbXsrv_session_table *table,
     622             :                                              /* conn: optional */
     623             :                                              struct smbXsrv_connection *conn,
     624             :                                              uint32_t session_local_id,
     625             :                                              NTTIME now,
     626             :                                              struct smbXsrv_session **_session)
     627             : {
     628     2168541 :         struct smbXsrv_session_local_fetch_state state = {
     629             :                 .session = NULL,
     630             :                 .status = NT_STATUS_INTERNAL_ERROR,
     631             :         };
     632       20567 :         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
     633       20567 :         TDB_DATA key;
     634       20567 :         NTSTATUS status;
     635             : 
     636     2168541 :         *_session = NULL;
     637             : 
     638     2168541 :         if (session_local_id == 0) {
     639       82745 :                 return NT_STATUS_USER_SESSION_DELETED;
     640             :         }
     641             : 
     642     2085796 :         if (table == NULL) {
     643             :                 /* this might happen before the end of negprot */
     644           0 :                 return NT_STATUS_USER_SESSION_DELETED;
     645             :         }
     646             : 
     647     2085796 :         if (table->local.db_ctx == NULL) {
     648           0 :                 return NT_STATUS_INTERNAL_ERROR;
     649             :         }
     650             : 
     651     2085796 :         key = smbXsrv_session_local_id_to_key(session_local_id, key_buf);
     652             : 
     653     2085796 :         status = dbwrap_parse_record(table->local.db_ctx, key,
     654             :                                      smbXsrv_session_local_fetch_parser,
     655             :                                      &state);
     656     2085796 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     657        1057 :                 return NT_STATUS_USER_SESSION_DELETED;
     658     2084739 :         } else if (!NT_STATUS_IS_OK(status)) {
     659           0 :                 return status;
     660             :         }
     661     2084739 :         if (!NT_STATUS_IS_OK(state.status)) {
     662           0 :                 return state.status;
     663             :         }
     664             : 
     665     2084739 :         if (NT_STATUS_EQUAL(state.session->status, NT_STATUS_USER_SESSION_DELETED)) {
     666           0 :                 return NT_STATUS_USER_SESSION_DELETED;
     667             :         }
     668             : 
     669             :         /*
     670             :          * If a connection is specified check if the session is
     671             :          * valid on the channel.
     672             :          */
     673     2084739 :         if (conn != NULL) {
     674     2063884 :                 struct smbXsrv_channel_global0 *c = NULL;
     675             : 
     676     2063884 :                 status = smbXsrv_session_find_channel(state.session, conn, &c);
     677     2063884 :                 if (!NT_STATUS_IS_OK(status)) {
     678         140 :                         return status;
     679             :                 }
     680             :         }
     681             : 
     682     2084599 :         state.session->idle_time = now;
     683             : 
     684     2084599 :         if (!NT_STATUS_IS_OK(state.session->status)) {
     685       31173 :                 *_session = state.session;
     686       31173 :                 return state.session->status;
     687             :         }
     688             : 
     689     2053426 :         if (now > state.session->global->expiration_time) {
     690          49 :                 state.session->status = NT_STATUS_NETWORK_SESSION_EXPIRED;
     691             :         }
     692             : 
     693     2053426 :         *_session = state.session;
     694     2053426 :         return state.session->status;
     695             : }
     696             : 
     697       32243 : static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0 *global)
     698             : {
     699       32243 :         return 0;
     700             : }
     701             : 
     702             : static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
     703             :                                         bool *is_free,
     704             :                                         bool *was_free,
     705             :                                         TALLOC_CTX *mem_ctx,
     706             :                                         struct smbXsrv_session_global0 **_g,
     707             :                                         uint32_t *pseqnum);
     708             : 
     709       32257 : static NTSTATUS smbXsrv_session_global_allocate(struct db_context *db,
     710             :                                         TALLOC_CTX *mem_ctx,
     711             :                                         struct smbXsrv_session_global0 **_global)
     712             : {
     713         760 :         uint32_t i;
     714       32257 :         struct smbXsrv_session_global0 *global = NULL;
     715       32257 :         uint32_t last_free = 0;
     716       32257 :         const uint32_t min_tries = 3;
     717             : 
     718       32257 :         *_global = NULL;
     719             : 
     720       32257 :         global = talloc_zero(mem_ctx, struct smbXsrv_session_global0);
     721       32257 :         if (global == NULL) {
     722           0 :                 return NT_STATUS_NO_MEMORY;
     723             :         }
     724       32257 :         talloc_set_destructor(global, smbXsrv_session_global_destructor);
     725             : 
     726             :         /*
     727             :          * Here we just randomly try the whole 32-bit space
     728             :          *
     729             :          * We use just 32-bit, because we want to reuse the
     730             :          * ID for SRVSVC.
     731             :          */
     732       33017 :         for (i = 0; i < UINT32_MAX; i++) {
     733       32257 :                 bool is_free = false;
     734       32257 :                 bool was_free = false;
     735         760 :                 uint32_t id;
     736             : 
     737       32257 :                 if (i >= min_tries && last_free != 0) {
     738           0 :                         id = last_free;
     739             :                 } else {
     740       32257 :                         id = generate_random();
     741             :                 }
     742       32257 :                 if (id == 0) {
     743           0 :                         id++;
     744             :                 }
     745       32257 :                 if (id == UINT32_MAX) {
     746           0 :                         id--;
     747             :                 }
     748             : 
     749       32257 :                 global->db_rec = smbXsrv_session_global_fetch_locked(db, id,
     750             :                                                                      mem_ctx);
     751       32257 :                 if (global->db_rec == NULL) {
     752           0 :                         talloc_free(global);
     753           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     754             :                 }
     755             : 
     756       32257 :                 smbXsrv_session_global_verify_record(global->db_rec,
     757             :                                                      &is_free,
     758             :                                                      &was_free,
     759             :                                                      NULL, NULL, NULL);
     760             : 
     761       32257 :                 if (!is_free) {
     762           0 :                         TALLOC_FREE(global->db_rec);
     763           0 :                         continue;
     764             :                 }
     765             : 
     766       32257 :                 if (!was_free && i < min_tries) {
     767             :                         /*
     768             :                          * The session_id is free now,
     769             :                          * but was not free before.
     770             :                          *
     771             :                          * This happens if a smbd crashed
     772             :                          * and did not cleanup the record.
     773             :                          *
     774             :                          * If this is one of our first tries,
     775             :                          * then we try to find a real free one.
     776             :                          */
     777           0 :                         if (last_free == 0) {
     778           0 :                                 last_free = id;
     779             :                         }
     780           0 :                         TALLOC_FREE(global->db_rec);
     781           0 :                         continue;
     782             :                 }
     783             : 
     784       32257 :                 global->session_global_id = id;
     785             : 
     786       32257 :                 *_global = global;
     787       32257 :                 return NT_STATUS_OK;
     788             :         }
     789             : 
     790             :         /* should not be reached */
     791           0 :         talloc_free(global);
     792           0 :         return NT_STATUS_INTERNAL_ERROR;
     793             : }
     794             : 
     795       33582 : static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
     796             :                                         bool *is_free,
     797             :                                         bool *was_free,
     798             :                                         TALLOC_CTX *mem_ctx,
     799             :                                         struct smbXsrv_session_global0 **_g,
     800             :                                         uint32_t *pseqnum)
     801             : {
     802         973 :         TDB_DATA key;
     803         973 :         TDB_DATA val;
     804         973 :         DATA_BLOB blob;
     805         973 :         struct smbXsrv_session_globalB global_blob;
     806         973 :         enum ndr_err_code ndr_err;
     807       33582 :         struct smbXsrv_session_global0 *global = NULL;
     808         973 :         bool exists;
     809       33582 :         TALLOC_CTX *frame = talloc_stackframe();
     810             : 
     811       33582 :         *is_free = false;
     812             : 
     813       33582 :         if (was_free) {
     814       32257 :                 *was_free = false;
     815             :         }
     816       33582 :         if (_g) {
     817        1325 :                 *_g = NULL;
     818             :         }
     819       33582 :         if (pseqnum) {
     820         158 :                 *pseqnum = 0;
     821             :         }
     822             : 
     823       33582 :         key = dbwrap_record_get_key(db_rec);
     824             : 
     825       33582 :         val = dbwrap_record_get_value(db_rec);
     826       33582 :         if (val.dsize == 0) {
     827       32369 :                 TALLOC_FREE(frame);
     828       32369 :                 *is_free = true;
     829       32369 :                 if (was_free) {
     830       32257 :                         *was_free = true;
     831             :                 }
     832       32369 :                 return;
     833             :         }
     834             : 
     835        1213 :         blob = data_blob_const(val.dptr, val.dsize);
     836             : 
     837        1213 :         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
     838             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
     839        1213 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     840           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     841           0 :                 DBG_WARNING("key '%s' ndr_pull_struct_blob - %s\n",
     842             :                             tdb_data_dbg(key),
     843             :                             nt_errstr(status));
     844           0 :                 TALLOC_FREE(frame);
     845           0 :                 *is_free = true;
     846           0 :                 if (was_free) {
     847           0 :                         *was_free = true;
     848             :                 }
     849           0 :                 return;
     850             :         }
     851             : 
     852        1213 :         DBG_DEBUG("smbXsrv_session_global_verify_record\n");
     853        1213 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     854           0 :                 NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
     855             :         }
     856             : 
     857        1213 :         if (global_blob.version != SMBXSRV_VERSION_0) {
     858           0 :                 DBG_ERR("key '%s' use unsupported version %u\n",
     859             :                         tdb_data_dbg(key),
     860             :                         global_blob.version);
     861           0 :                 NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
     862           0 :                 TALLOC_FREE(frame);
     863           0 :                 *is_free = true;
     864           0 :                 if (was_free) {
     865           0 :                         *was_free = true;
     866             :                 }
     867           0 :                 return;
     868             :         }
     869             : 
     870        1213 :         global = global_blob.info.info0;
     871             : 
     872             : #define __BLOB_KEEP_SECRET(__blob) do { \
     873             :         if ((__blob).length != 0) { \
     874             :                 talloc_keep_secret((__blob).data); \
     875             :         } \
     876             : } while(0)
     877             :         {
     878         209 :                 uint32_t i;
     879        1213 :                 __BLOB_KEEP_SECRET(global->application_key_blob);
     880        1213 :                 __BLOB_KEEP_SECRET(global->signing_key_blob);
     881        1213 :                 __BLOB_KEEP_SECRET(global->encryption_key_blob);
     882        1213 :                 __BLOB_KEEP_SECRET(global->decryption_key_blob);
     883        2434 :                 for (i = 0; i < global->num_channels; i++) {
     884        1221 :                         __BLOB_KEEP_SECRET(global->channels[i].signing_key_blob);
     885             :                 }
     886             :         }
     887             : #undef __BLOB_KEEP_SECRET
     888             : 
     889        1213 :         exists = serverid_exists(&global->channels[0].server_id);
     890        1213 :         if (!exists) {
     891           0 :                 struct server_id_buf idbuf;
     892           0 :                 DBG_NOTICE("key '%s' server_id %s does not exist.\n",
     893             :                            tdb_data_dbg(key),
     894             :                            server_id_str_buf(global->channels[0].server_id,
     895             :                                              &idbuf));
     896           0 :                 if (DEBUGLVL(DBGLVL_NOTICE)) {
     897           0 :                         NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
     898             :                 }
     899           0 :                 TALLOC_FREE(frame);
     900           0 :                 dbwrap_record_delete(db_rec);
     901           0 :                 *is_free = true;
     902           0 :                 return;
     903             :         }
     904             : 
     905        1213 :         if (_g) {
     906        1213 :                 *_g = talloc_move(mem_ctx, &global);
     907             :         }
     908        1213 :         if (pseqnum) {
     909          56 :                 *pseqnum = global_blob.seqnum;
     910             :         }
     911        1213 :         TALLOC_FREE(frame);
     912             : }
     913             : 
     914      163620 : static NTSTATUS smbXsrv_session_global_store(struct smbXsrv_session_global0 *global)
     915             : {
     916        3327 :         struct smbXsrv_session_globalB global_blob;
     917      163620 :         DATA_BLOB blob = data_blob_null;
     918        3327 :         TDB_DATA key;
     919        3327 :         TDB_DATA val;
     920        3327 :         NTSTATUS status;
     921        3327 :         enum ndr_err_code ndr_err;
     922             : 
     923             :         /*
     924             :          * TODO: if we use other versions than '0'
     925             :          * we would add glue code here, that would be able to
     926             :          * store the information in the old format.
     927             :          */
     928             : 
     929      163620 :         key = dbwrap_record_get_key(global->db_rec);
     930      163620 :         val = dbwrap_record_get_value(global->db_rec);
     931             : 
     932      166947 :         global_blob = (struct smbXsrv_session_globalB){
     933      163620 :                 .version = smbXsrv_version_global_current(),
     934             :                 .info.info0 = global,
     935             :         };
     936             : 
     937      163620 :         if (val.dsize >= 8) {
     938      131363 :                 global_blob.seqnum = IVAL(val.dptr, 4);
     939             :         }
     940      163620 :         global_blob.seqnum += 1;
     941             : 
     942      163620 :         ndr_err = ndr_push_struct_blob(
     943             :                 &blob,
     944             :                 talloc_tos(),
     945             :                 &global_blob,
     946             :                 (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_globalB);
     947      163620 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     948           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     949           0 :                 DBG_WARNING("key '%s' ndr_push - %s\n",
     950             :                             tdb_data_dbg(key),
     951             :                             nt_errstr(status));
     952           0 :                 TALLOC_FREE(global->db_rec);
     953           0 :                 return status;
     954             :         }
     955             : 
     956      163620 :         val = make_tdb_data(blob.data, blob.length);
     957      163620 :         status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
     958      163620 :         TALLOC_FREE(blob.data);
     959      163620 :         if (!NT_STATUS_IS_OK(status)) {
     960           0 :                 DBG_WARNING("key '%s' store - %s\n",
     961             :                             tdb_data_dbg(key),
     962             :                             nt_errstr(status));
     963           0 :                 TALLOC_FREE(global->db_rec);
     964           0 :                 return status;
     965             :         }
     966             : 
     967      163620 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     968           0 :                 DBG_DEBUG("key '%s' stored\n", tdb_data_dbg(key));
     969           0 :                 NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
     970             :         }
     971             : 
     972      163620 :         TALLOC_FREE(global->db_rec);
     973             : 
     974      163620 :         return NT_STATUS_OK;
     975             : }
     976             : 
     977             : struct smb2srv_session_close_previous_state {
     978             :         struct tevent_context *ev;
     979             :         struct smbXsrv_connection *connection;
     980             :         struct dom_sid *current_sid;
     981             :         uint64_t previous_session_id;
     982             :         uint64_t current_session_id;
     983             :         struct db_record *db_rec;
     984             :         uint64_t watch_instance;
     985             :         uint32_t last_seqnum;
     986             : };
     987             : 
     988         204 : static void smb2srv_session_close_previous_cleanup(struct tevent_req *req,
     989             :                                                    enum tevent_req_state req_state)
     990             : {
     991           8 :         struct smb2srv_session_close_previous_state *state =
     992         204 :                 tevent_req_data(req,
     993             :                 struct smb2srv_session_close_previous_state);
     994             : 
     995         204 :         if (state->db_rec != NULL) {
     996         102 :                 dbwrap_watched_watch_remove_instance(state->db_rec,
     997             :                                                      state->watch_instance);
     998         102 :                 state->watch_instance = 0;
     999         102 :                 TALLOC_FREE(state->db_rec);
    1000             :         }
    1001         204 : }
    1002             : 
    1003             : static void smb2srv_session_close_previous_check(struct tevent_req *req);
    1004             : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq);
    1005             : 
    1006         102 : struct tevent_req *smb2srv_session_close_previous_send(TALLOC_CTX *mem_ctx,
    1007             :                                         struct tevent_context *ev,
    1008             :                                         struct smbXsrv_connection *conn,
    1009             :                                         struct auth_session_info *session_info,
    1010             :                                         uint64_t previous_session_id,
    1011             :                                         uint64_t current_session_id)
    1012             : {
    1013           4 :         struct tevent_req *req;
    1014           4 :         struct smb2srv_session_close_previous_state *state;
    1015         102 :         uint32_t global_id = previous_session_id & UINT32_MAX;
    1016         102 :         uint64_t global_zeros = previous_session_id & 0xFFFFFFFF00000000LLU;
    1017         102 :         struct smbXsrv_session_table *table = conn->client->session_table;
    1018         102 :         struct security_token *current_token = NULL;
    1019             : 
    1020         102 :         req = tevent_req_create(mem_ctx, &state,
    1021             :                                 struct smb2srv_session_close_previous_state);
    1022         102 :         if (req == NULL) {
    1023           0 :                 return NULL;
    1024             :         }
    1025         102 :         state->ev = ev;
    1026         102 :         state->connection = conn;
    1027         102 :         state->previous_session_id = previous_session_id;
    1028         102 :         state->current_session_id = current_session_id;
    1029             : 
    1030         102 :         tevent_req_set_cleanup_fn(req, smb2srv_session_close_previous_cleanup);
    1031             : 
    1032         102 :         if (global_zeros != 0) {
    1033           0 :                 tevent_req_done(req);
    1034           0 :                 return tevent_req_post(req, ev);
    1035             :         }
    1036             : 
    1037         102 :         if (session_info == NULL) {
    1038           0 :                 tevent_req_done(req);
    1039           0 :                 return tevent_req_post(req, ev);
    1040             :         }
    1041         102 :         current_token = session_info->security_token;
    1042             : 
    1043         102 :         if (current_token->num_sids > PRIMARY_USER_SID_INDEX) {
    1044         102 :                 state->current_sid = &current_token->sids[PRIMARY_USER_SID_INDEX];
    1045             :         }
    1046             : 
    1047         102 :         if (state->current_sid == NULL) {
    1048           0 :                 tevent_req_done(req);
    1049           0 :                 return tevent_req_post(req, ev);
    1050             :         }
    1051             : 
    1052         102 :         if (!security_token_has_nt_authenticated_users(current_token)) {
    1053             :                 /* TODO */
    1054           0 :                 tevent_req_done(req);
    1055           0 :                 return tevent_req_post(req, ev);
    1056             :         }
    1057             : 
    1058         102 :         state->db_rec = smbXsrv_session_global_fetch_locked(
    1059             :                                                         table->global.db_ctx,
    1060             :                                                         global_id,
    1061             :                                                         state /* TALLOC_CTX */);
    1062         102 :         if (state->db_rec == NULL) {
    1063           0 :                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
    1064           0 :                 return tevent_req_post(req, ev);
    1065             :         }
    1066             : 
    1067         102 :         smb2srv_session_close_previous_check(req);
    1068         102 :         if (!tevent_req_is_in_progress(req)) {
    1069          46 :                 return tevent_req_post(req, ev);
    1070             :         }
    1071             : 
    1072          52 :         return req;
    1073             : }
    1074             : 
    1075         158 : static void smb2srv_session_close_previous_check(struct tevent_req *req)
    1076             : {
    1077           8 :         struct smb2srv_session_close_previous_state *state =
    1078         158 :                 tevent_req_data(req,
    1079             :                 struct smb2srv_session_close_previous_state);
    1080         158 :         struct smbXsrv_connection *conn = state->connection;
    1081           8 :         DATA_BLOB blob;
    1082         158 :         struct security_token *previous_token = NULL;
    1083         158 :         struct smbXsrv_session_global0 *global = NULL;
    1084           8 :         enum ndr_err_code ndr_err;
    1085           8 :         struct smbXsrv_session_close0 close_info0;
    1086           8 :         struct smbXsrv_session_closeB close_blob;
    1087         158 :         struct tevent_req *subreq = NULL;
    1088           8 :         NTSTATUS status;
    1089         158 :         bool is_free = false;
    1090         158 :         uint32_t seqnum = 0;
    1091             : 
    1092         158 :         smbXsrv_session_global_verify_record(state->db_rec,
    1093             :                                              &is_free,
    1094             :                                              NULL,
    1095             :                                              state,
    1096             :                                              &global,
    1097             :                                              &seqnum);
    1098             : 
    1099         158 :         if (is_free) {
    1100         102 :                 tevent_req_done(req);
    1101         102 :                 return;
    1102             :         }
    1103             : 
    1104          56 :         if (global->auth_session_info == NULL) {
    1105           0 :                 tevent_req_done(req);
    1106           0 :                 return;
    1107             :         }
    1108             : 
    1109          56 :         previous_token = global->auth_session_info->security_token;
    1110             : 
    1111          56 :         if (!security_token_is_sid(previous_token, state->current_sid)) {
    1112           0 :                 tevent_req_done(req);
    1113           0 :                 return;
    1114             :         }
    1115             : 
    1116             :         /*
    1117             :          * If the record changed, but we are not happy with the change yet,
    1118             :          * we better remove ourself from the waiter list
    1119             :          * (most likely the first position)
    1120             :          * and re-add us at the end of the list.
    1121             :          *
    1122             :          * This gives other waiters a change
    1123             :          * to make progress.
    1124             :          *
    1125             :          * Otherwise we'll keep our waiter instance alive,
    1126             :          * keep waiting (most likely at first position).
    1127             :          * It means the order of watchers stays fair.
    1128             :          */
    1129          56 :         if (state->last_seqnum != seqnum) {
    1130          56 :                 state->last_seqnum = seqnum;
    1131          56 :                 dbwrap_watched_watch_remove_instance(state->db_rec,
    1132             :                                                      state->watch_instance);
    1133          56 :                 state->watch_instance =
    1134          56 :                         dbwrap_watched_watch_add_instance(state->db_rec);
    1135             :         }
    1136             : 
    1137          60 :         subreq = dbwrap_watched_watch_send(state, state->ev, state->db_rec,
    1138             :                                            state->watch_instance,
    1139          56 :                                            (struct server_id){0});
    1140          56 :         if (tevent_req_nomem(subreq, req)) {
    1141           0 :                 return;
    1142             :         }
    1143          56 :         tevent_req_set_callback(subreq,
    1144             :                                 smb2srv_session_close_previous_modified,
    1145             :                                 req);
    1146             : 
    1147          56 :         close_info0 = (struct smbXsrv_session_close0){
    1148          56 :                 .old_session_global_id = global->session_global_id,
    1149          56 :                 .old_session_wire_id = global->session_wire_id,
    1150          56 :                 .old_creation_time = global->creation_time,
    1151          56 :                 .new_session_wire_id = state->current_session_id,
    1152             :         };
    1153             : 
    1154          60 :         close_blob = (struct smbXsrv_session_closeB){
    1155          56 :                 .version = smbXsrv_version_global_current(),
    1156             :                 .info.info0 = &close_info0,
    1157             :         };
    1158             : 
    1159          56 :         ndr_err = ndr_push_struct_blob(&blob, state, &close_blob,
    1160             :                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_closeB);
    1161          56 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1162           0 :                 status = ndr_map_error2ntstatus(ndr_err);
    1163           0 :                 DBG_WARNING("old_session[%" PRIu64 "] "
    1164             :                             "new_session[%" PRIu64 "] ndr_push - %s\n",
    1165             :                             close_info0.old_session_wire_id,
    1166             :                             close_info0.new_session_wire_id,
    1167             :                             nt_errstr(status));
    1168           0 :                 tevent_req_nterror(req, status);
    1169           0 :                 return;
    1170             :         }
    1171             : 
    1172          56 :         status = messaging_send(conn->client->msg_ctx,
    1173          56 :                                 global->channels[0].server_id,
    1174             :                                 MSG_SMBXSRV_SESSION_CLOSE, &blob);
    1175          56 :         TALLOC_FREE(global);
    1176          56 :         if (tevent_req_nterror(req, status)) {
    1177           0 :                 return;
    1178             :         }
    1179             : 
    1180          56 :         TALLOC_FREE(state->db_rec);
    1181          52 :         return;
    1182             : }
    1183             : 
    1184          56 : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq)
    1185             : {
    1186           4 :         struct tevent_req *req =
    1187          56 :                 tevent_req_callback_data(subreq,
    1188             :                 struct tevent_req);
    1189           4 :         struct smb2srv_session_close_previous_state *state =
    1190          56 :                 tevent_req_data(req,
    1191             :                 struct smb2srv_session_close_previous_state);
    1192           4 :         uint32_t global_id;
    1193           4 :         NTSTATUS status;
    1194          56 :         uint64_t instance = 0;
    1195             : 
    1196          56 :         status = dbwrap_watched_watch_recv(subreq, &instance, NULL, NULL);
    1197          56 :         TALLOC_FREE(subreq);
    1198          56 :         if (tevent_req_nterror(req, status)) {
    1199           0 :                 return;
    1200             :         }
    1201             : 
    1202          56 :         state->watch_instance = instance;
    1203             : 
    1204          56 :         global_id = state->previous_session_id & UINT32_MAX;
    1205             : 
    1206         112 :         state->db_rec = smbXsrv_session_global_fetch_locked(
    1207          56 :                 state->connection->client->session_table->global.db_ctx,
    1208             :                 global_id, state /* TALLOC_CTX */);
    1209          56 :         if (state->db_rec == NULL) {
    1210           0 :                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
    1211           0 :                 return;
    1212             :         }
    1213             : 
    1214          56 :         smb2srv_session_close_previous_check(req);
    1215             : }
    1216             : 
    1217         102 : NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
    1218             : {
    1219           4 :         NTSTATUS status;
    1220             : 
    1221         102 :         if (tevent_req_is_nterror(req, &status)) {
    1222           0 :                 tevent_req_received(req);
    1223           0 :                 return status;
    1224             :         }
    1225             : 
    1226         102 :         tevent_req_received(req);
    1227         102 :         return NT_STATUS_OK;
    1228             : }
    1229             : 
    1230       61154 : static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session)
    1231             : {
    1232        1499 :         NTSTATUS status;
    1233       61154 :         struct smbXsrv_connection *xconn = NULL;
    1234             : 
    1235       61154 :         if (session->client != NULL) {
    1236       31974 :                 xconn = session->client->connections;
    1237             :         }
    1238             : 
    1239       93180 :         for (; xconn != NULL; xconn = xconn->next) {
    1240         750 :                 struct smbd_smb2_request *preq;
    1241             : 
    1242       32082 :                 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
    1243          56 :                         if (preq->session != session) {
    1244           0 :                                 continue;
    1245             :                         }
    1246             : 
    1247          56 :                         preq->session = NULL;
    1248             :                         /*
    1249             :                          * If we no longer have a session we can't
    1250             :                          * sign or encrypt replies.
    1251             :                          */
    1252          56 :                         preq->do_signing = false;
    1253          56 :                         preq->do_encryption = false;
    1254          56 :                         preq->preauth = NULL;
    1255             :                 }
    1256             :         }
    1257             : 
    1258       61154 :         status = smbXsrv_session_logoff(session);
    1259       61154 :         return status;
    1260             : }
    1261             : 
    1262       32243 : static int smbXsrv_session_destructor(struct smbXsrv_session *session)
    1263             : {
    1264         760 :         NTSTATUS status;
    1265             : 
    1266       32243 :         DBG_DEBUG("destructing session(%" PRIu64 ")\n",
    1267             :                   session->global->session_wire_id);
    1268             : 
    1269       32243 :         status = smbXsrv_session_clear_and_logoff(session);
    1270       32243 :         if (!NT_STATUS_IS_OK(status)) {
    1271           0 :                 DBG_ERR("smbXsrv_session_logoff() failed: %s\n",
    1272             :                         nt_errstr(status));
    1273             :         }
    1274             : 
    1275       32243 :         TALLOC_FREE(session->global);
    1276             : 
    1277       32243 :         return 0;
    1278             : }
    1279             : 
    1280       32257 : NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
    1281             :                                 NTTIME now,
    1282             :                                 struct smbXsrv_session **_session)
    1283             : {
    1284       32257 :         struct smbXsrv_session_table *table = conn->client->session_table;
    1285       32257 :         struct db_record *local_rec = NULL;
    1286       32257 :         struct smbXsrv_session *session = NULL;
    1287       32257 :         void *ptr = NULL;
    1288         760 :         TDB_DATA val;
    1289       32257 :         struct smbXsrv_session_global0 *global = NULL;
    1290       32257 :         struct smbXsrv_channel_global0 *channel = NULL;
    1291         760 :         NTSTATUS status;
    1292             : 
    1293       32257 :         if (table->local.num_sessions >= table->local.max_sessions) {
    1294           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
    1295             :         }
    1296             : 
    1297       32257 :         session = talloc_zero(table, struct smbXsrv_session);
    1298       32257 :         if (session == NULL) {
    1299           0 :                 return NT_STATUS_NO_MEMORY;
    1300             :         }
    1301       32257 :         session->table = table;
    1302       32257 :         session->idle_time = now;
    1303       32257 :         session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
    1304       32257 :         session->client = conn->client;
    1305       32257 :         session->homes_snum = -1;
    1306             : 
    1307       32257 :         status = smbXsrv_session_global_allocate(table->global.db_ctx,
    1308             :                                                  session,
    1309             :                                                  &global);
    1310       32257 :         if (!NT_STATUS_IS_OK(status)) {
    1311           0 :                 TALLOC_FREE(session);
    1312           0 :                 return status;
    1313             :         }
    1314       32257 :         session->global = global;
    1315             : 
    1316       32257 :         if (conn->protocol >= PROTOCOL_SMB2_02) {
    1317       25211 :                 uint64_t id = global->session_global_id;
    1318             : 
    1319       25211 :                 global->connection_dialect = conn->smb2.server.dialect;
    1320       25211 :                 global->client_guid = conn->smb2.client.guid;
    1321             : 
    1322       25211 :                 global->session_wire_id = id;
    1323             : 
    1324       25211 :                 status = smb2srv_tcon_table_init(session);
    1325       25211 :                 if (!NT_STATUS_IS_OK(status)) {
    1326           0 :                         TALLOC_FREE(session);
    1327           0 :                         return status;
    1328             :                 }
    1329             : 
    1330       25211 :                 session->local_id = global->session_global_id;
    1331             : 
    1332       25211 :                 local_rec = smbXsrv_session_local_fetch_locked(
    1333             :                                                 table->local.db_ctx,
    1334             :                                                 session->local_id,
    1335             :                                                 session /* TALLOC_CTX */);
    1336       25211 :                 if (local_rec == NULL) {
    1337           0 :                         TALLOC_FREE(session);
    1338           0 :                         return NT_STATUS_NO_MEMORY;
    1339             :                 }
    1340             : 
    1341       25211 :                 val = dbwrap_record_get_value(local_rec);
    1342       25211 :                 if (val.dsize != 0) {
    1343           0 :                         TALLOC_FREE(session);
    1344           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1345             :                 }
    1346             :         } else {
    1347             : 
    1348        7046 :                 status = smb1srv_session_local_allocate_id(table->local.db_ctx,
    1349             :                                                         table->local.lowest_id,
    1350             :                                                         table->local.highest_id,
    1351             :                                                         session,
    1352             :                                                         &local_rec,
    1353             :                                                         &session->local_id);
    1354        7046 :                 if (!NT_STATUS_IS_OK(status)) {
    1355           0 :                         TALLOC_FREE(session);
    1356           0 :                         return status;
    1357             :                 }
    1358             : 
    1359        7046 :                 global->session_wire_id = session->local_id;
    1360             :         }
    1361             : 
    1362       32257 :         global->creation_time = now;
    1363       32257 :         global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
    1364             : 
    1365       32257 :         status = smbXsrv_session_add_channel(session, conn, now, &channel);
    1366       32257 :         if (!NT_STATUS_IS_OK(status)) {
    1367           0 :                 TALLOC_FREE(session);
    1368           0 :                 return status;
    1369             :         }
    1370             : 
    1371       32257 :         ptr = session;
    1372       32257 :         val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
    1373       32257 :         status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
    1374       32257 :         TALLOC_FREE(local_rec);
    1375       32257 :         if (!NT_STATUS_IS_OK(status)) {
    1376           0 :                 TALLOC_FREE(session);
    1377           0 :                 return status;
    1378             :         }
    1379       32257 :         table->local.num_sessions += 1;
    1380             : 
    1381       32257 :         talloc_set_destructor(session, smbXsrv_session_destructor);
    1382             : 
    1383       32257 :         status = smbXsrv_session_global_store(global);
    1384       32257 :         if (!NT_STATUS_IS_OK(status)) {
    1385           0 :                 DBG_ERR("global_id (0x%08x) store failed - %s\n",
    1386             :                         session->global->session_global_id,
    1387             :                         nt_errstr(status));
    1388           0 :                 TALLOC_FREE(session);
    1389           0 :                 return status;
    1390             :         }
    1391             : 
    1392       32257 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
    1393           0 :                 struct smbXsrv_sessionB session_blob = {
    1394             :                         .version = SMBXSRV_VERSION_0,
    1395             :                         .info.info0 = session,
    1396             :                 };
    1397             : 
    1398           0 :                 DBG_DEBUG("global_id (0x%08x) stored\n",
    1399             :                           session->global->session_global_id);
    1400           0 :                 NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
    1401             :         }
    1402             : 
    1403       32257 :         *_session = session;
    1404       32257 :         return NT_STATUS_OK;
    1405             : }
    1406             : 
    1407       33167 : NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
    1408             :                                      struct smbXsrv_connection *conn,
    1409             :                                      NTTIME now,
    1410             :                                      struct smbXsrv_channel_global0 **_c)
    1411             : {
    1412       33167 :         struct smbXsrv_session_global0 *global = session->global;
    1413       33167 :         struct smbXsrv_channel_global0 *c = NULL;
    1414             : 
    1415       33167 :         if (global->num_channels > 31) {
    1416             :                 /*
    1417             :                  * Windows allow up to 32 channels
    1418             :                  */
    1419           4 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
    1420             :         }
    1421             : 
    1422       33163 :         c = talloc_realloc(global,
    1423             :                            global->channels,
    1424             :                            struct smbXsrv_channel_global0,
    1425             :                            global->num_channels + 1);
    1426       33163 :         if (c == NULL) {
    1427           0 :                 return NT_STATUS_NO_MEMORY;
    1428             :         }
    1429       33163 :         global->channels = c;
    1430             : 
    1431       33163 :         c = &global->channels[global->num_channels];
    1432             : 
    1433       33945 :         *c = (struct smbXsrv_channel_global0){
    1434       33163 :                 .server_id = messaging_server_id(conn->client->msg_ctx),
    1435       33163 :                 .channel_id = conn->channel_id,
    1436             :                 .creation_time = now,
    1437             :                 .connection = conn,
    1438             :         };
    1439             : 
    1440       66326 :         c->local_address = tsocket_address_string(conn->local_address,
    1441       33163 :                                                   global->channels);
    1442       33163 :         if (c->local_address == NULL) {
    1443           0 :                 return NT_STATUS_NO_MEMORY;
    1444             :         }
    1445       66326 :         c->remote_address = tsocket_address_string(conn->remote_address,
    1446       33163 :                                                    global->channels);
    1447       33163 :         if (c->remote_address == NULL) {
    1448           0 :                 return NT_STATUS_NO_MEMORY;
    1449             :         }
    1450       33163 :         c->remote_name = talloc_strdup(global->channels,
    1451             :                                        conn->remote_hostname);
    1452       33163 :         if (c->remote_name == NULL) {
    1453           0 :                 return NT_STATUS_NO_MEMORY;
    1454             :         }
    1455             : 
    1456       33163 :         global->num_channels += 1;
    1457             : 
    1458       33163 :         *_c = c;
    1459       33163 :         return NT_STATUS_OK;
    1460             : }
    1461             : 
    1462      131363 : NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session)
    1463             : {
    1464      131363 :         struct smbXsrv_session_table *table = session->table;
    1465        2567 :         NTSTATUS status;
    1466             : 
    1467      131363 :         if (session->global->db_rec != NULL) {
    1468           0 :                 DBG_ERR("smbXsrv_session_update(0x%08x): "
    1469             :                           "Called with db_rec != NULL'\n",
    1470             :                           session->global->session_global_id);
    1471           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1472             :         }
    1473             : 
    1474      131363 :         if (table == NULL) {
    1475           0 :                 DBG_ERR("smbXsrv_session_update(0x%08x): "
    1476             :                           "Called with table == NULL'\n",
    1477             :                           session->global->session_global_id);
    1478           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1479             :         }
    1480             : 
    1481      260159 :         session->global->db_rec = smbXsrv_session_global_fetch_locked(
    1482             :                                         table->global.db_ctx,
    1483      128796 :                                         session->global->session_global_id,
    1484      128796 :                                         session->global /* TALLOC_CTX */);
    1485      131363 :         if (session->global->db_rec == NULL) {
    1486           0 :                 return NT_STATUS_INTERNAL_DB_ERROR;
    1487             :         }
    1488             : 
    1489      131363 :         status = smbXsrv_session_global_store(session->global);
    1490      131363 :         if (!NT_STATUS_IS_OK(status)) {
    1491           0 :                 DBG_ERR("global_id (0x%08x) store failed - %s\n",
    1492             :                         session->global->session_global_id,
    1493             :                         nt_errstr(status));
    1494           0 :                 return status;
    1495             :         }
    1496             : 
    1497      131363 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
    1498           0 :                 struct smbXsrv_sessionB session_blob = {
    1499             :                         .version = SMBXSRV_VERSION_0,
    1500             :                         .info.info0 = session,
    1501             :                 };
    1502             : 
    1503           0 :                 DBG_DEBUG("global_id (0x%08x) stored\n",
    1504             :                           session->global->session_global_id);
    1505           0 :                 NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
    1506             :         }
    1507             : 
    1508      131363 :         return NT_STATUS_OK;
    1509             : }
    1510             : 
    1511     3552221 : NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
    1512             :                                       const struct smbXsrv_connection *conn,
    1513             :                                       struct smbXsrv_channel_global0 **_c)
    1514             : {
    1515       38633 :         uint32_t i;
    1516             : 
    1517     3631595 :         for (i=0; i < session->global->num_channels; i++) {
    1518     3625519 :                 struct smbXsrv_channel_global0 *c = &session->global->channels[i];
    1519             : 
    1520     3625519 :                 if (c->channel_id != conn->channel_id) {
    1521       79374 :                         continue;
    1522             :                 }
    1523             : 
    1524     3546145 :                 if (c->connection != conn) {
    1525           0 :                         continue;
    1526             :                 }
    1527             : 
    1528     3546145 :                 *_c = c;
    1529     3546145 :                 return NT_STATUS_OK;
    1530             :         }
    1531             : 
    1532        6076 :         return NT_STATUS_USER_SESSION_DELETED;
    1533             : }
    1534             : 
    1535       93681 : NTSTATUS smbXsrv_session_find_auth(const struct smbXsrv_session *session,
    1536             :                                    const struct smbXsrv_connection *conn,
    1537             :                                    NTTIME now,
    1538             :                                    struct smbXsrv_session_auth0 **_a)
    1539             : {
    1540        1980 :         struct smbXsrv_session_auth0 *a;
    1541             : 
    1542       93681 :         for (a = session->pending_auth; a != NULL; a = a->next) {
    1543       25121 :                 if (a->channel_id != conn->channel_id) {
    1544           0 :                         continue;
    1545             :                 }
    1546             : 
    1547       25121 :                 if (a->connection == conn) {
    1548       25121 :                         if (now != 0) {
    1549       25103 :                                 a->idle_time = now;
    1550             :                         }
    1551       25121 :                         *_a = a;
    1552       25121 :                         return NT_STATUS_OK;
    1553             :                 }
    1554             :         }
    1555             : 
    1556       68560 :         return NT_STATUS_USER_SESSION_DELETED;
    1557             : }
    1558             : 
    1559       33282 : static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0 *a)
    1560             : {
    1561       33282 :         if (a->session == NULL) {
    1562          14 :                 return 0;
    1563             :         }
    1564             : 
    1565       33264 :         DLIST_REMOVE(a->session->pending_auth, a);
    1566       33264 :         a->session = NULL;
    1567       33264 :         return 0;
    1568             : }
    1569             : 
    1570       33276 : NTSTATUS smbXsrv_session_create_auth(struct smbXsrv_session *session,
    1571             :                                      struct smbXsrv_connection *conn,
    1572             :                                      NTTIME now,
    1573             :                                      uint8_t in_flags,
    1574             :                                      uint8_t in_security_mode,
    1575             :                                      struct smbXsrv_session_auth0 **_a)
    1576             : {
    1577         811 :         struct smbXsrv_session_auth0 *a;
    1578         811 :         NTSTATUS status;
    1579             : 
    1580       33276 :         status = smbXsrv_session_find_auth(session, conn, 0, &a);
    1581       33276 :         if (NT_STATUS_IS_OK(status)) {
    1582           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1583             :         }
    1584             : 
    1585       33276 :         a = talloc(session, struct smbXsrv_session_auth0);
    1586       33276 :         if (a == NULL) {
    1587           0 :                 return NT_STATUS_NO_MEMORY;
    1588             :         }
    1589             : 
    1590       33276 :         *a = (struct smbXsrv_session_auth0){
    1591             :                 .session = session,
    1592             :                 .connection = conn,
    1593             :                 .in_flags = in_flags,
    1594             :                 .in_security_mode = in_security_mode,
    1595             :                 .creation_time = now,
    1596             :                 .idle_time = now,
    1597       33276 :                 .channel_id = conn->channel_id,
    1598             :         };
    1599             : 
    1600       33276 :         if (conn->protocol >= PROTOCOL_SMB3_11) {
    1601       23718 :                 a->preauth = talloc(a, struct smbXsrv_preauth);
    1602       23718 :                 if (a->preauth == NULL) {
    1603           0 :                         TALLOC_FREE(session);
    1604           0 :                         return NT_STATUS_NO_MEMORY;
    1605             :                 }
    1606       23718 :                 *a->preauth = conn->smb2.preauth;
    1607             :         }
    1608             : 
    1609       33276 :         talloc_set_destructor(a, smbXsrv_session_auth0_destructor);
    1610       33276 :         DLIST_ADD_END(session->pending_auth, a);
    1611             : 
    1612       33276 :         *_a = a;
    1613       33276 :         return NT_STATUS_OK;
    1614             : }
    1615             : 
    1616             : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq);
    1617             : 
    1618        2026 : NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session,
    1619             :                                         struct smbXsrv_connection *xconn)
    1620             : {
    1621        2026 :         struct smbXsrv_session_auth0 *a = NULL;
    1622        2026 :         struct smbXsrv_channel_global0 *c = NULL;
    1623         210 :         NTSTATUS status;
    1624        2026 :         bool need_update = false;
    1625             : 
    1626        2026 :         status = smbXsrv_session_find_auth(session, xconn, 0, &a);
    1627        2026 :         if (!NT_STATUS_IS_OK(status)) {
    1628        2008 :                 a = NULL;
    1629             :         }
    1630        2026 :         status = smbXsrv_session_find_channel(session, xconn, &c);
    1631        2026 :         if (!NT_STATUS_IS_OK(status)) {
    1632        1086 :                 c = NULL;
    1633             :         }
    1634             : 
    1635        2026 :         if (a != NULL) {
    1636          18 :                 smbXsrv_session_auth0_destructor(a);
    1637          18 :                 a->connection = NULL;
    1638          18 :                 need_update = true;
    1639             :         }
    1640             : 
    1641        2026 :         if (c != NULL) {
    1642         940 :                 struct smbXsrv_session_global0 *global = session->global;
    1643          24 :                 ptrdiff_t n;
    1644             : 
    1645         940 :                 n = (c - global->channels);
    1646         940 :                 if (n >= global->num_channels || n < 0) {
    1647           0 :                         return NT_STATUS_INTERNAL_ERROR;
    1648             :                 }
    1649         940 :                 ARRAY_DEL_ELEMENT(global->channels, n, global->num_channels);
    1650         940 :                 global->num_channels--;
    1651         940 :                 if (global->num_channels == 0) {
    1652          44 :                         struct smbXsrv_client *client = session->client;
    1653          44 :                         struct tevent_queue *xconn_wait_queue =
    1654             :                                 xconn->transport.shutdown_wait_queue;
    1655          44 :                         struct tevent_req *subreq = NULL;
    1656             : 
    1657             :                         /*
    1658             :                          * Let the connection wait until the session is
    1659             :                          * destroyed.
    1660             :                          *
    1661             :                          * We don't set a callback, as we just want to block the
    1662             :                          * wait queue and the talloc_free() of the session will
    1663             :                          * remove the item from the wait queue in order
    1664             :                          * to remove allow the connection to disappear.
    1665             :                          */
    1666          44 :                         if (xconn_wait_queue != NULL) {
    1667          44 :                                 subreq = tevent_queue_wait_send(session,
    1668             :                                                                 client->raw_ev_ctx,
    1669             :                                                                 xconn_wait_queue);
    1670          44 :                                 if (subreq == NULL) {
    1671           0 :                                         status = NT_STATUS_NO_MEMORY;
    1672           0 :                                         DBG_ERR("tevent_queue_wait_send() "
    1673             :                                                 "session(%" PRIu64
    1674             :                                                 ") failed: %s\n",
    1675             :                                                 session->global
    1676             :                                                         ->session_wire_id,
    1677             :                                                 nt_errstr(status));
    1678           0 :                                         return status;
    1679             :                                 }
    1680             :                         }
    1681             : 
    1682             :                         /*
    1683             :                          * This is guaranteed to set
    1684             :                          * session->status = NT_STATUS_USER_SESSION_DELETED
    1685             :                          * even if NULL is returned.
    1686             :                          */
    1687          44 :                         subreq = smb2srv_session_shutdown_send(session,
    1688             :                                                                client->raw_ev_ctx,
    1689             :                                                                session,
    1690             :                                                                NULL);
    1691          44 :                         if (subreq == NULL) {
    1692           0 :                                 status = NT_STATUS_NO_MEMORY;
    1693           0 :                                 DBG_ERR("smb2srv_session_shutdown_send("
    1694             :                                         "%" PRIu64 " failed: %s\n",
    1695             :                                         session->global->session_wire_id,
    1696             :                                         nt_errstr(status));
    1697           0 :                                 return status;
    1698             :                         }
    1699          44 :                         tevent_req_set_callback(subreq,
    1700             :                                                 smbXsrv_session_remove_channel_done,
    1701             :                                                 session);
    1702             :                 }
    1703         916 :                 need_update = true;
    1704             :         }
    1705             : 
    1706        2002 :         if (!need_update) {
    1707        1086 :                 return NT_STATUS_OK;
    1708             :         }
    1709             : 
    1710         940 :         return smbXsrv_session_update(session);
    1711             : }
    1712             : 
    1713          44 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq)
    1714             : {
    1715           4 :         struct smbXsrv_session *session =
    1716          44 :                 tevent_req_callback_data(subreq,
    1717             :                 struct smbXsrv_session);
    1718           4 :         NTSTATUS status;
    1719             : 
    1720          44 :         status = smb2srv_session_shutdown_recv(subreq);
    1721          44 :         TALLOC_FREE(subreq);
    1722          44 :         if (!NT_STATUS_IS_OK(status)) {
    1723           0 :                 DBG_ERR("smb2srv_session_shutdown_recv(%" PRIu64
    1724             :                         ") failed: %s\n",
    1725             :                         session->global->session_wire_id,
    1726             :                         nt_errstr(status));
    1727             :         }
    1728             : 
    1729          44 :         status = smbXsrv_session_logoff(session);
    1730          44 :         if (!NT_STATUS_IS_OK(status)) {
    1731           0 :                 DBG_ERR("smbXsrv_session_logoff(%" PRIu64 ") failed: %s\n",
    1732             :                         session->global->session_wire_id,
    1733             :                         nt_errstr(status));
    1734             :         }
    1735             : 
    1736          44 :         TALLOC_FREE(session);
    1737          44 : }
    1738             : 
    1739             : struct smb2srv_session_shutdown_state {
    1740             :         struct tevent_queue *wait_queue;
    1741             : };
    1742             : 
    1743             : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
    1744             : 
    1745        2023 : struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
    1746             :                                         struct tevent_context *ev,
    1747             :                                         struct smbXsrv_session *session,
    1748             :                                         struct smbd_smb2_request *current_req)
    1749             : {
    1750          21 :         struct tevent_req *req;
    1751          21 :         struct smb2srv_session_shutdown_state *state;
    1752          21 :         struct tevent_req *subreq;
    1753        2023 :         struct smbXsrv_connection *xconn = NULL;
    1754        2023 :         size_t len = 0;
    1755             : 
    1756             :         /*
    1757             :          * Make sure that no new request will be able to use this session.
    1758             :          */
    1759        2023 :         session->status = NT_STATUS_USER_SESSION_DELETED;
    1760             : 
    1761        2023 :         req = tevent_req_create(mem_ctx, &state,
    1762             :                                 struct smb2srv_session_shutdown_state);
    1763        2023 :         if (req == NULL) {
    1764           0 :                 return NULL;
    1765             :         }
    1766             : 
    1767        2023 :         state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
    1768        2023 :         if (tevent_req_nomem(state->wait_queue, req)) {
    1769           0 :                 return tevent_req_post(req, ev);
    1770             :         }
    1771             : 
    1772        4136 :         for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
    1773          33 :                 struct smbd_smb2_request *preq;
    1774             : 
    1775        4076 :                 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
    1776        1963 :                         if (preq == current_req) {
    1777             :                                 /* Can't cancel current request. */
    1778        1925 :                                 continue;
    1779             :                         }
    1780          38 :                         if (preq->session != session) {
    1781             :                                 /* Request on different session. */
    1782          26 :                                 continue;
    1783             :                         }
    1784             : 
    1785          12 :                         if (preq->subreq != NULL) {
    1786          12 :                                 tevent_req_cancel(preq->subreq);
    1787             :                         }
    1788             : 
    1789             :                         /*
    1790             :                          * Now wait until the request is finished.
    1791             :                          *
    1792             :                          * We don't set a callback, as we just want to block the
    1793             :                          * wait queue and the talloc_free() of the request will
    1794             :                          * remove the item from the wait queue.
    1795             :                          */
    1796          12 :                         subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
    1797          12 :                         if (tevent_req_nomem(subreq, req)) {
    1798           0 :                                 return tevent_req_post(req, ev);
    1799             :                         }
    1800             :                 }
    1801             :         }
    1802             : 
    1803        2023 :         len = tevent_queue_length(state->wait_queue);
    1804        2023 :         if (len == 0) {
    1805        2011 :                 tevent_req_done(req);
    1806        2011 :                 return tevent_req_post(req, ev);
    1807             :         }
    1808             : 
    1809             :         /*
    1810             :          * Now we add our own waiter to the end of the queue,
    1811             :          * this way we get notified when all pending requests are finished
    1812             :          * and send to the socket.
    1813             :          */
    1814          12 :         subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
    1815          12 :         if (tevent_req_nomem(subreq, req)) {
    1816           0 :                 return tevent_req_post(req, ev);
    1817             :         }
    1818          12 :         tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
    1819             : 
    1820          12 :         return req;
    1821             : }
    1822             : 
    1823          12 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
    1824             : {
    1825           0 :         struct tevent_req *req =
    1826          12 :                 tevent_req_callback_data(subreq,
    1827             :                 struct tevent_req);
    1828             : 
    1829          12 :         tevent_queue_wait_recv(subreq);
    1830          12 :         TALLOC_FREE(subreq);
    1831             : 
    1832          12 :         tevent_req_done(req);
    1833          12 : }
    1834             : 
    1835        2023 : NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
    1836             : {
    1837        2023 :         return tevent_req_simple_recv_ntstatus(req);
    1838             : }
    1839             : 
    1840       61423 : NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
    1841             : {
    1842        1513 :         struct smbXsrv_session_table *table;
    1843       61423 :         struct db_record *local_rec = NULL;
    1844       61423 :         struct db_record *global_rec = NULL;
    1845       61423 :         struct smbd_server_connection *sconn = NULL;
    1846        1513 :         NTSTATUS status;
    1847       61423 :         NTSTATUS error = NT_STATUS_OK;
    1848             : 
    1849       61423 :         if (session->table == NULL) {
    1850       29180 :                 return NT_STATUS_OK;
    1851             :         }
    1852             : 
    1853       32243 :         table = session->table;
    1854       32243 :         session->table = NULL;
    1855             : 
    1856       32243 :         sconn = session->client->sconn;
    1857       32243 :         session->client = NULL;
    1858       32243 :         session->status = NT_STATUS_USER_SESSION_DELETED;
    1859             : 
    1860             :         /*
    1861             :          * For SMB2 this is a bit redundant as files are also close
    1862             :          * below via smb2srv_tcon_disconnect_all() -> ... ->
    1863             :          * smbXsrv_tcon_disconnect() -> close_cnum() ->
    1864             :          * file_close_conn().
    1865             :          */
    1866       32243 :         file_close_user(sconn, session->global->session_wire_id);
    1867             : 
    1868       32243 :         if (session->tcon_table != NULL) {
    1869             :                 /*
    1870             :                  * Note: We only have a tcon_table for SMB2.
    1871             :                  */
    1872       25209 :                 status = smb2srv_tcon_disconnect_all(session);
    1873       25209 :                 if (!NT_STATUS_IS_OK(status)) {
    1874          52 :                         DBG_ERR("smbXsrv_session_logoff(0x%08x): "
    1875             :                                   "smb2srv_tcon_disconnect_all() failed: %s\n",
    1876             :                                   session->global->session_global_id,
    1877             :                                   nt_errstr(status));
    1878          52 :                         error = status;
    1879             :                 }
    1880             :         }
    1881             : 
    1882       32243 :         invalidate_vuid(sconn, session->global->session_wire_id);
    1883             : 
    1884       32243 :         global_rec = session->global->db_rec;
    1885       32243 :         session->global->db_rec = NULL;
    1886       32243 :         if (global_rec == NULL) {
    1887       32243 :                 global_rec = smbXsrv_session_global_fetch_locked(
    1888             :                                         table->global.db_ctx,
    1889       31483 :                                         session->global->session_global_id,
    1890       31483 :                                         session->global /* TALLOC_CTX */);
    1891       32243 :                 if (global_rec == NULL) {
    1892           0 :                         error = NT_STATUS_INTERNAL_ERROR;
    1893             :                 }
    1894             :         }
    1895             : 
    1896       32243 :         if (global_rec != NULL) {
    1897       32243 :                 status = dbwrap_record_delete(global_rec);
    1898       32243 :                 if (!NT_STATUS_IS_OK(status)) {
    1899           0 :                         TDB_DATA key = dbwrap_record_get_key(global_rec);
    1900             : 
    1901           0 :                         DBG_ERR("smbXsrv_session_logoff(0x%08x): "
    1902             :                                   "failed to delete global key '%s': %s\n",
    1903             :                                   session->global->session_global_id,
    1904             :                                   tdb_data_dbg(key),
    1905             :                                   nt_errstr(status));
    1906           0 :                         error = status;
    1907             :                 }
    1908             :         }
    1909       32243 :         TALLOC_FREE(global_rec);
    1910             : 
    1911       32243 :         local_rec = session->db_rec;
    1912       32243 :         if (local_rec == NULL) {
    1913        3332 :                 local_rec = smbXsrv_session_local_fetch_locked(
    1914             :                                                 table->local.db_ctx,
    1915             :                                                 session->local_id,
    1916             :                                                 session /* TALLOC_CTX */);
    1917        3332 :                 if (local_rec == NULL) {
    1918           0 :                         error = NT_STATUS_INTERNAL_ERROR;
    1919             :                 }
    1920             :         }
    1921             : 
    1922       32243 :         if (local_rec != NULL) {
    1923       32243 :                 status = dbwrap_record_delete(local_rec);
    1924       32243 :                 if (!NT_STATUS_IS_OK(status)) {
    1925           0 :                         TDB_DATA key = dbwrap_record_get_key(local_rec);
    1926             : 
    1927           0 :                         DBG_ERR("smbXsrv_session_logoff(0x%08x): "
    1928             :                                   "failed to delete local key '%s': %s\n",
    1929             :                                   session->global->session_global_id,
    1930             :                                   tdb_data_dbg(key),
    1931             :                                   nt_errstr(status));
    1932           0 :                         error = status;
    1933             :                 }
    1934       32243 :                 table->local.num_sessions -= 1;
    1935             :         }
    1936       32243 :         if (session->db_rec == NULL) {
    1937        3332 :                 TALLOC_FREE(local_rec);
    1938             :         }
    1939       32243 :         session->db_rec = NULL;
    1940             : 
    1941       32243 :         return error;
    1942             : }
    1943             : 
    1944             : struct smbXsrv_session_logoff_all_state {
    1945             :         NTSTATUS first_status;
    1946             :         int errors;
    1947             : };
    1948             : 
    1949             : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
    1950             :                                                void *private_data);
    1951             : 
    1952       31549 : NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_client *client)
    1953             : {
    1954       31549 :         struct smbXsrv_session_table *table = client->session_table;
    1955       31549 :         struct smbXsrv_session_logoff_all_state state = {};
    1956         842 :         NTSTATUS status;
    1957       31549 :         int count = 0;
    1958             : 
    1959       31549 :         if (table == NULL) {
    1960         700 :                 DBG_DEBUG("empty session_table, nothing to do.\n");
    1961         700 :                 return NT_STATUS_OK;
    1962             :         }
    1963             : 
    1964       30849 :         status = dbwrap_traverse(table->local.db_ctx,
    1965             :                                  smbXsrv_session_logoff_all_callback,
    1966             :                                  &state, &count);
    1967       30849 :         if (!NT_STATUS_IS_OK(status)) {
    1968           0 :                 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
    1969           0 :                 return status;
    1970             :         }
    1971             : 
    1972       30849 :         if (!NT_STATUS_IS_OK(state.first_status)) {
    1973          50 :                 DBG_ERR("count[%d] errors[%d] first[%s]\n",
    1974             :                         count,
    1975             :                         state.errors,
    1976             :                         nt_errstr(state.first_status));
    1977          50 :                 return state.first_status;
    1978             :         }
    1979             : 
    1980       30799 :         return NT_STATUS_OK;
    1981             : }
    1982             : 
    1983       28911 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
    1984             :                                                void *private_data)
    1985             : {
    1986       28911 :         struct smbXsrv_session_logoff_all_state *state =
    1987             :                 (struct smbXsrv_session_logoff_all_state *)private_data;
    1988         739 :         TDB_DATA val;
    1989       28911 :         void *ptr = NULL;
    1990       28911 :         struct smbXsrv_session *session = NULL;
    1991         739 :         NTSTATUS status;
    1992             : 
    1993       28911 :         val = dbwrap_record_get_value(local_rec);
    1994       28911 :         if (val.dsize != sizeof(ptr)) {
    1995           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    1996           0 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    1997           0 :                         state->first_status = status;
    1998             :                 }
    1999           0 :                 state->errors++;
    2000           0 :                 return 0;
    2001             :         }
    2002             : 
    2003       28911 :         memcpy(&ptr, val.dptr, val.dsize);
    2004       28911 :         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
    2005             : 
    2006       28911 :         session->db_rec = local_rec;
    2007       28911 :         status = smbXsrv_session_clear_and_logoff(session);
    2008       28911 :         session->db_rec = NULL;
    2009       28911 :         if (!NT_STATUS_IS_OK(status)) {
    2010          52 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    2011          50 :                         state->first_status = status;
    2012             :                 }
    2013          52 :                 state->errors++;
    2014          52 :                 return 0;
    2015             :         }
    2016             : 
    2017       28120 :         return 0;
    2018             : }
    2019             : 
    2020             : struct smbXsrv_session_local_trav_state {
    2021             :         NTSTATUS status;
    2022             :         int (*caller_cb)(struct smbXsrv_session *session,
    2023             :                          void *caller_data);
    2024             :         void *caller_data;
    2025             : };
    2026             : 
    2027             : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
    2028             :                                              void *private_data);
    2029             : 
    2030           0 : NTSTATUS smbXsrv_session_local_traverse(
    2031             :         struct smbXsrv_client *client,
    2032             :         int (*caller_cb)(struct smbXsrv_session *session,
    2033             :                          void *caller_data),
    2034             :         void *caller_data)
    2035             : {
    2036           0 :         struct smbXsrv_session_table *table = client->session_table;
    2037           0 :         struct smbXsrv_session_local_trav_state state;
    2038           0 :         NTSTATUS status;
    2039           0 :         int count = 0;
    2040             : 
    2041           0 :         state = (struct smbXsrv_session_local_trav_state) {
    2042             :                 .status = NT_STATUS_OK,
    2043             :                 .caller_cb = caller_cb,
    2044             :                 .caller_data = caller_data,
    2045             :         };
    2046             : 
    2047           0 :         if (table == NULL) {
    2048           0 :                 DBG_DEBUG("empty session_table, nothing to do.\n");
    2049           0 :                 return NT_STATUS_OK;
    2050             :         }
    2051             : 
    2052           0 :         status = dbwrap_traverse(table->local.db_ctx,
    2053             :                                  smbXsrv_session_local_traverse_cb,
    2054             :                                  &state,
    2055             :                                  &count);
    2056           0 :         if (!NT_STATUS_IS_OK(status)) {
    2057           0 :                 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
    2058           0 :                 return status;
    2059             :         }
    2060           0 :         if (!NT_STATUS_IS_OK(state.status)) {
    2061           0 :                 DBG_ERR("count[%d] status[%s]\n",
    2062             :                         count, nt_errstr(state.status));
    2063           0 :                 return state.status;
    2064             :         }
    2065             : 
    2066           0 :         return NT_STATUS_OK;
    2067             : }
    2068             : 
    2069           0 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
    2070             :                                              void *private_data)
    2071             : {
    2072           0 :         struct smbXsrv_session_local_trav_state *state =
    2073             :                 (struct smbXsrv_session_local_trav_state *)private_data;
    2074           0 :         TDB_DATA val;
    2075           0 :         void *ptr = NULL;
    2076           0 :         struct smbXsrv_session *session = NULL;
    2077           0 :         int ret;
    2078             : 
    2079           0 :         val = dbwrap_record_get_value(local_rec);
    2080           0 :         if (val.dsize != sizeof(ptr)) {
    2081           0 :                 state->status = NT_STATUS_INTERNAL_ERROR;
    2082           0 :                 return -1;
    2083             :         }
    2084             : 
    2085           0 :         memcpy(&ptr, val.dptr, val.dsize);
    2086           0 :         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
    2087             : 
    2088           0 :         session->db_rec = local_rec;
    2089           0 :         ret = state->caller_cb(session, state->caller_data);
    2090           0 :         session->db_rec = NULL;
    2091             : 
    2092           0 :         return ret;
    2093             : }
    2094             : 
    2095             : struct smbXsrv_session_disconnect_xconn_state {
    2096             :         struct smbXsrv_connection *xconn;
    2097             :         NTSTATUS first_status;
    2098             :         int errors;
    2099             : };
    2100             : 
    2101             : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
    2102             :                                                void *private_data);
    2103             : 
    2104        1106 : NTSTATUS smbXsrv_session_disconnect_xconn(struct smbXsrv_connection *xconn)
    2105             : {
    2106        1106 :         struct smbXsrv_client *client = xconn->client;
    2107        1106 :         struct smbXsrv_session_table *table = client->session_table;
    2108        1106 :         struct smbXsrv_session_disconnect_xconn_state state = {
    2109             :                 .xconn = xconn,
    2110             :         };
    2111          52 :         NTSTATUS status;
    2112        1106 :         int count = 0;
    2113             : 
    2114        1106 :         if (table == NULL) {
    2115           0 :                 DBG_ERR("empty session_table, nothing to do.\n");
    2116           0 :                 return NT_STATUS_OK;
    2117             :         }
    2118             : 
    2119        1106 :         status = dbwrap_traverse(table->local.db_ctx,
    2120             :                                  smbXsrv_session_disconnect_xconn_callback,
    2121             :                                  &state, &count);
    2122        1106 :         if (!NT_STATUS_IS_OK(status)) {
    2123           0 :                 DBG_ERR("dbwrap_traverse() failed: %s\n",
    2124             :                         nt_errstr(status));
    2125           0 :                 return status;
    2126             :         }
    2127             : 
    2128        1106 :         if (!NT_STATUS_IS_OK(state.first_status)) {
    2129           0 :                 DBG_ERR("count[%d] errors[%d] first[%s]\n",
    2130             :                         count, state.errors,
    2131             :                         nt_errstr(state.first_status));
    2132           0 :                 return state.first_status;
    2133             :         }
    2134             : 
    2135        1106 :         return NT_STATUS_OK;
    2136             : }
    2137             : 
    2138        1184 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
    2139             :                                                void *private_data)
    2140             : {
    2141        1184 :         struct smbXsrv_session_disconnect_xconn_state *state =
    2142             :                 (struct smbXsrv_session_disconnect_xconn_state *)private_data;
    2143          62 :         TDB_DATA val;
    2144        1184 :         void *ptr = NULL;
    2145        1184 :         struct smbXsrv_session *session = NULL;
    2146          62 :         NTSTATUS status;
    2147             : 
    2148        1184 :         val = dbwrap_record_get_value(local_rec);
    2149        1184 :         if (val.dsize != sizeof(ptr)) {
    2150           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    2151           0 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    2152           0 :                         state->first_status = status;
    2153             :                 }
    2154           0 :                 state->errors++;
    2155           0 :                 return 0;
    2156             :         }
    2157             : 
    2158        1184 :         memcpy(&ptr, val.dptr, val.dsize);
    2159        1184 :         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
    2160             : 
    2161        1184 :         session->db_rec = local_rec;
    2162        1184 :         status = smbXsrv_session_remove_channel(session, state->xconn);
    2163        1184 :         session->db_rec = NULL;
    2164        1184 :         if (!NT_STATUS_IS_OK(status)) {
    2165           0 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    2166           0 :                         state->first_status = status;
    2167             :                 }
    2168           0 :                 state->errors++;
    2169             :         }
    2170             : 
    2171        1122 :         return 0;
    2172             : }
    2173             : 
    2174        5777 : NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn)
    2175             : {
    2176             :         /*
    2177             :          * Allow a range from 1..65534 with 65534 values.
    2178             :          */
    2179        5777 :         return smbXsrv_session_table_init(conn, 1, UINT16_MAX - 1,
    2180             :                                           UINT16_MAX - 1);
    2181             : }
    2182             : 
    2183      675140 : NTSTATUS smb1srv_session_lookup(struct smbXsrv_connection *conn,
    2184             :                                 uint16_t vuid, NTTIME now,
    2185             :                                 struct smbXsrv_session **session)
    2186             : {
    2187      675140 :         struct smbXsrv_session_table *table = conn->client->session_table;
    2188      675140 :         uint32_t local_id = vuid;
    2189             : 
    2190      675140 :         return smbXsrv_session_local_lookup(table, conn, local_id, now,
    2191             :                                             session);
    2192             : }
    2193             : 
    2194     1847431 : NTSTATUS smbXsrv_session_info_lookup(struct smbXsrv_client *client,
    2195             :                                      uint64_t session_wire_id,
    2196             :                                      struct auth_session_info **si)
    2197             : {
    2198     1847431 :         struct smbXsrv_session_table *table = client->session_table;
    2199       16987 :         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
    2200     1847431 :         struct smbXsrv_session_local_fetch_state state = {
    2201             :                 .status = NT_STATUS_INTERNAL_ERROR,
    2202             :         };
    2203       16987 :         TDB_DATA key;
    2204       16987 :         NTSTATUS status;
    2205             : 
    2206     1847431 :         if (session_wire_id == 0) {
    2207           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2208             :         }
    2209             : 
    2210     1847431 :         if (table == NULL) {
    2211             :                 /* this might happen before the end of negprot */
    2212           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2213             :         }
    2214             : 
    2215     1847431 :         if (table->local.db_ctx == NULL) {
    2216           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2217             :         }
    2218             : 
    2219     1847431 :         key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
    2220             : 
    2221     1847431 :         status = dbwrap_parse_record(table->local.db_ctx, key,
    2222             :                                      smbXsrv_session_local_fetch_parser,
    2223             :                                      &state);
    2224     1847431 :         if (!NT_STATUS_IS_OK(status)) {
    2225          17 :                 return status;
    2226             :         }
    2227     1847414 :         if (!NT_STATUS_IS_OK(state.status)) {
    2228           0 :                 return state.status;
    2229             :         }
    2230     1847414 :         if (state.session->global->auth_session_info == NULL) {
    2231           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2232             :         }
    2233             : 
    2234     1847414 :         *si = state.session->global->auth_session_info;
    2235     1847414 :         return NT_STATUS_OK;
    2236             : }
    2237             : 
    2238             : /*
    2239             :  * In memory of get_valid_user_struct()
    2240             :  *
    2241             :  * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
    2242             :  * but it doesn't implement the state checks of
    2243             :  * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
    2244             :  * session wire-id of incoming SMB requests, it MUST only be used in later
    2245             :  * internal processing where the session wire-id has already been validated.
    2246             :  */
    2247       32556 : NTSTATUS get_valid_smbXsrv_session(struct smbXsrv_client *client,
    2248             :                                    uint64_t session_wire_id,
    2249             :                                    struct smbXsrv_session **session)
    2250             : {
    2251       32556 :         struct smbXsrv_session_table *table = client->session_table;
    2252         760 :         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
    2253       32556 :         struct smbXsrv_session_local_fetch_state state = {
    2254             :                 .status = NT_STATUS_INTERNAL_ERROR,
    2255             :         };
    2256         760 :         TDB_DATA key;
    2257         760 :         NTSTATUS status;
    2258             : 
    2259       32556 :         if (session_wire_id == 0) {
    2260           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2261             :         }
    2262             : 
    2263       32556 :         if (table == NULL) {
    2264             :                 /* this might happen before the end of negprot */
    2265           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2266             :         }
    2267             : 
    2268       32556 :         if (table->local.db_ctx == NULL) {
    2269           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2270             :         }
    2271             : 
    2272       32556 :         key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
    2273             : 
    2274       32556 :         status = dbwrap_parse_record(table->local.db_ctx, key,
    2275             :                                      smbXsrv_session_local_fetch_parser,
    2276             :                                      &state);
    2277       32556 :         if (!NT_STATUS_IS_OK(status)) {
    2278           0 :                 return status;
    2279             :         }
    2280       32556 :         if (!NT_STATUS_IS_OK(state.status)) {
    2281           0 :                 return state.status;
    2282             :         }
    2283       32556 :         if (state.session->global->auth_session_info == NULL) {
    2284        3034 :                 return NT_STATUS_USER_SESSION_DELETED;
    2285             :         }
    2286             : 
    2287       29522 :         *session = state.session;
    2288       29522 :         return NT_STATUS_OK;
    2289             : }
    2290             : 
    2291       26378 : NTSTATUS smb2srv_session_lookup_global(struct smbXsrv_client *client,
    2292             :                                        uint64_t session_wire_id,
    2293             :                                        TALLOC_CTX *mem_ctx,
    2294             :                                        struct smbXsrv_session **_session)
    2295             : {
    2296       26378 :         TALLOC_CTX *frame = talloc_stackframe();
    2297       26378 :         struct smbXsrv_session_table *table = client->session_table;
    2298       26378 :         uint32_t global_id = session_wire_id & UINT32_MAX;
    2299       26378 :         uint64_t global_zeros = session_wire_id & 0xFFFFFFFF00000000LLU;
    2300       26378 :         struct smbXsrv_session *session = NULL;
    2301       26378 :         struct db_record *global_rec = NULL;
    2302       26378 :         bool is_free = false;
    2303         832 :         NTSTATUS status;
    2304             : 
    2305       26378 :         if (global_id == 0) {
    2306       25211 :                 TALLOC_FREE(frame);
    2307       25211 :                 return NT_STATUS_USER_SESSION_DELETED;
    2308             :         }
    2309        1167 :         if (global_zeros != 0) {
    2310           0 :                 TALLOC_FREE(frame);
    2311           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2312             :         }
    2313             : 
    2314        1167 :         if (table == NULL) {
    2315             :                 /* this might happen before the end of negprot */
    2316           0 :                 TALLOC_FREE(frame);
    2317           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2318             :         }
    2319             : 
    2320        1167 :         if (table->global.db_ctx == NULL) {
    2321           0 :                 TALLOC_FREE(frame);
    2322           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2323             :         }
    2324             : 
    2325        1167 :         session = talloc_zero(mem_ctx, struct smbXsrv_session);
    2326        1167 :         if (session == NULL) {
    2327           0 :                 TALLOC_FREE(frame);
    2328           0 :                 return NT_STATUS_NO_MEMORY;
    2329             :         }
    2330        1167 :         talloc_steal(frame, session);
    2331             : 
    2332        1167 :         session->client = client;
    2333        1167 :         session->status = NT_STATUS_BAD_LOGON_SESSION_STATE;
    2334        1167 :         session->local_id = global_id;
    2335             : 
    2336             :         /*
    2337             :          * This means smb2_get_new_nonce() will return
    2338             :          * NT_STATUS_ENCRYPTION_FAILED.
    2339             :          *
    2340             :          * But we initialize some random parts just in case...
    2341             :          */
    2342        1167 :         session->nonce_high_max = session->nonce_high = 0;
    2343        1167 :         generate_nonce_buffer((uint8_t *)&session->nonce_high_random,
    2344             :                               sizeof(session->nonce_high_random));
    2345        1167 :         generate_nonce_buffer((uint8_t *)&session->nonce_low,
    2346             :                               sizeof(session->nonce_low));
    2347             : 
    2348        1167 :         global_rec = smbXsrv_session_global_fetch_locked(table->global.db_ctx,
    2349             :                                                          global_id,
    2350             :                                                          frame);
    2351        1167 :         if (global_rec == NULL) {
    2352           0 :                 TALLOC_FREE(frame);
    2353           0 :                 return NT_STATUS_INTERNAL_DB_ERROR;
    2354             :         }
    2355             : 
    2356        1167 :         smbXsrv_session_global_verify_record(global_rec,
    2357             :                                              &is_free,
    2358             :                                              NULL,
    2359             :                                              session,
    2360        1167 :                                              &session->global,
    2361             :                                              NULL);
    2362        1167 :         if (is_free) {
    2363          10 :                 TALLOC_FREE(frame);
    2364          10 :                 return NT_STATUS_USER_SESSION_DELETED;
    2365             :         }
    2366             : 
    2367             :         /*
    2368             :          * We don't have channels on this session
    2369             :          * and only the main signing key
    2370             :          */
    2371        1157 :         session->global->num_channels = 0;
    2372        1362 :         status = smb2_signing_key_sign_create(session->global,
    2373        1157 :                                               session->global->signing_algo,
    2374             :                                               NULL, /* no master key */
    2375             :                                               NULL, /* derivations */
    2376         952 :                                               &session->global->signing_key);
    2377        1157 :         if (!NT_STATUS_IS_OK(status)) {
    2378           0 :                 TALLOC_FREE(frame);
    2379           0 :                 return NT_STATUS_NO_MEMORY;
    2380             :         }
    2381        1157 :         session->global->signing_key->blob = session->global->signing_key_blob;
    2382        1157 :         session->global->signing_flags = 0;
    2383             : 
    2384        1362 :         status = smb2_signing_key_cipher_create(session->global,
    2385        1157 :                                                 session->global->encryption_cipher,
    2386             :                                                 NULL, /* no master key */
    2387             :                                                 NULL, /* derivations */
    2388         952 :                                                 &session->global->decryption_key);
    2389        1157 :         if (!NT_STATUS_IS_OK(status)) {
    2390           0 :                 TALLOC_FREE(frame);
    2391           0 :                 return NT_STATUS_NO_MEMORY;
    2392             :         }
    2393        1157 :         session->global->decryption_key->blob = session->global->decryption_key_blob;
    2394        1157 :         session->global->encryption_flags = 0;
    2395             : 
    2396        1157 :         *_session = talloc_move(mem_ctx, &session);
    2397        1157 :         TALLOC_FREE(frame);
    2398        1157 :         return NT_STATUS_OK;
    2399             : }
    2400             : 
    2401       25086 : NTSTATUS smb2srv_session_table_init(struct smbXsrv_connection *conn)
    2402             : {
    2403             :         /*
    2404             :          * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
    2405             :          */
    2406       25086 :         return smbXsrv_session_table_init(conn, 1, UINT32_MAX - 1,
    2407             :                                           UINT16_MAX - 1);
    2408             : }
    2409             : 
    2410     1493425 : static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
    2411             :                                            /* conn: optional */
    2412             :                                            struct smbXsrv_connection *conn,
    2413             :                                            uint64_t session_id, NTTIME now,
    2414             :                                            struct smbXsrv_session **session)
    2415             : {
    2416     1493425 :         uint32_t local_id = session_id & UINT32_MAX;
    2417     1493425 :         uint64_t local_zeros = session_id & 0xFFFFFFFF00000000LLU;
    2418             : 
    2419     1493425 :         if (local_zeros != 0) {
    2420          24 :                 return NT_STATUS_USER_SESSION_DELETED;
    2421             :         }
    2422             : 
    2423     1493401 :         return smbXsrv_session_local_lookup(table, conn, local_id, now,
    2424             :                                             session);
    2425             : }
    2426             : 
    2427     1446519 : NTSTATUS smb2srv_session_lookup_conn(struct smbXsrv_connection *conn,
    2428             :                                      uint64_t session_id, NTTIME now,
    2429             :                                      struct smbXsrv_session **session)
    2430             : {
    2431     1446519 :         struct smbXsrv_session_table *table = conn->client->session_table;
    2432     1446519 :         return smb2srv_session_lookup_raw(table, conn, session_id, now,
    2433             :                                           session);
    2434             : }
    2435             : 
    2436       46906 : NTSTATUS smb2srv_session_lookup_client(struct smbXsrv_client *client,
    2437             :                                        uint64_t session_id, NTTIME now,
    2438             :                                        struct smbXsrv_session **session)
    2439             : {
    2440       46906 :         struct smbXsrv_session_table *table = client->session_table;
    2441       46906 :         return smb2srv_session_lookup_raw(table, NULL, session_id, now,
    2442             :                                           session);
    2443             : }
    2444             : 
    2445             : struct smbXsrv_session_global_traverse_state {
    2446             :         int (*fn)(struct smbXsrv_session_global0 *, void *);
    2447             :         void *private_data;
    2448             : };
    2449             : 
    2450          46 : static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
    2451             : {
    2452          46 :         int ret = -1;
    2453          46 :         struct smbXsrv_session_global_traverse_state *state =
    2454             :                 (struct smbXsrv_session_global_traverse_state*)data;
    2455          46 :         TDB_DATA key = dbwrap_record_get_key(rec);
    2456          46 :         TDB_DATA val = dbwrap_record_get_value(rec);
    2457          46 :         DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
    2458           0 :         struct smbXsrv_session_globalB global_blob;
    2459           0 :         enum ndr_err_code ndr_err;
    2460          46 :         TALLOC_CTX *frame = talloc_stackframe();
    2461             : 
    2462          46 :         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
    2463             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
    2464          46 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    2465           0 :                 DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
    2466             :                          "key '%s' ndr_pull_struct_blob - %s\n",
    2467             :                          tdb_data_dbg(key),
    2468             :                          ndr_errstr(ndr_err));
    2469           0 :                 goto done;
    2470             :         }
    2471             : 
    2472          46 :         if (global_blob.version != SMBXSRV_VERSION_0) {
    2473           0 :                 DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
    2474             :                          "key '%s' unsupported version - %d\n",
    2475             :                          tdb_data_dbg(key),
    2476             :                          (int)global_blob.version);
    2477           0 :                 goto done;
    2478             :         }
    2479             : 
    2480          46 :         if (global_blob.info.info0 == NULL) {
    2481           0 :                 DBG_WARNING("Invalid record in smbXsrv_tcon_global.tdb:"
    2482             :                          "key '%s' info0 NULL pointer\n",
    2483             :                          tdb_data_dbg(key));
    2484           0 :                 goto done;
    2485             :         }
    2486             : 
    2487          46 :         global_blob.info.info0->db_rec = rec;
    2488          46 :         ret = state->fn(global_blob.info.info0, state->private_data);
    2489          46 : done:
    2490          46 :         TALLOC_FREE(frame);
    2491          46 :         return ret;
    2492             : }
    2493             : 
    2494          42 : NTSTATUS smbXsrv_session_global_traverse(
    2495             :                         int (*fn)(struct smbXsrv_session_global0 *, void *),
    2496             :                         void *private_data)
    2497             : {
    2498             : 
    2499           0 :         NTSTATUS status;
    2500          42 :         int count = 0;
    2501          42 :         struct smbXsrv_session_global_traverse_state state = {
    2502             :                 .fn = fn,
    2503             :                 .private_data = private_data,
    2504             :         };
    2505             : 
    2506          42 :         become_root();
    2507          42 :         status = smbXsrv_session_global_init(NULL);
    2508          42 :         if (!NT_STATUS_IS_OK(status)) {
    2509           0 :                 unbecome_root();
    2510           0 :                 DBG_ERR("Failed to initialize session_global: %s\n",
    2511             :                           nt_errstr(status));
    2512           0 :                 return status;
    2513             :         }
    2514             : 
    2515          42 :         status = dbwrap_traverse_read(smbXsrv_session_global_db_ctx,
    2516             :                                       smbXsrv_session_global_traverse_fn,
    2517             :                                       &state,
    2518             :                                       &count);
    2519          42 :         unbecome_root();
    2520             : 
    2521          42 :         return status;
    2522             : }

Generated by: LCOV version 1.14