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

Generated by: LCOV version 1.14