LCOV - code coverage report
Current view: top level - source3/smbd - smbXsrv_session.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 850 1203 70.7 %
Date: 2024-02-28 12:06:22 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       34746 : NTSTATUS smbXsrv_session_global_init(struct messaging_context *msg_ctx)
      60             : {
      61       34746 :         char *global_path = NULL;
      62       34746 :         struct db_context *backend = NULL;
      63       34746 :         struct db_context *db_ctx = NULL;
      64             : 
      65       34746 :         if (smbXsrv_session_global_db_ctx != NULL) {
      66       34717 :                 return NT_STATUS_OK;
      67             :         }
      68             : 
      69             :         /*
      70             :          * This contains secret information like session keys!
      71             :          */
      72          29 :         global_path = lock_path(talloc_tos(), "smbXsrv_session_global.tdb");
      73          29 :         if (global_path == NULL) {
      74           0 :                 return NT_STATUS_NO_MEMORY;
      75             :         }
      76             : 
      77          29 :         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          29 :         TALLOC_FREE(global_path);
      84          29 :         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          29 :         db_ctx = db_open_watched(NULL, &backend, global_messaging_context());
      93          29 :         if (db_ctx == NULL) {
      94           0 :                 TALLOC_FREE(backend);
      95           0 :                 return NT_STATUS_NO_MEMORY;
      96             :         }
      97             : 
      98          29 :         smbXsrv_session_global_db_ctx = db_ctx;
      99             : 
     100          29 :         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      226531 : 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      226531 :         RSIVAL(key_buf, 0, id);
     120             : 
     121      226531 :         key = make_tdb_data(key_buf, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE);
     122             : 
     123      226531 :         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     4259228 : static TDB_DATA smbXsrv_session_local_id_to_key(uint32_t id,
     146             :                                                 uint8_t *key_buf)
     147             : {
     148       37545 :         TDB_DATA key;
     149             : 
     150     4259228 :         RSIVAL(key_buf, 0, id);
     151             : 
     152     4259228 :         key = make_tdb_data(key_buf, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE);
     153             : 
     154     4259228 :         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      226531 : 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      226531 :         struct db_record *rec = NULL;
     180             : 
     181      226531 :         key = smbXsrv_session_global_id_to_key(id, key_buf);
     182             : 
     183      226531 :         rec = dbwrap_fetch_locked(db, mem_ctx, key);
     184             : 
     185      226531 :         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      226531 :         return rec;
     191             : }
     192             : 
     193       40455 : 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       40455 :         struct db_record *rec = NULL;
     201             : 
     202       40455 :         key = smbXsrv_session_local_id_to_key(id, key_buf);
     203             : 
     204       40455 :         rec = dbwrap_fetch_locked(db, mem_ctx, key);
     205             : 
     206       40455 :         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       40455 :         return rec;
     212             : }
     213             : 
     214             : static void smbXsrv_session_close_loop(struct tevent_req *subreq);
     215             : 
     216       34693 : 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       34693 :         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       34693 :         if (lowest_id > highest_id) {
     228           0 :                 return NT_STATUS_INTERNAL_ERROR;
     229             :         }
     230             : 
     231       34693 :         max_range = highest_id;
     232       34693 :         max_range -= lowest_id;
     233       34693 :         max_range += 1;
     234             : 
     235       34693 :         if (max_sessions > max_range) {
     236           0 :                 return NT_STATUS_INTERNAL_ERROR;
     237             :         }
     238             : 
     239       34693 :         table = talloc_zero(client, struct smbXsrv_session_table);
     240       34693 :         if (table == NULL) {
     241           0 :                 return NT_STATUS_NO_MEMORY;
     242             :         }
     243             : 
     244       34693 :         table->local.db_ctx = db_open_rbt(table);
     245       34693 :         if (table->local.db_ctx == NULL) {
     246           0 :                 TALLOC_FREE(table);
     247           0 :                 return NT_STATUS_NO_MEMORY;
     248             :         }
     249       34693 :         table->local.lowest_id = lowest_id;
     250       34693 :         table->local.highest_id = highest_id;
     251       34693 :         table->local.max_sessions = max_sessions;
     252             : 
     253       34693 :         status = smbXsrv_session_global_init(client->msg_ctx);
     254       34693 :         if (!NT_STATUS_IS_OK(status)) {
     255           0 :                 TALLOC_FREE(table);
     256           0 :                 return status;
     257             :         }
     258             : 
     259       34693 :         table->global.db_ctx = smbXsrv_session_global_db_ctx;
     260             : 
     261       34693 :         subreq = messaging_read_send(table,
     262             :                                      client->raw_ev_ctx,
     263             :                                      client->msg_ctx,
     264             :                                      MSG_SMBXSRV_SESSION_CLOSE);
     265       34693 :         if (subreq == NULL) {
     266           0 :                 TALLOC_FREE(table);
     267           0 :                 return NT_STATUS_NO_MEMORY;
     268             :         }
     269       34693 :         tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
     270             : 
     271       34693 :         client->session_table = table;
     272       34693 :         return NT_STATUS_OK;
     273             : }
     274             : 
     275             : static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq);
     276             : 
     277          55 : static void smbXsrv_session_close_loop(struct tevent_req *subreq)
     278             : {
     279           4 :         struct smbXsrv_client *client =
     280          55 :                 tevent_req_callback_data(subreq,
     281             :                 struct smbXsrv_client);
     282          55 :         struct smbXsrv_session_table *table = client->session_table;
     283           4 :         int ret;
     284          55 :         struct messaging_rec *rec = NULL;
     285           4 :         struct smbXsrv_session_closeB close_blob;
     286           4 :         enum ndr_err_code ndr_err;
     287          55 :         struct smbXsrv_session_close0 *close_info0 = NULL;
     288          55 :         struct smbXsrv_session *session = NULL;
     289           4 :         NTSTATUS status;
     290          55 :         struct timeval tv = timeval_current();
     291          55 :         NTTIME now = timeval_to_nttime(&tv);
     292             : 
     293          55 :         ret = messaging_read_recv(subreq, talloc_tos(), &rec);
     294          55 :         TALLOC_FREE(subreq);
     295          55 :         if (ret != 0) {
     296           0 :                 goto next;
     297             :         }
     298             : 
     299          55 :         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &close_blob,
     300             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_closeB);
     301          55 :         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          55 :         DBG_DEBUG("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n");
     310          55 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     311           0 :                 NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
     312             :         }
     313             : 
     314          55 :         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          55 :         close_info0 = close_blob.info.info0;
     322          55 :         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          55 :         status = smb2srv_session_lookup_client(client,
     330             :                                                close_info0->old_session_wire_id,
     331             :                                                now, &session);
     332          55 :         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          55 :         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          55 :         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          55 :         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          55 :         subreq = smb2srv_session_shutdown_send(session, client->raw_ev_ctx,
     382             :                                                session, NULL);
     383          55 :         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          55 :         tevent_req_set_callback(subreq,
     395             :                                 smbXsrv_session_close_shutdown_done,
     396             :                                 session);
     397             : 
     398          55 : next:
     399          55 :         TALLOC_FREE(rec);
     400             : 
     401          55 :         subreq = messaging_read_send(table,
     402             :                                      client->raw_ev_ctx,
     403             :                                      client->msg_ctx,
     404             :                                      MSG_SMBXSRV_SESSION_CLOSE);
     405          55 :         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          55 :         tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
     412             : }
     413             : 
     414          55 : static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq)
     415             : {
     416           4 :         struct smbXsrv_session *session =
     417          55 :                 tevent_req_callback_data(subreq,
     418             :                 struct smbXsrv_session);
     419           4 :         NTSTATUS status;
     420             : 
     421          55 :         status = smb2srv_session_shutdown_recv(subreq);
     422          55 :         TALLOC_FREE(subreq);
     423          55 :         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          55 :         status = smbXsrv_session_logoff(session);
     431          55 :         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          55 :         TALLOC_FREE(session);
     439          55 : }
     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        7122 : 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        7122 :         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        7122 :         int count = 0;
     502             : 
     503        7122 :         *_rec = NULL;
     504        7122 :         *_id = 0;
     505             : 
     506        7122 :         if (lowest_id > highest_id) {
     507           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
     508             :         }
     509             : 
     510             :         /*
     511             :          * first we try randomly
     512             :          */
     513        7122 :         range = (highest_id - lowest_id) + 1;
     514             : 
     515        7122 :         for (i = 0; i < (range / 2); i++) {
     516         133 :                 uint32_t id;
     517         133 :                 TDB_DATA val;
     518        7122 :                 struct db_record *rec = NULL;
     519             : 
     520        7122 :                 id = generate_random() % range;
     521        7122 :                 id += lowest_id;
     522             : 
     523        7122 :                 if (id < lowest_id) {
     524           0 :                         id = lowest_id;
     525             :                 }
     526        7122 :                 if (id > highest_id) {
     527           0 :                         id = highest_id;
     528             :                 }
     529             : 
     530        7122 :                 rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
     531        7122 :                 if (rec == NULL) {
     532           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     533             :                 }
     534             : 
     535        7122 :                 val = dbwrap_record_get_value(rec);
     536        7122 :                 if (val.dsize != 0) {
     537           0 :                         TALLOC_FREE(rec);
     538           0 :                         continue;
     539             :                 }
     540             : 
     541        7122 :                 *_rec = rec;
     542        7122 :                 *_id = id;
     543        7122 :                 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     4217695 : static void smbXsrv_session_local_fetch_parser(TDB_DATA key, TDB_DATA data,
     610             :                                                void *private_data)
     611             : {
     612     4217695 :         struct smbXsrv_session_local_fetch_state *state =
     613             :                 (struct smbXsrv_session_local_fetch_state *)private_data;
     614       36598 :         void *ptr;
     615             : 
     616     4217695 :         if (data.dsize != sizeof(ptr)) {
     617           0 :                 state->status = NT_STATUS_INTERNAL_DB_ERROR;
     618           0 :                 return;
     619             :         }
     620             : 
     621     4217695 :         memcpy(&ptr, data.dptr, data.dsize);
     622     4217695 :         state->session = talloc_get_type_abort(ptr, struct smbXsrv_session);
     623     4217695 :         state->status = NT_STATUS_OK;
     624             : }
     625             : 
     626     2306989 : 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     2306989 :         struct smbXsrv_session_local_fetch_state state = {
     634             :                 .session = NULL,
     635             :                 .status = NT_STATUS_INTERNAL_ERROR,
     636             :         };
     637       20817 :         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
     638       20817 :         TDB_DATA key;
     639       20817 :         NTSTATUS status;
     640             : 
     641     2306989 :         *_session = NULL;
     642             : 
     643     2306989 :         if (session_local_id == 0) {
     644       94585 :                 return NT_STATUS_USER_SESSION_DELETED;
     645             :         }
     646             : 
     647     2212404 :         if (table == NULL) {
     648             :                 /* this might happen before the end of negprot */
     649           0 :                 return NT_STATUS_USER_SESSION_DELETED;
     650             :         }
     651             : 
     652     2212404 :         if (table->local.db_ctx == NULL) {
     653           0 :                 return NT_STATUS_INTERNAL_ERROR;
     654             :         }
     655             : 
     656     2212404 :         key = smbXsrv_session_local_id_to_key(session_local_id, key_buf);
     657             : 
     658     2212404 :         status = dbwrap_parse_record(table->local.db_ctx, key,
     659             :                                      smbXsrv_session_local_fetch_parser,
     660             :                                      &state);
     661     2212404 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     662        1061 :                 return NT_STATUS_USER_SESSION_DELETED;
     663     2211343 :         } else if (!NT_STATUS_IS_OK(status)) {
     664           0 :                 return status;
     665             :         }
     666     2211343 :         if (!NT_STATUS_IS_OK(state.status)) {
     667           0 :                 return state.status;
     668             :         }
     669             : 
     670     2211343 :         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     2211343 :         if (conn != NULL) {
     679     2186163 :                 struct smbXsrv_channel_global0 *c = NULL;
     680             : 
     681     2186163 :                 status = smbXsrv_session_find_channel(state.session, conn, &c);
     682     2186163 :                 if (!NT_STATUS_IS_OK(status)) {
     683         140 :                         return status;
     684             :                 }
     685             :         }
     686             : 
     687     2211203 :         state.session->idle_time = now;
     688             : 
     689     2211203 :         if (!NT_STATUS_IS_OK(state.session->status)) {
     690       35654 :                 *_session = state.session;
     691       35654 :                 return state.session->status;
     692             :         }
     693             : 
     694     2175549 :         if (now > state.session->global->expiration_time) {
     695          49 :                 state.session->status = NT_STATUS_NETWORK_SESSION_EXPIRED;
     696             :         }
     697             : 
     698     2175549 :         *_session = state.session;
     699     2175549 :         return state.session->status;
     700             : }
     701             : 
     702       36588 : static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0 *global)
     703             : {
     704       36588 :         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       36602 : 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       36602 :         struct smbXsrv_session_global0 *global = NULL;
     720       36602 :         uint32_t last_free = 0;
     721       36602 :         const uint32_t min_tries = 3;
     722             : 
     723       36602 :         *_global = NULL;
     724             : 
     725       36602 :         global = talloc_zero(mem_ctx, struct smbXsrv_session_global0);
     726       36602 :         if (global == NULL) {
     727           0 :                 return NT_STATUS_NO_MEMORY;
     728             :         }
     729       36602 :         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       37362 :         for (i = 0; i < UINT32_MAX; i++) {
     738       36602 :                 bool is_free = false;
     739       36602 :                 bool was_free = false;
     740         760 :                 uint32_t id;
     741             : 
     742       36602 :                 if (i >= min_tries && last_free != 0) {
     743           0 :                         id = last_free;
     744             :                 } else {
     745       36602 :                         id = generate_random();
     746             :                 }
     747       36602 :                 if (id == 0) {
     748           0 :                         id++;
     749             :                 }
     750       36602 :                 if (id == UINT32_MAX) {
     751           0 :                         id--;
     752             :                 }
     753             : 
     754       36602 :                 global->db_rec = smbXsrv_session_global_fetch_locked(db, id,
     755             :                                                                      mem_ctx);
     756       36602 :                 if (global->db_rec == NULL) {
     757           0 :                         talloc_free(global);
     758           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     759             :                 }
     760             : 
     761       36602 :                 smbXsrv_session_global_verify_record(global->db_rec,
     762             :                                                      &is_free,
     763             :                                                      &was_free,
     764             :                                                      NULL, NULL, NULL);
     765             : 
     766       36602 :                 if (!is_free) {
     767           0 :                         TALLOC_FREE(global->db_rec);
     768           0 :                         continue;
     769             :                 }
     770             : 
     771       36602 :                 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       36602 :                 global->session_global_id = id;
     790             : 
     791       36602 :                 *_global = global;
     792       36602 :                 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       37929 : 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       37929 :         struct smbXsrv_session_global0 *global = NULL;
     813         973 :         bool exists;
     814       37929 :         TALLOC_CTX *frame = talloc_stackframe();
     815             : 
     816       37929 :         *is_free = false;
     817             : 
     818       37929 :         if (was_free) {
     819       36602 :                 *was_free = false;
     820             :         }
     821       37929 :         if (_g) {
     822        1327 :                 *_g = NULL;
     823             :         }
     824       37929 :         if (pseqnum) {
     825         160 :                 *pseqnum = 0;
     826             :         }
     827             : 
     828       37929 :         key = dbwrap_record_get_key(db_rec);
     829             : 
     830       37929 :         val = dbwrap_record_get_value(db_rec);
     831       37929 :         if (val.dsize == 0) {
     832       36715 :                 TALLOC_FREE(frame);
     833       36715 :                 *is_free = true;
     834       36715 :                 if (was_free) {
     835       36602 :                         *was_free = true;
     836             :                 }
     837       36715 :                 return;
     838             :         }
     839             : 
     840        1214 :         blob = data_blob_const(val.dptr, val.dsize);
     841             : 
     842        1214 :         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
     843             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
     844        1214 :         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        1214 :         DBG_DEBUG("smbXsrv_session_global_verify_record\n");
     859        1214 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     860           0 :                 NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
     861             :         }
     862             : 
     863        1214 :         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        1214 :         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        1214 :                 __BLOB_KEEP_SECRET(global->application_key_blob);
     887        1214 :                 __BLOB_KEEP_SECRET(global->signing_key_blob);
     888        1214 :                 __BLOB_KEEP_SECRET(global->encryption_key_blob);
     889        1214 :                 __BLOB_KEEP_SECRET(global->decryption_key_blob);
     890        2436 :                 for (i = 0; i < global->num_channels; i++) {
     891        1222 :                         __BLOB_KEEP_SECRET(global->channels[i].signing_key_blob);
     892             :                 }
     893             :         }
     894             : #undef __BLOB_KEEP_SECRET
     895             : 
     896        1214 :         exists = serverid_exists(&global->channels[0].server_id);
     897        1214 :         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        1214 :         if (_g) {
     914        1214 :                 *_g = talloc_move(mem_ctx, &global);
     915             :         }
     916        1214 :         if (pseqnum) {
     917          57 :                 *pseqnum = global_blob.seqnum;
     918             :         }
     919        1214 :         TALLOC_FREE(frame);
     920             : }
     921             : 
     922      188616 : static NTSTATUS smbXsrv_session_global_store(struct smbXsrv_session_global0 *global)
     923             : {
     924        3327 :         struct smbXsrv_session_globalB global_blob;
     925      188616 :         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      188616 :         if (global->db_rec == NULL) {
     938           0 :                 return NT_STATUS_INTERNAL_ERROR;
     939             :         }
     940             : 
     941      188616 :         key = dbwrap_record_get_key(global->db_rec);
     942      188616 :         val = dbwrap_record_get_value(global->db_rec);
     943             : 
     944      188616 :         ZERO_STRUCT(global_blob);
     945      188616 :         global_blob.version = smbXsrv_version_global_current();
     946      188616 :         if (val.dsize >= 8) {
     947      152014 :                 global_blob.seqnum = IVAL(val.dptr, 4);
     948             :         }
     949      188616 :         global_blob.seqnum += 1;
     950      188616 :         global_blob.info.info0 = global;
     951             : 
     952      188616 :         ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
     953             :                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_globalB);
     954      188616 :         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      188616 :         val = make_tdb_data(blob.data, blob.length);
     964      188616 :         status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
     965      188616 :         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      188616 :         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      188616 :         TALLOC_FREE(global->db_rec);
     980             : 
     981      188616 :         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         206 : 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         206 :                 tevent_req_data(req,
    1000             :                 struct smb2srv_session_close_previous_state);
    1001             : 
    1002         206 :         if (state->db_rec != NULL) {
    1003         103 :                 dbwrap_watched_watch_remove_instance(state->db_rec,
    1004             :                                                      state->watch_instance);
    1005         103 :                 state->watch_instance = 0;
    1006         103 :                 TALLOC_FREE(state->db_rec);
    1007             :         }
    1008         206 : }
    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         103 : 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         103 :         uint32_t global_id = previous_session_id & UINT32_MAX;
    1023         103 :         uint64_t global_zeros = previous_session_id & 0xFFFFFFFF00000000LLU;
    1024         103 :         struct smbXsrv_session_table *table = conn->client->session_table;
    1025         103 :         struct security_token *current_token = NULL;
    1026             : 
    1027         103 :         req = tevent_req_create(mem_ctx, &state,
    1028             :                                 struct smb2srv_session_close_previous_state);
    1029         103 :         if (req == NULL) {
    1030           0 :                 return NULL;
    1031             :         }
    1032         103 :         state->ev = ev;
    1033         103 :         state->connection = conn;
    1034         103 :         state->previous_session_id = previous_session_id;
    1035         103 :         state->current_session_id = current_session_id;
    1036             : 
    1037         103 :         tevent_req_set_cleanup_fn(req, smb2srv_session_close_previous_cleanup);
    1038             : 
    1039         103 :         if (global_zeros != 0) {
    1040           0 :                 tevent_req_done(req);
    1041           0 :                 return tevent_req_post(req, ev);
    1042             :         }
    1043             : 
    1044         103 :         if (session_info == NULL) {
    1045           0 :                 tevent_req_done(req);
    1046           0 :                 return tevent_req_post(req, ev);
    1047             :         }
    1048         103 :         current_token = session_info->security_token;
    1049             : 
    1050         103 :         if (current_token->num_sids > PRIMARY_USER_SID_INDEX) {
    1051         103 :                 state->current_sid = &current_token->sids[PRIMARY_USER_SID_INDEX];
    1052             :         }
    1053             : 
    1054         103 :         if (state->current_sid == NULL) {
    1055           0 :                 tevent_req_done(req);
    1056           0 :                 return tevent_req_post(req, ev);
    1057             :         }
    1058             : 
    1059         103 :         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         103 :         state->db_rec = smbXsrv_session_global_fetch_locked(
    1066             :                                                         table->global.db_ctx,
    1067             :                                                         global_id,
    1068             :                                                         state /* TALLOC_CTX */);
    1069         103 :         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         103 :         smb2srv_session_close_previous_check(req);
    1075         103 :         if (!tevent_req_is_in_progress(req)) {
    1076          46 :                 return tevent_req_post(req, ev);
    1077             :         }
    1078             : 
    1079          53 :         return req;
    1080             : }
    1081             : 
    1082         160 : static void smb2srv_session_close_previous_check(struct tevent_req *req)
    1083             : {
    1084           8 :         struct smb2srv_session_close_previous_state *state =
    1085         160 :                 tevent_req_data(req,
    1086             :                 struct smb2srv_session_close_previous_state);
    1087         160 :         struct smbXsrv_connection *conn = state->connection;
    1088           8 :         DATA_BLOB blob;
    1089         160 :         struct security_token *previous_token = NULL;
    1090         160 :         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         160 :         struct tevent_req *subreq = NULL;
    1095           8 :         NTSTATUS status;
    1096         160 :         bool is_free = false;
    1097         160 :         uint32_t seqnum = 0;
    1098             : 
    1099         160 :         smbXsrv_session_global_verify_record(state->db_rec,
    1100             :                                              &is_free,
    1101             :                                              NULL,
    1102             :                                              state,
    1103             :                                              &global,
    1104             :                                              &seqnum);
    1105             : 
    1106         160 :         if (is_free) {
    1107         103 :                 tevent_req_done(req);
    1108         103 :                 return;
    1109             :         }
    1110             : 
    1111          57 :         if (global->auth_session_info == NULL) {
    1112           0 :                 tevent_req_done(req);
    1113           0 :                 return;
    1114             :         }
    1115             : 
    1116          57 :         previous_token = global->auth_session_info->security_token;
    1117             : 
    1118          57 :         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          57 :         if (state->last_seqnum != seqnum) {
    1137          57 :                 state->last_seqnum = seqnum;
    1138          57 :                 dbwrap_watched_watch_remove_instance(state->db_rec,
    1139             :                                                      state->watch_instance);
    1140          57 :                 state->watch_instance =
    1141          57 :                         dbwrap_watched_watch_add_instance(state->db_rec);
    1142             :         }
    1143             : 
    1144          61 :         subreq = dbwrap_watched_watch_send(state, state->ev, state->db_rec,
    1145             :                                            state->watch_instance,
    1146          57 :                                            (struct server_id){0});
    1147          57 :         if (tevent_req_nomem(subreq, req)) {
    1148           0 :                 return;
    1149             :         }
    1150          57 :         tevent_req_set_callback(subreq,
    1151             :                                 smb2srv_session_close_previous_modified,
    1152             :                                 req);
    1153             : 
    1154          57 :         close_info0.old_session_global_id = global->session_global_id;
    1155          57 :         close_info0.old_session_wire_id = global->session_wire_id;
    1156          57 :         close_info0.old_creation_time = global->creation_time;
    1157          57 :         close_info0.new_session_wire_id = state->current_session_id;
    1158             : 
    1159          57 :         ZERO_STRUCT(close_blob);
    1160          57 :         close_blob.version = smbXsrv_version_global_current();
    1161          57 :         close_blob.info.info0 = &close_info0;
    1162             : 
    1163          57 :         ndr_err = ndr_push_struct_blob(&blob, state, &close_blob,
    1164             :                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_closeB);
    1165          57 :         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          57 :         status = messaging_send(conn->client->msg_ctx,
    1177          57 :                                 global->channels[0].server_id,
    1178             :                                 MSG_SMBXSRV_SESSION_CLOSE, &blob);
    1179          57 :         TALLOC_FREE(global);
    1180          57 :         if (tevent_req_nterror(req, status)) {
    1181           0 :                 return;
    1182             :         }
    1183             : 
    1184          57 :         TALLOC_FREE(state->db_rec);
    1185          53 :         return;
    1186             : }
    1187             : 
    1188          57 : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq)
    1189             : {
    1190           4 :         struct tevent_req *req =
    1191          57 :                 tevent_req_callback_data(subreq,
    1192             :                 struct tevent_req);
    1193           4 :         struct smb2srv_session_close_previous_state *state =
    1194          57 :                 tevent_req_data(req,
    1195             :                 struct smb2srv_session_close_previous_state);
    1196           4 :         uint32_t global_id;
    1197           4 :         NTSTATUS status;
    1198          57 :         uint64_t instance = 0;
    1199             : 
    1200          57 :         status = dbwrap_watched_watch_recv(subreq, &instance, NULL, NULL);
    1201          57 :         TALLOC_FREE(subreq);
    1202          57 :         if (tevent_req_nterror(req, status)) {
    1203           0 :                 return;
    1204             :         }
    1205             : 
    1206          57 :         state->watch_instance = instance;
    1207             : 
    1208          57 :         global_id = state->previous_session_id & UINT32_MAX;
    1209             : 
    1210         114 :         state->db_rec = smbXsrv_session_global_fetch_locked(
    1211          57 :                 state->connection->client->session_table->global.db_ctx,
    1212             :                 global_id, state /* TALLOC_CTX */);
    1213          57 :         if (state->db_rec == NULL) {
    1214           0 :                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
    1215           0 :                 return;
    1216             :         }
    1217             : 
    1218          57 :         smb2srv_session_close_previous_check(req);
    1219             : }
    1220             : 
    1221         103 : NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
    1222             : {
    1223           4 :         NTSTATUS status;
    1224             : 
    1225         103 :         if (tevent_req_is_nterror(req, &status)) {
    1226           0 :                 tevent_req_received(req);
    1227           0 :                 return status;
    1228             :         }
    1229             : 
    1230         103 :         tevent_req_received(req);
    1231         103 :         return NT_STATUS_OK;
    1232             : }
    1233             : 
    1234       69323 : static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session)
    1235             : {
    1236        1499 :         NTSTATUS status;
    1237       69323 :         struct smbXsrv_connection *xconn = NULL;
    1238             : 
    1239       69323 :         if (session->client != NULL) {
    1240       36313 :                 xconn = session->client->connections;
    1241             :         }
    1242             : 
    1243      105688 :         for (; xconn != NULL; xconn = xconn->next) {
    1244         750 :                 struct smbd_smb2_request *preq;
    1245             : 
    1246       36422 :                 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
    1247          57 :                         if (preq->session != session) {
    1248           0 :                                 continue;
    1249             :                         }
    1250             : 
    1251          57 :                         preq->session = NULL;
    1252             :                         /*
    1253             :                          * If we no longer have a session we can't
    1254             :                          * sign or encrypt replies.
    1255             :                          */
    1256          57 :                         preq->do_signing = false;
    1257          57 :                         preq->do_encryption = false;
    1258          57 :                         preq->preauth = NULL;
    1259             :                 }
    1260             :         }
    1261             : 
    1262       69323 :         status = smbXsrv_session_logoff(session);
    1263       69323 :         return status;
    1264             : }
    1265             : 
    1266       36588 : static int smbXsrv_session_destructor(struct smbXsrv_session *session)
    1267             : {
    1268         760 :         NTSTATUS status;
    1269             : 
    1270       36588 :         DBG_DEBUG("destructing session(%llu)\n",
    1271             :                   (unsigned long long)session->global->session_wire_id);
    1272             : 
    1273       36588 :         status = smbXsrv_session_clear_and_logoff(session);
    1274       36588 :         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       36588 :         TALLOC_FREE(session->global);
    1281             : 
    1282       36588 :         return 0;
    1283             : }
    1284             : 
    1285       36602 : NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
    1286             :                                 NTTIME now,
    1287             :                                 struct smbXsrv_session **_session)
    1288             : {
    1289       36602 :         struct smbXsrv_session_table *table = conn->client->session_table;
    1290       36602 :         struct db_record *local_rec = NULL;
    1291       36602 :         struct smbXsrv_session *session = NULL;
    1292       36602 :         void *ptr = NULL;
    1293         760 :         TDB_DATA val;
    1294       36602 :         struct smbXsrv_session_global0 *global = NULL;
    1295       36602 :         struct smbXsrv_channel_global0 *channel = NULL;
    1296         760 :         NTSTATUS status;
    1297             : 
    1298       36602 :         if (table->local.num_sessions >= table->local.max_sessions) {
    1299           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
    1300             :         }
    1301             : 
    1302       36602 :         session = talloc_zero(table, struct smbXsrv_session);
    1303       36602 :         if (session == NULL) {
    1304           0 :                 return NT_STATUS_NO_MEMORY;
    1305             :         }
    1306       36602 :         session->table = table;
    1307       36602 :         session->idle_time = now;
    1308       36602 :         session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
    1309       36602 :         session->client = conn->client;
    1310       36602 :         session->homes_snum = -1;
    1311             : 
    1312       36602 :         status = smbXsrv_session_global_allocate(table->global.db_ctx,
    1313             :                                                  session,
    1314             :                                                  &global);
    1315       36602 :         if (!NT_STATUS_IS_OK(status)) {
    1316           0 :                 TALLOC_FREE(session);
    1317           0 :                 return status;
    1318             :         }
    1319       36602 :         session->global = global;
    1320             : 
    1321       36602 :         if (conn->protocol >= PROTOCOL_SMB2_02) {
    1322       29480 :                 uint64_t id = global->session_global_id;
    1323             : 
    1324       29480 :                 global->connection_dialect = conn->smb2.server.dialect;
    1325       29480 :                 global->client_guid = conn->smb2.client.guid;
    1326             : 
    1327       29480 :                 global->session_wire_id = id;
    1328             : 
    1329       29480 :                 status = smb2srv_tcon_table_init(session);
    1330       29480 :                 if (!NT_STATUS_IS_OK(status)) {
    1331           0 :                         TALLOC_FREE(session);
    1332           0 :                         return status;
    1333             :                 }
    1334             : 
    1335       29480 :                 session->local_id = global->session_global_id;
    1336             : 
    1337       29480 :                 local_rec = smbXsrv_session_local_fetch_locked(
    1338             :                                                 table->local.db_ctx,
    1339             :                                                 session->local_id,
    1340             :                                                 session /* TALLOC_CTX */);
    1341       29480 :                 if (local_rec == NULL) {
    1342           0 :                         TALLOC_FREE(session);
    1343           0 :                         return NT_STATUS_NO_MEMORY;
    1344             :                 }
    1345             : 
    1346       29480 :                 val = dbwrap_record_get_value(local_rec);
    1347       29480 :                 if (val.dsize != 0) {
    1348           0 :                         TALLOC_FREE(session);
    1349           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1350             :                 }
    1351             :         } else {
    1352             : 
    1353        7122 :                 status = smb1srv_session_local_allocate_id(table->local.db_ctx,
    1354             :                                                         table->local.lowest_id,
    1355             :                                                         table->local.highest_id,
    1356             :                                                         session,
    1357             :                                                         &local_rec,
    1358             :                                                         &session->local_id);
    1359        7122 :                 if (!NT_STATUS_IS_OK(status)) {
    1360           0 :                         TALLOC_FREE(session);
    1361           0 :                         return status;
    1362             :                 }
    1363             : 
    1364        7122 :                 global->session_wire_id = session->local_id;
    1365             :         }
    1366             : 
    1367       36602 :         global->creation_time = now;
    1368       36602 :         global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
    1369             : 
    1370       36602 :         status = smbXsrv_session_add_channel(session, conn, now, &channel);
    1371       36602 :         if (!NT_STATUS_IS_OK(status)) {
    1372           0 :                 TALLOC_FREE(session);
    1373           0 :                 return status;
    1374             :         }
    1375             : 
    1376       36602 :         ptr = session;
    1377       36602 :         val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
    1378       36602 :         status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
    1379       36602 :         TALLOC_FREE(local_rec);
    1380       36602 :         if (!NT_STATUS_IS_OK(status)) {
    1381           0 :                 TALLOC_FREE(session);
    1382           0 :                 return status;
    1383             :         }
    1384       36602 :         table->local.num_sessions += 1;
    1385             : 
    1386       36602 :         talloc_set_destructor(session, smbXsrv_session_destructor);
    1387             : 
    1388       36602 :         status = smbXsrv_session_global_store(global);
    1389       36602 :         if (!NT_STATUS_IS_OK(status)) {
    1390           0 :                 DBG_ERR("smbXsrv_session_create: "
    1391             :                          "global_id (0x%08x) store failed - %s\n",
    1392             :                          session->global->session_global_id,
    1393             :                          nt_errstr(status));
    1394           0 :                 TALLOC_FREE(session);
    1395           0 :                 return status;
    1396             :         }
    1397             : 
    1398       36602 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
    1399           0 :                 struct smbXsrv_sessionB session_blob = {
    1400             :                         .version = SMBXSRV_VERSION_0,
    1401             :                         .info.info0 = session,
    1402             :                 };
    1403             : 
    1404           0 :                 DBG_DEBUG("smbXsrv_session_create: global_id (0x%08x) stored\n",
    1405             :                          session->global->session_global_id);
    1406           0 :                 NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
    1407             :         }
    1408             : 
    1409       36602 :         *_session = session;
    1410       36602 :         return NT_STATUS_OK;
    1411             : }
    1412             : 
    1413       37512 : NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
    1414             :                                      struct smbXsrv_connection *conn,
    1415             :                                      NTTIME now,
    1416             :                                      struct smbXsrv_channel_global0 **_c)
    1417             : {
    1418       37512 :         struct smbXsrv_session_global0 *global = session->global;
    1419       37512 :         struct smbXsrv_channel_global0 *c = NULL;
    1420             : 
    1421       37512 :         if (global->num_channels > 31) {
    1422             :                 /*
    1423             :                  * Windows allow up to 32 channels
    1424             :                  */
    1425           4 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
    1426             :         }
    1427             : 
    1428       37508 :         c = talloc_realloc(global,
    1429             :                            global->channels,
    1430             :                            struct smbXsrv_channel_global0,
    1431             :                            global->num_channels + 1);
    1432       37508 :         if (c == NULL) {
    1433           0 :                 return NT_STATUS_NO_MEMORY;
    1434             :         }
    1435       37508 :         global->channels = c;
    1436             : 
    1437       37508 :         c = &global->channels[global->num_channels];
    1438       37508 :         ZERO_STRUCTP(c);
    1439             : 
    1440       37508 :         c->server_id = messaging_server_id(conn->client->msg_ctx);
    1441       37508 :         c->channel_id = conn->channel_id;
    1442       37508 :         c->creation_time = now;
    1443       75016 :         c->local_address = tsocket_address_string(conn->local_address,
    1444       37508 :                                                   global->channels);
    1445       37508 :         if (c->local_address == NULL) {
    1446           0 :                 return NT_STATUS_NO_MEMORY;
    1447             :         }
    1448       75016 :         c->remote_address = tsocket_address_string(conn->remote_address,
    1449       37508 :                                                    global->channels);
    1450       37508 :         if (c->remote_address == NULL) {
    1451           0 :                 return NT_STATUS_NO_MEMORY;
    1452             :         }
    1453       37508 :         c->remote_name = talloc_strdup(global->channels,
    1454             :                                        conn->remote_hostname);
    1455       37508 :         if (c->remote_name == NULL) {
    1456           0 :                 return NT_STATUS_NO_MEMORY;
    1457             :         }
    1458       37508 :         c->connection = conn;
    1459             : 
    1460       37508 :         global->num_channels += 1;
    1461             : 
    1462       37508 :         *_c = c;
    1463       37508 :         return NT_STATUS_OK;
    1464             : }
    1465             : 
    1466      152014 : NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session)
    1467             : {
    1468      152014 :         struct smbXsrv_session_table *table = session->table;
    1469        2567 :         NTSTATUS status;
    1470             : 
    1471      152014 :         if (session->global->db_rec != NULL) {
    1472           0 :                 DBG_ERR("smbXsrv_session_update(0x%08x): "
    1473             :                           "Called with db_rec != NULL'\n",
    1474             :                           session->global->session_global_id);
    1475           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1476             :         }
    1477             : 
    1478      152014 :         if (table == NULL) {
    1479           0 :                 DBG_ERR("smbXsrv_session_update(0x%08x): "
    1480             :                           "Called with table == NULL'\n",
    1481             :                           session->global->session_global_id);
    1482           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1483             :         }
    1484             : 
    1485      301461 :         session->global->db_rec = smbXsrv_session_global_fetch_locked(
    1486             :                                         table->global.db_ctx,
    1487      149447 :                                         session->global->session_global_id,
    1488      149447 :                                         session->global /* TALLOC_CTX */);
    1489      152014 :         if (session->global->db_rec == NULL) {
    1490           0 :                 return NT_STATUS_INTERNAL_DB_ERROR;
    1491             :         }
    1492             : 
    1493      152014 :         status = smbXsrv_session_global_store(session->global);
    1494      152014 :         if (!NT_STATUS_IS_OK(status)) {
    1495           0 :                 DBG_ERR("smbXsrv_session_update: "
    1496             :                          "global_id (0x%08x) store failed - %s\n",
    1497             :                          session->global->session_global_id,
    1498             :                          nt_errstr(status));
    1499           0 :                 return status;
    1500             :         }
    1501             : 
    1502      152014 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
    1503           0 :                 struct smbXsrv_sessionB session_blob = {
    1504             :                         .version = SMBXSRV_VERSION_0,
    1505             :                         .info.info0 = session,
    1506             :                 };
    1507             : 
    1508           0 :                 DBG_DEBUG("smbXsrv_session_update: global_id (0x%08x) stored\n",
    1509             :                           session->global->session_global_id);
    1510           0 :                 NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
    1511             :         }
    1512             : 
    1513      152014 :         return NT_STATUS_OK;
    1514             : }
    1515             : 
    1516     3706315 : NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
    1517             :                                       const struct smbXsrv_connection *conn,
    1518             :                                       struct smbXsrv_channel_global0 **_c)
    1519             : {
    1520       39383 :         uint32_t i;
    1521             : 
    1522     3785689 :         for (i=0; i < session->global->num_channels; i++) {
    1523     3779613 :                 struct smbXsrv_channel_global0 *c = &session->global->channels[i];
    1524             : 
    1525     3779613 :                 if (c->channel_id != conn->channel_id) {
    1526       79374 :                         continue;
    1527             :                 }
    1528             : 
    1529     3700239 :                 if (c->connection != conn) {
    1530           0 :                         continue;
    1531             :                 }
    1532             : 
    1533     3700239 :                 *_c = c;
    1534     3700239 :                 return NT_STATUS_OK;
    1535             :         }
    1536             : 
    1537        6076 :         return NT_STATUS_USER_SESSION_DELETED;
    1538             : }
    1539             : 
    1540      106771 : NTSTATUS smbXsrv_session_find_auth(const struct smbXsrv_session *session,
    1541             :                                    const struct smbXsrv_connection *conn,
    1542             :                                    NTTIME now,
    1543             :                                    struct smbXsrv_session_auth0 **_a)
    1544             : {
    1545        1980 :         struct smbXsrv_session_auth0 *a;
    1546             : 
    1547      106771 :         for (a = session->pending_auth; a != NULL; a = a->next) {
    1548       29519 :                 if (a->channel_id != conn->channel_id) {
    1549           0 :                         continue;
    1550             :                 }
    1551             : 
    1552       29519 :                 if (a->connection == conn) {
    1553       29519 :                         if (now != 0) {
    1554       29501 :                                 a->idle_time = now;
    1555             :                         }
    1556       29519 :                         *_a = a;
    1557       29519 :                         return NT_STATUS_OK;
    1558             :                 }
    1559             :         }
    1560             : 
    1561       77252 :         return NT_STATUS_USER_SESSION_DELETED;
    1562             : }
    1563             : 
    1564       37628 : static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0 *a)
    1565             : {
    1566       37628 :         if (a->session == NULL) {
    1567          14 :                 return 0;
    1568             :         }
    1569             : 
    1570       37610 :         DLIST_REMOVE(a->session->pending_auth, a);
    1571       37610 :         a->session = NULL;
    1572       37610 :         return 0;
    1573             : }
    1574             : 
    1575       37622 : NTSTATUS smbXsrv_session_create_auth(struct smbXsrv_session *session,
    1576             :                                      struct smbXsrv_connection *conn,
    1577             :                                      NTTIME now,
    1578             :                                      uint8_t in_flags,
    1579             :                                      uint8_t in_security_mode,
    1580             :                                      struct smbXsrv_session_auth0 **_a)
    1581             : {
    1582         811 :         struct smbXsrv_session_auth0 *a;
    1583         811 :         NTSTATUS status;
    1584             : 
    1585       37622 :         status = smbXsrv_session_find_auth(session, conn, 0, &a);
    1586       37622 :         if (NT_STATUS_IS_OK(status)) {
    1587           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1588             :         }
    1589             : 
    1590       37622 :         a = talloc_zero(session, struct smbXsrv_session_auth0);
    1591       37622 :         if (a == NULL) {
    1592           0 :                 return NT_STATUS_NO_MEMORY;
    1593             :         }
    1594       37622 :         a->session = session;
    1595       37622 :         a->connection = conn;
    1596       37622 :         a->in_flags = in_flags;
    1597       37622 :         a->in_security_mode = in_security_mode;
    1598       37622 :         a->creation_time = now;
    1599       37622 :         a->idle_time = now;
    1600       37622 :         a->channel_id = conn->channel_id;
    1601             : 
    1602       37622 :         if (conn->protocol >= PROTOCOL_SMB3_11) {
    1603       27964 :                 a->preauth = talloc(a, struct smbXsrv_preauth);
    1604       27964 :                 if (a->preauth == NULL) {
    1605           0 :                         TALLOC_FREE(session);
    1606           0 :                         return NT_STATUS_NO_MEMORY;
    1607             :                 }
    1608       27964 :                 *a->preauth = conn->smb2.preauth;
    1609             :         }
    1610             : 
    1611       37622 :         talloc_set_destructor(a, smbXsrv_session_auth0_destructor);
    1612       37622 :         DLIST_ADD_END(session->pending_auth, a);
    1613             : 
    1614       37622 :         *_a = a;
    1615       37622 :         return NT_STATUS_OK;
    1616             : }
    1617             : 
    1618             : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq);
    1619             : 
    1620        2026 : NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session,
    1621             :                                         struct smbXsrv_connection *xconn)
    1622             : {
    1623        2026 :         struct smbXsrv_session_auth0 *a = NULL;
    1624        2026 :         struct smbXsrv_channel_global0 *c = NULL;
    1625         210 :         NTSTATUS status;
    1626        2026 :         bool need_update = false;
    1627             : 
    1628        2026 :         status = smbXsrv_session_find_auth(session, xconn, 0, &a);
    1629        2026 :         if (!NT_STATUS_IS_OK(status)) {
    1630        2008 :                 a = NULL;
    1631             :         }
    1632        2026 :         status = smbXsrv_session_find_channel(session, xconn, &c);
    1633        2026 :         if (!NT_STATUS_IS_OK(status)) {
    1634        1086 :                 c = NULL;
    1635             :         }
    1636             : 
    1637        2026 :         if (a != NULL) {
    1638          18 :                 smbXsrv_session_auth0_destructor(a);
    1639          18 :                 a->connection = NULL;
    1640          18 :                 need_update = true;
    1641             :         }
    1642             : 
    1643        2026 :         if (c != NULL) {
    1644         940 :                 struct smbXsrv_session_global0 *global = session->global;
    1645          24 :                 ptrdiff_t n;
    1646             : 
    1647         940 :                 n = (c - global->channels);
    1648         940 :                 if (n >= global->num_channels || n < 0) {
    1649           0 :                         return NT_STATUS_INTERNAL_ERROR;
    1650             :                 }
    1651         940 :                 ARRAY_DEL_ELEMENT(global->channels, n, global->num_channels);
    1652         940 :                 global->num_channels--;
    1653         940 :                 if (global->num_channels == 0) {
    1654          44 :                         struct smbXsrv_client *client = session->client;
    1655          44 :                         struct tevent_queue *xconn_wait_queue =
    1656             :                                 xconn->transport.shutdown_wait_queue;
    1657          44 :                         struct tevent_req *subreq = NULL;
    1658             : 
    1659             :                         /*
    1660             :                          * Let the connection wait until the session is
    1661             :                          * destroyed.
    1662             :                          *
    1663             :                          * We don't set a callback, as we just want to block the
    1664             :                          * wait queue and the talloc_free() of the session will
    1665             :                          * remove the item from the wait queue in order
    1666             :                          * to remove allow the connection to disappear.
    1667             :                          */
    1668          44 :                         if (xconn_wait_queue != NULL) {
    1669          44 :                                 subreq = tevent_queue_wait_send(session,
    1670             :                                                                 client->raw_ev_ctx,
    1671             :                                                                 xconn_wait_queue);
    1672          44 :                                 if (subreq == NULL) {
    1673           0 :                                         status = NT_STATUS_NO_MEMORY;
    1674           0 :                                         DBG_ERR("tevent_queue_wait_send() session(%llu) failed: %s\n",
    1675             :                                                 (unsigned long long)session->global->session_wire_id,
    1676             :                                                 nt_errstr(status));
    1677           0 :                                         return status;
    1678             :                                 }
    1679             :                         }
    1680             : 
    1681             :                         /*
    1682             :                          * This is guaranteed to set
    1683             :                          * session->status = NT_STATUS_USER_SESSION_DELETED
    1684             :                          * even if NULL is returned.
    1685             :                          */
    1686          44 :                         subreq = smb2srv_session_shutdown_send(session,
    1687             :                                                                client->raw_ev_ctx,
    1688             :                                                                session,
    1689             :                                                                NULL);
    1690          44 :                         if (subreq == NULL) {
    1691           0 :                                 status = NT_STATUS_NO_MEMORY;
    1692           0 :                                 DBG_ERR("smb2srv_session_shutdown_send(%llu) failed: %s\n",
    1693             :                                         (unsigned long long)session->global->session_wire_id,
    1694             :                                         nt_errstr(status));
    1695           0 :                                 return status;
    1696             :                         }
    1697          44 :                         tevent_req_set_callback(subreq,
    1698             :                                                 smbXsrv_session_remove_channel_done,
    1699             :                                                 session);
    1700             :                 }
    1701         916 :                 need_update = true;
    1702             :         }
    1703             : 
    1704        2002 :         if (!need_update) {
    1705        1086 :                 return NT_STATUS_OK;
    1706             :         }
    1707             : 
    1708         940 :         return smbXsrv_session_update(session);
    1709             : }
    1710             : 
    1711          44 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq)
    1712             : {
    1713           4 :         struct smbXsrv_session *session =
    1714          44 :                 tevent_req_callback_data(subreq,
    1715             :                 struct smbXsrv_session);
    1716           4 :         NTSTATUS status;
    1717             : 
    1718          44 :         status = smb2srv_session_shutdown_recv(subreq);
    1719          44 :         TALLOC_FREE(subreq);
    1720          44 :         if (!NT_STATUS_IS_OK(status)) {
    1721           0 :                 DBG_ERR("smb2srv_session_shutdown_recv(%llu) failed: %s\n",
    1722             :                         (unsigned long long)session->global->session_wire_id,
    1723             :                         nt_errstr(status));
    1724             :         }
    1725             : 
    1726          44 :         status = smbXsrv_session_logoff(session);
    1727          44 :         if (!NT_STATUS_IS_OK(status)) {
    1728           0 :                 DBG_ERR("smbXsrv_session_logoff(%llu) failed: %s\n",
    1729             :                         (unsigned long long)session->global->session_wire_id,
    1730             :                         nt_errstr(status));
    1731             :         }
    1732             : 
    1733          44 :         TALLOC_FREE(session);
    1734          44 : }
    1735             : 
    1736             : struct smb2srv_session_shutdown_state {
    1737             :         struct tevent_queue *wait_queue;
    1738             : };
    1739             : 
    1740             : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
    1741             : 
    1742        2472 : struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
    1743             :                                         struct tevent_context *ev,
    1744             :                                         struct smbXsrv_session *session,
    1745             :                                         struct smbd_smb2_request *current_req)
    1746             : {
    1747          21 :         struct tevent_req *req;
    1748          21 :         struct smb2srv_session_shutdown_state *state;
    1749          21 :         struct tevent_req *subreq;
    1750        2472 :         struct smbXsrv_connection *xconn = NULL;
    1751        2472 :         size_t len = 0;
    1752             : 
    1753             :         /*
    1754             :          * Make sure that no new request will be able to use this session.
    1755             :          */
    1756        2472 :         session->status = NT_STATUS_USER_SESSION_DELETED;
    1757             : 
    1758        2472 :         req = tevent_req_create(mem_ctx, &state,
    1759             :                                 struct smb2srv_session_shutdown_state);
    1760        2472 :         if (req == NULL) {
    1761           0 :                 return NULL;
    1762             :         }
    1763             : 
    1764        2472 :         state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
    1765        2472 :         if (tevent_req_nomem(state->wait_queue, req)) {
    1766           0 :                 return tevent_req_post(req, ev);
    1767             :         }
    1768             : 
    1769        5034 :         for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
    1770          33 :                 struct smbd_smb2_request *preq;
    1771             : 
    1772        4973 :                 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
    1773        2411 :                         if (preq == current_req) {
    1774             :                                 /* Can't cancel current request. */
    1775        2373 :                                 continue;
    1776             :                         }
    1777          38 :                         if (preq->session != session) {
    1778             :                                 /* Request on different session. */
    1779          26 :                                 continue;
    1780             :                         }
    1781             : 
    1782          12 :                         if (preq->subreq != NULL) {
    1783          12 :                                 tevent_req_cancel(preq->subreq);
    1784             :                         }
    1785             : 
    1786             :                         /*
    1787             :                          * Now wait until the request is finished.
    1788             :                          *
    1789             :                          * We don't set a callback, as we just want to block the
    1790             :                          * wait queue and the talloc_free() of the request will
    1791             :                          * remove the item from the wait queue.
    1792             :                          */
    1793          12 :                         subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
    1794          12 :                         if (tevent_req_nomem(subreq, req)) {
    1795           0 :                                 return tevent_req_post(req, ev);
    1796             :                         }
    1797             :                 }
    1798             :         }
    1799             : 
    1800        2472 :         len = tevent_queue_length(state->wait_queue);
    1801        2472 :         if (len == 0) {
    1802        2460 :                 tevent_req_done(req);
    1803        2460 :                 return tevent_req_post(req, ev);
    1804             :         }
    1805             : 
    1806             :         /*
    1807             :          * Now we add our own waiter to the end of the queue,
    1808             :          * this way we get notified when all pending requests are finished
    1809             :          * and send to the socket.
    1810             :          */
    1811          12 :         subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
    1812          12 :         if (tevent_req_nomem(subreq, req)) {
    1813           0 :                 return tevent_req_post(req, ev);
    1814             :         }
    1815          12 :         tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
    1816             : 
    1817          12 :         return req;
    1818             : }
    1819             : 
    1820          12 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
    1821             : {
    1822           0 :         struct tevent_req *req =
    1823          12 :                 tevent_req_callback_data(subreq,
    1824             :                 struct tevent_req);
    1825             : 
    1826          12 :         tevent_queue_wait_recv(subreq);
    1827          12 :         TALLOC_FREE(subreq);
    1828             : 
    1829          12 :         tevent_req_done(req);
    1830          12 : }
    1831             : 
    1832        2472 : NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
    1833             : {
    1834        2472 :         return tevent_req_simple_recv_ntstatus(req);
    1835             : }
    1836             : 
    1837       69598 : NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
    1838             : {
    1839        1513 :         struct smbXsrv_session_table *table;
    1840       69598 :         struct db_record *local_rec = NULL;
    1841       69598 :         struct db_record *global_rec = NULL;
    1842       69598 :         struct smbd_server_connection *sconn = NULL;
    1843        1513 :         NTSTATUS status;
    1844       69598 :         NTSTATUS error = NT_STATUS_OK;
    1845             : 
    1846       69598 :         if (session->table == NULL) {
    1847       33010 :                 return NT_STATUS_OK;
    1848             :         }
    1849             : 
    1850       36588 :         table = session->table;
    1851       36588 :         session->table = NULL;
    1852             : 
    1853       36588 :         sconn = session->client->sconn;
    1854       36588 :         session->client = NULL;
    1855       36588 :         session->status = NT_STATUS_USER_SESSION_DELETED;
    1856             : 
    1857             :         /*
    1858             :          * For SMB2 this is a bit redundant as files are also close
    1859             :          * below via smb2srv_tcon_disconnect_all() -> ... ->
    1860             :          * smbXsrv_tcon_disconnect() -> close_cnum() ->
    1861             :          * file_close_conn().
    1862             :          */
    1863       36588 :         file_close_user(sconn, session->global->session_wire_id);
    1864             : 
    1865       36588 :         if (session->tcon_table != NULL) {
    1866             :                 /*
    1867             :                  * Note: We only have a tcon_table for SMB2.
    1868             :                  */
    1869       29478 :                 status = smb2srv_tcon_disconnect_all(session);
    1870       29478 :                 if (!NT_STATUS_IS_OK(status)) {
    1871          54 :                         DBG_ERR("smbXsrv_session_logoff(0x%08x): "
    1872             :                                   "smb2srv_tcon_disconnect_all() failed: %s\n",
    1873             :                                   session->global->session_global_id,
    1874             :                                   nt_errstr(status));
    1875          54 :                         error = status;
    1876             :                 }
    1877             :         }
    1878             : 
    1879       36588 :         invalidate_vuid(sconn, session->global->session_wire_id);
    1880             : 
    1881       36588 :         global_rec = session->global->db_rec;
    1882       36588 :         session->global->db_rec = NULL;
    1883       36588 :         if (global_rec == NULL) {
    1884       36588 :                 global_rec = smbXsrv_session_global_fetch_locked(
    1885             :                                         table->global.db_ctx,
    1886       35828 :                                         session->global->session_global_id,
    1887       35828 :                                         session->global /* TALLOC_CTX */);
    1888       36588 :                 if (global_rec == NULL) {
    1889           0 :                         error = NT_STATUS_INTERNAL_ERROR;
    1890             :                 }
    1891             :         }
    1892             : 
    1893       36588 :         if (global_rec != NULL) {
    1894       36588 :                 status = dbwrap_record_delete(global_rec);
    1895       36588 :                 if (!NT_STATUS_IS_OK(status)) {
    1896           0 :                         TDB_DATA key = dbwrap_record_get_key(global_rec);
    1897             : 
    1898           0 :                         DBG_ERR("smbXsrv_session_logoff(0x%08x): "
    1899             :                                   "failed to delete global key '%s': %s\n",
    1900             :                                   session->global->session_global_id,
    1901             :                                   tdb_data_dbg(key),
    1902             :                                   nt_errstr(status));
    1903           0 :                         error = status;
    1904             :                 }
    1905             :         }
    1906       36588 :         TALLOC_FREE(global_rec);
    1907             : 
    1908       36588 :         local_rec = session->db_rec;
    1909       36588 :         if (local_rec == NULL) {
    1910        3853 :                 local_rec = smbXsrv_session_local_fetch_locked(
    1911             :                                                 table->local.db_ctx,
    1912             :                                                 session->local_id,
    1913             :                                                 session /* TALLOC_CTX */);
    1914        3853 :                 if (local_rec == NULL) {
    1915           0 :                         error = NT_STATUS_INTERNAL_ERROR;
    1916             :                 }
    1917             :         }
    1918             : 
    1919       36588 :         if (local_rec != NULL) {
    1920       36588 :                 status = dbwrap_record_delete(local_rec);
    1921       36588 :                 if (!NT_STATUS_IS_OK(status)) {
    1922           0 :                         TDB_DATA key = dbwrap_record_get_key(local_rec);
    1923             : 
    1924           0 :                         DBG_ERR("smbXsrv_session_logoff(0x%08x): "
    1925             :                                   "failed to delete local key '%s': %s\n",
    1926             :                                   session->global->session_global_id,
    1927             :                                   tdb_data_dbg(key),
    1928             :                                   nt_errstr(status));
    1929           0 :                         error = status;
    1930             :                 }
    1931       36588 :                 table->local.num_sessions -= 1;
    1932             :         }
    1933       36588 :         if (session->db_rec == NULL) {
    1934        3853 :                 TALLOC_FREE(local_rec);
    1935             :         }
    1936       36588 :         session->db_rec = NULL;
    1937             : 
    1938       36588 :         return error;
    1939             : }
    1940             : 
    1941             : struct smbXsrv_session_logoff_all_state {
    1942             :         NTSTATUS first_status;
    1943             :         int errors;
    1944             : };
    1945             : 
    1946             : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
    1947             :                                                void *private_data);
    1948             : 
    1949       35381 : NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_client *client)
    1950             : {
    1951       35381 :         struct smbXsrv_session_table *table = client->session_table;
    1952         842 :         struct smbXsrv_session_logoff_all_state state;
    1953         842 :         NTSTATUS status;
    1954       35381 :         int count = 0;
    1955             : 
    1956       35381 :         if (table == NULL) {
    1957         702 :                 DBG_DEBUG("smbXsrv_session_logoff_all: "
    1958             :                            "empty session_table, nothing to do.\n");
    1959         702 :                 return NT_STATUS_OK;
    1960             :         }
    1961             : 
    1962       34679 :         ZERO_STRUCT(state);
    1963             : 
    1964       34679 :         status = dbwrap_traverse(table->local.db_ctx,
    1965             :                                  smbXsrv_session_logoff_all_callback,
    1966             :                                  &state, &count);
    1967       34679 :         if (!NT_STATUS_IS_OK(status)) {
    1968           0 :                 DBG_ERR("smbXsrv_session_logoff_all: "
    1969             :                           "dbwrap_traverse() failed: %s\n",
    1970             :                           nt_errstr(status));
    1971           0 :                 return status;
    1972             :         }
    1973             : 
    1974       34679 :         if (!NT_STATUS_IS_OK(state.first_status)) {
    1975          52 :                 DBG_ERR("smbXsrv_session_logoff_all: "
    1976             :                           "count[%d] errors[%d] first[%s]\n",
    1977             :                           count, state.errors,
    1978             :                           nt_errstr(state.first_status));
    1979          52 :                 return state.first_status;
    1980             :         }
    1981             : 
    1982       34627 :         return NT_STATUS_OK;
    1983             : }
    1984             : 
    1985       32735 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
    1986             :                                                void *private_data)
    1987             : {
    1988       32735 :         struct smbXsrv_session_logoff_all_state *state =
    1989             :                 (struct smbXsrv_session_logoff_all_state *)private_data;
    1990         739 :         TDB_DATA val;
    1991       32735 :         void *ptr = NULL;
    1992       32735 :         struct smbXsrv_session *session = NULL;
    1993         739 :         NTSTATUS status;
    1994             : 
    1995       32735 :         val = dbwrap_record_get_value(local_rec);
    1996       32735 :         if (val.dsize != sizeof(ptr)) {
    1997           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    1998           0 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    1999           0 :                         state->first_status = status;
    2000             :                 }
    2001           0 :                 state->errors++;
    2002           0 :                 return 0;
    2003             :         }
    2004             : 
    2005       32735 :         memcpy(&ptr, val.dptr, val.dsize);
    2006       32735 :         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
    2007             : 
    2008       32735 :         session->db_rec = local_rec;
    2009       32735 :         status = smbXsrv_session_clear_and_logoff(session);
    2010       32735 :         session->db_rec = NULL;
    2011       32735 :         if (!NT_STATUS_IS_OK(status)) {
    2012          54 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    2013          52 :                         state->first_status = status;
    2014             :                 }
    2015          54 :                 state->errors++;
    2016          54 :                 return 0;
    2017             :         }
    2018             : 
    2019       31942 :         return 0;
    2020             : }
    2021             : 
    2022             : struct smbXsrv_session_local_trav_state {
    2023             :         NTSTATUS status;
    2024             :         int (*caller_cb)(struct smbXsrv_session *session,
    2025             :                          void *caller_data);
    2026             :         void *caller_data;
    2027             : };
    2028             : 
    2029             : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
    2030             :                                              void *private_data);
    2031             : 
    2032           0 : NTSTATUS smbXsrv_session_local_traverse(
    2033             :         struct smbXsrv_client *client,
    2034             :         int (*caller_cb)(struct smbXsrv_session *session,
    2035             :                          void *caller_data),
    2036             :         void *caller_data)
    2037             : {
    2038           0 :         struct smbXsrv_session_table *table = client->session_table;
    2039           0 :         struct smbXsrv_session_local_trav_state state;
    2040           0 :         NTSTATUS status;
    2041           0 :         int count = 0;
    2042             : 
    2043           0 :         state = (struct smbXsrv_session_local_trav_state) {
    2044             :                 .status = NT_STATUS_OK,
    2045             :                 .caller_cb = caller_cb,
    2046             :                 .caller_data = caller_data,
    2047             :         };
    2048             : 
    2049           0 :         if (table == NULL) {
    2050           0 :                 DBG_DEBUG("empty session_table, nothing to do.\n");
    2051           0 :                 return NT_STATUS_OK;
    2052             :         }
    2053             : 
    2054           0 :         status = dbwrap_traverse(table->local.db_ctx,
    2055             :                                  smbXsrv_session_local_traverse_cb,
    2056             :                                  &state,
    2057             :                                  &count);
    2058           0 :         if (!NT_STATUS_IS_OK(status)) {
    2059           0 :                 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
    2060           0 :                 return status;
    2061             :         }
    2062           0 :         if (!NT_STATUS_IS_OK(state.status)) {
    2063           0 :                 DBG_ERR("count[%d] status[%s]\n",
    2064             :                         count, nt_errstr(state.status));
    2065           0 :                 return state.status;
    2066             :         }
    2067             : 
    2068           0 :         return NT_STATUS_OK;
    2069             : }
    2070             : 
    2071           0 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
    2072             :                                              void *private_data)
    2073             : {
    2074           0 :         struct smbXsrv_session_local_trav_state *state =
    2075             :                 (struct smbXsrv_session_local_trav_state *)private_data;
    2076           0 :         TDB_DATA val;
    2077           0 :         void *ptr = NULL;
    2078           0 :         struct smbXsrv_session *session = NULL;
    2079           0 :         int ret;
    2080             : 
    2081           0 :         val = dbwrap_record_get_value(local_rec);
    2082           0 :         if (val.dsize != sizeof(ptr)) {
    2083           0 :                 state->status = NT_STATUS_INTERNAL_ERROR;
    2084           0 :                 return -1;
    2085             :         }
    2086             : 
    2087           0 :         memcpy(&ptr, val.dptr, val.dsize);
    2088           0 :         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
    2089             : 
    2090           0 :         session->db_rec = local_rec;
    2091           0 :         ret = state->caller_cb(session, state->caller_data);
    2092           0 :         session->db_rec = NULL;
    2093             : 
    2094           0 :         return ret;
    2095             : }
    2096             : 
    2097             : struct smbXsrv_session_disconnect_xconn_state {
    2098             :         struct smbXsrv_connection *xconn;
    2099             :         NTSTATUS first_status;
    2100             :         int errors;
    2101             : };
    2102             : 
    2103             : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
    2104             :                                                void *private_data);
    2105             : 
    2106        1106 : NTSTATUS smbXsrv_session_disconnect_xconn(struct smbXsrv_connection *xconn)
    2107             : {
    2108        1106 :         struct smbXsrv_client *client = xconn->client;
    2109        1106 :         struct smbXsrv_session_table *table = client->session_table;
    2110          52 :         struct smbXsrv_session_disconnect_xconn_state state;
    2111          52 :         NTSTATUS status;
    2112        1106 :         int count = 0;
    2113             : 
    2114        1106 :         if (table == NULL) {
    2115           0 :                 DBG_ERR("empty session_table, nothing to do.\n");
    2116           0 :                 return NT_STATUS_OK;
    2117             :         }
    2118             : 
    2119        1106 :         ZERO_STRUCT(state);
    2120        1106 :         state.xconn = xconn;
    2121             : 
    2122        1106 :         status = dbwrap_traverse(table->local.db_ctx,
    2123             :                                  smbXsrv_session_disconnect_xconn_callback,
    2124             :                                  &state, &count);
    2125        1106 :         if (!NT_STATUS_IS_OK(status)) {
    2126           0 :                 DBG_ERR("dbwrap_traverse() failed: %s\n",
    2127             :                         nt_errstr(status));
    2128           0 :                 return status;
    2129             :         }
    2130             : 
    2131        1106 :         if (!NT_STATUS_IS_OK(state.first_status)) {
    2132           0 :                 DBG_ERR("count[%d] errors[%d] first[%s]\n",
    2133             :                         count, state.errors,
    2134             :                         nt_errstr(state.first_status));
    2135           0 :                 return state.first_status;
    2136             :         }
    2137             : 
    2138        1106 :         return NT_STATUS_OK;
    2139             : }
    2140             : 
    2141        1184 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
    2142             :                                                void *private_data)
    2143             : {
    2144        1184 :         struct smbXsrv_session_disconnect_xconn_state *state =
    2145             :                 (struct smbXsrv_session_disconnect_xconn_state *)private_data;
    2146          62 :         TDB_DATA val;
    2147        1184 :         void *ptr = NULL;
    2148        1184 :         struct smbXsrv_session *session = NULL;
    2149          62 :         NTSTATUS status;
    2150             : 
    2151        1184 :         val = dbwrap_record_get_value(local_rec);
    2152        1184 :         if (val.dsize != sizeof(ptr)) {
    2153           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    2154           0 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    2155           0 :                         state->first_status = status;
    2156             :                 }
    2157           0 :                 state->errors++;
    2158           0 :                 return 0;
    2159             :         }
    2160             : 
    2161        1184 :         memcpy(&ptr, val.dptr, val.dsize);
    2162        1184 :         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
    2163             : 
    2164        1184 :         session->db_rec = local_rec;
    2165        1184 :         status = smbXsrv_session_remove_channel(session, state->xconn);
    2166        1184 :         session->db_rec = NULL;
    2167        1184 :         if (!NT_STATUS_IS_OK(status)) {
    2168           0 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    2169           0 :                         state->first_status = status;
    2170             :                 }
    2171           0 :                 state->errors++;
    2172             :         }
    2173             : 
    2174        1122 :         return 0;
    2175             : }
    2176             : 
    2177        5780 : NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn)
    2178             : {
    2179             :         /*
    2180             :          * Allow a range from 1..65534 with 65534 values.
    2181             :          */
    2182        5780 :         return smbXsrv_session_table_init(conn, 1, UINT16_MAX - 1,
    2183             :                                           UINT16_MAX - 1);
    2184             : }
    2185             : 
    2186      675569 : NTSTATUS smb1srv_session_lookup(struct smbXsrv_connection *conn,
    2187             :                                 uint16_t vuid, NTTIME now,
    2188             :                                 struct smbXsrv_session **session)
    2189             : {
    2190      675569 :         struct smbXsrv_session_table *table = conn->client->session_table;
    2191      675569 :         uint32_t local_id = vuid;
    2192             : 
    2193      675569 :         return smbXsrv_session_local_lookup(table, conn, local_id, now,
    2194             :                                             session);
    2195             : }
    2196             : 
    2197     1969469 : NTSTATUS smbXsrv_session_info_lookup(struct smbXsrv_client *client,
    2198             :                                      uint64_t session_wire_id,
    2199             :                                      struct auth_session_info **si)
    2200             : {
    2201     1969469 :         struct smbXsrv_session_table *table = client->session_table;
    2202       17237 :         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
    2203     1969469 :         struct smbXsrv_session_local_fetch_state state = {
    2204             :                 .session = NULL,
    2205             :                 .status = NT_STATUS_INTERNAL_ERROR,
    2206             :         };
    2207       17237 :         TDB_DATA key;
    2208       17237 :         NTSTATUS status;
    2209             : 
    2210     1969469 :         if (session_wire_id == 0) {
    2211           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2212             :         }
    2213             : 
    2214     1969469 :         if (table == NULL) {
    2215             :                 /* this might happen before the end of negprot */
    2216           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2217             :         }
    2218             : 
    2219     1969469 :         if (table->local.db_ctx == NULL) {
    2220           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2221             :         }
    2222             : 
    2223     1969469 :         key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
    2224             : 
    2225     1969469 :         status = dbwrap_parse_record(table->local.db_ctx, key,
    2226             :                                      smbXsrv_session_local_fetch_parser,
    2227             :                                      &state);
    2228     1969469 :         if (!NT_STATUS_IS_OK(status)) {
    2229          17 :                 return status;
    2230             :         }
    2231     1969452 :         if (!NT_STATUS_IS_OK(state.status)) {
    2232           0 :                 return state.status;
    2233             :         }
    2234     1969452 :         if (state.session->global->auth_session_info == NULL) {
    2235           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2236             :         }
    2237             : 
    2238     1969452 :         *si = state.session->global->auth_session_info;
    2239     1969452 :         return NT_STATUS_OK;
    2240             : }
    2241             : 
    2242             : /*
    2243             :  * In memory of get_valid_user_struct()
    2244             :  *
    2245             :  * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
    2246             :  * but it doesn't implement the state checks of
    2247             :  * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
    2248             :  * session wire-id of incoming SMB requests, it MUST only be used in later
    2249             :  * internal processing where the session wire-id has already been validated.
    2250             :  */
    2251       36900 : NTSTATUS get_valid_smbXsrv_session(struct smbXsrv_client *client,
    2252             :                                    uint64_t session_wire_id,
    2253             :                                    struct smbXsrv_session **session)
    2254             : {
    2255       36900 :         struct smbXsrv_session_table *table = client->session_table;
    2256         760 :         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
    2257       36900 :         struct smbXsrv_session_local_fetch_state state = {
    2258             :                 .session = NULL,
    2259             :                 .status = NT_STATUS_INTERNAL_ERROR,
    2260             :         };
    2261         760 :         TDB_DATA key;
    2262         760 :         NTSTATUS status;
    2263             : 
    2264       36900 :         if (session_wire_id == 0) {
    2265           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2266             :         }
    2267             : 
    2268       36900 :         if (table == NULL) {
    2269             :                 /* this might happen before the end of negprot */
    2270           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2271             :         }
    2272             : 
    2273       36900 :         if (table->local.db_ctx == NULL) {
    2274           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2275             :         }
    2276             : 
    2277       36900 :         key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
    2278             : 
    2279       36900 :         status = dbwrap_parse_record(table->local.db_ctx, key,
    2280             :                                      smbXsrv_session_local_fetch_parser,
    2281             :                                      &state);
    2282       36900 :         if (!NT_STATUS_IS_OK(status)) {
    2283           0 :                 return status;
    2284             :         }
    2285       36900 :         if (!NT_STATUS_IS_OK(state.status)) {
    2286           0 :                 return state.status;
    2287             :         }
    2288       36900 :         if (state.session->global->auth_session_info == NULL) {
    2289        3550 :                 return NT_STATUS_USER_SESSION_DELETED;
    2290             :         }
    2291             : 
    2292       33350 :         *session = state.session;
    2293       33350 :         return NT_STATUS_OK;
    2294             : }
    2295             : 
    2296       30647 : NTSTATUS smb2srv_session_lookup_global(struct smbXsrv_client *client,
    2297             :                                        uint64_t session_wire_id,
    2298             :                                        TALLOC_CTX *mem_ctx,
    2299             :                                        struct smbXsrv_session **_session)
    2300             : {
    2301       30647 :         TALLOC_CTX *frame = talloc_stackframe();
    2302       30647 :         struct smbXsrv_session_table *table = client->session_table;
    2303       30647 :         uint32_t global_id = session_wire_id & UINT32_MAX;
    2304       30647 :         uint64_t global_zeros = session_wire_id & 0xFFFFFFFF00000000LLU;
    2305       30647 :         struct smbXsrv_session *session = NULL;
    2306       30647 :         struct db_record *global_rec = NULL;
    2307       30647 :         bool is_free = false;
    2308         832 :         NTSTATUS status;
    2309             : 
    2310       30647 :         if (global_id == 0) {
    2311       29480 :                 TALLOC_FREE(frame);
    2312       29480 :                 return NT_STATUS_USER_SESSION_DELETED;
    2313             :         }
    2314        1167 :         if (global_zeros != 0) {
    2315           0 :                 TALLOC_FREE(frame);
    2316           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2317             :         }
    2318             : 
    2319        1167 :         if (table == NULL) {
    2320             :                 /* this might happen before the end of negprot */
    2321           0 :                 TALLOC_FREE(frame);
    2322           0 :                 return NT_STATUS_USER_SESSION_DELETED;
    2323             :         }
    2324             : 
    2325        1167 :         if (table->global.db_ctx == NULL) {
    2326           0 :                 TALLOC_FREE(frame);
    2327           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2328             :         }
    2329             : 
    2330        1167 :         session = talloc_zero(mem_ctx, struct smbXsrv_session);
    2331        1167 :         if (session == NULL) {
    2332           0 :                 TALLOC_FREE(frame);
    2333           0 :                 return NT_STATUS_NO_MEMORY;
    2334             :         }
    2335        1167 :         talloc_steal(frame, session);
    2336             : 
    2337        1167 :         session->client = client;
    2338        1167 :         session->status = NT_STATUS_BAD_LOGON_SESSION_STATE;
    2339        1167 :         session->local_id = global_id;
    2340             : 
    2341             :         /*
    2342             :          * This means smb2_get_new_nonce() will return
    2343             :          * NT_STATUS_ENCRYPTION_FAILED.
    2344             :          *
    2345             :          * But we initialize some random parts just in case...
    2346             :          */
    2347        1167 :         session->nonce_high_max = session->nonce_high = 0;
    2348        1167 :         generate_nonce_buffer((uint8_t *)&session->nonce_high_random,
    2349             :                               sizeof(session->nonce_high_random));
    2350        1167 :         generate_nonce_buffer((uint8_t *)&session->nonce_low,
    2351             :                               sizeof(session->nonce_low));
    2352             : 
    2353        1167 :         global_rec = smbXsrv_session_global_fetch_locked(table->global.db_ctx,
    2354             :                                                          global_id,
    2355             :                                                          frame);
    2356        1167 :         if (global_rec == NULL) {
    2357           0 :                 TALLOC_FREE(frame);
    2358           0 :                 return NT_STATUS_INTERNAL_DB_ERROR;
    2359             :         }
    2360             : 
    2361        1167 :         smbXsrv_session_global_verify_record(global_rec,
    2362             :                                              &is_free,
    2363             :                                              NULL,
    2364             :                                              session,
    2365        1167 :                                              &session->global,
    2366             :                                              NULL);
    2367        1167 :         if (is_free) {
    2368          10 :                 TALLOC_FREE(frame);
    2369          10 :                 return NT_STATUS_USER_SESSION_DELETED;
    2370             :         }
    2371             : 
    2372             :         /*
    2373             :          * We don't have channels on this session
    2374             :          * and only the main signing key
    2375             :          */
    2376        1157 :         session->global->num_channels = 0;
    2377        1362 :         status = smb2_signing_key_sign_create(session->global,
    2378        1157 :                                               session->global->signing_algo,
    2379             :                                               NULL, /* no master key */
    2380             :                                               NULL, /* derivations */
    2381         952 :                                               &session->global->signing_key);
    2382        1157 :         if (!NT_STATUS_IS_OK(status)) {
    2383           0 :                 TALLOC_FREE(frame);
    2384           0 :                 return NT_STATUS_NO_MEMORY;
    2385             :         }
    2386        1157 :         session->global->signing_key->blob = session->global->signing_key_blob;
    2387        1157 :         session->global->signing_flags = 0;
    2388             : 
    2389        1362 :         status = smb2_signing_key_cipher_create(session->global,
    2390        1157 :                                                 session->global->encryption_cipher,
    2391             :                                                 NULL, /* no master key */
    2392             :                                                 NULL, /* derivations */
    2393         952 :                                                 &session->global->decryption_key);
    2394        1157 :         if (!NT_STATUS_IS_OK(status)) {
    2395           0 :                 TALLOC_FREE(frame);
    2396           0 :                 return NT_STATUS_NO_MEMORY;
    2397             :         }
    2398        1157 :         session->global->decryption_key->blob = session->global->decryption_key_blob;
    2399        1157 :         session->global->encryption_flags = 0;
    2400             : 
    2401        1157 :         *_session = talloc_move(mem_ctx, &session);
    2402        1157 :         TALLOC_FREE(frame);
    2403        1157 :         return NT_STATUS_OK;
    2404             : }
    2405             : 
    2406       28913 : NTSTATUS smb2srv_session_table_init(struct smbXsrv_connection *conn)
    2407             : {
    2408             :         /*
    2409             :          * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
    2410             :          */
    2411       28913 :         return smbXsrv_session_table_init(conn, 1, UINT32_MAX - 1,
    2412             :                                           UINT16_MAX - 1);
    2413             : }
    2414             : 
    2415     1631444 : static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
    2416             :                                            /* conn: optional */
    2417             :                                            struct smbXsrv_connection *conn,
    2418             :                                            uint64_t session_id, NTTIME now,
    2419             :                                            struct smbXsrv_session **session)
    2420             : {
    2421     1631444 :         uint32_t local_id = session_id & UINT32_MAX;
    2422     1631444 :         uint64_t local_zeros = session_id & 0xFFFFFFFF00000000LLU;
    2423             : 
    2424     1631444 :         if (local_zeros != 0) {
    2425          24 :                 return NT_STATUS_USER_SESSION_DELETED;
    2426             :         }
    2427             : 
    2428     1631420 :         return smbXsrv_session_local_lookup(table, conn, local_id, now,
    2429             :                                             session);
    2430             : }
    2431             : 
    2432     1575944 : NTSTATUS smb2srv_session_lookup_conn(struct smbXsrv_connection *conn,
    2433             :                                      uint64_t session_id, NTTIME now,
    2434             :                                      struct smbXsrv_session **session)
    2435             : {
    2436     1575944 :         struct smbXsrv_session_table *table = conn->client->session_table;
    2437     1575944 :         return smb2srv_session_lookup_raw(table, conn, session_id, now,
    2438             :                                           session);
    2439             : }
    2440             : 
    2441       55500 : NTSTATUS smb2srv_session_lookup_client(struct smbXsrv_client *client,
    2442             :                                        uint64_t session_id, NTTIME now,
    2443             :                                        struct smbXsrv_session **session)
    2444             : {
    2445       55500 :         struct smbXsrv_session_table *table = client->session_table;
    2446       55500 :         return smb2srv_session_lookup_raw(table, NULL, session_id, now,
    2447             :                                           session);
    2448             : }
    2449             : 
    2450             : struct smbXsrv_session_global_traverse_state {
    2451             :         int (*fn)(struct smbXsrv_session_global0 *, void *);
    2452             :         void *private_data;
    2453             : };
    2454             : 
    2455          57 : static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
    2456             : {
    2457          57 :         int ret = -1;
    2458          57 :         struct smbXsrv_session_global_traverse_state *state =
    2459             :                 (struct smbXsrv_session_global_traverse_state*)data;
    2460          57 :         TDB_DATA key = dbwrap_record_get_key(rec);
    2461          57 :         TDB_DATA val = dbwrap_record_get_value(rec);
    2462          57 :         DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
    2463           0 :         struct smbXsrv_session_globalB global_blob;
    2464           0 :         enum ndr_err_code ndr_err;
    2465          57 :         TALLOC_CTX *frame = talloc_stackframe();
    2466             : 
    2467          57 :         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
    2468             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
    2469          57 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    2470           0 :                 DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
    2471             :                          "key '%s' ndr_pull_struct_blob - %s\n",
    2472             :                          tdb_data_dbg(key),
    2473             :                          ndr_errstr(ndr_err));
    2474           0 :                 goto done;
    2475             :         }
    2476             : 
    2477          57 :         if (global_blob.version != SMBXSRV_VERSION_0) {
    2478           0 :                 DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
    2479             :                          "key '%s' unsupported version - %d\n",
    2480             :                          tdb_data_dbg(key),
    2481             :                          (int)global_blob.version);
    2482           0 :                 goto done;
    2483             :         }
    2484             : 
    2485          57 :         if (global_blob.info.info0 == NULL) {
    2486           0 :                 DBG_WARNING("Invalid record in smbXsrv_tcon_global.tdb:"
    2487             :                          "key '%s' info0 NULL pointer\n",
    2488             :                          tdb_data_dbg(key));
    2489           0 :                 goto done;
    2490             :         }
    2491             : 
    2492          57 :         global_blob.info.info0->db_rec = rec;
    2493          57 :         ret = state->fn(global_blob.info.info0, state->private_data);
    2494          57 : done:
    2495          57 :         TALLOC_FREE(frame);
    2496          57 :         return ret;
    2497             : }
    2498             : 
    2499          53 : NTSTATUS smbXsrv_session_global_traverse(
    2500             :                         int (*fn)(struct smbXsrv_session_global0 *, void *),
    2501             :                         void *private_data)
    2502             : {
    2503             : 
    2504           0 :         NTSTATUS status;
    2505          53 :         int count = 0;
    2506          53 :         struct smbXsrv_session_global_traverse_state state = {
    2507             :                 .fn = fn,
    2508             :                 .private_data = private_data,
    2509             :         };
    2510             : 
    2511          53 :         become_root();
    2512          53 :         status = smbXsrv_session_global_init(NULL);
    2513          53 :         if (!NT_STATUS_IS_OK(status)) {
    2514           0 :                 unbecome_root();
    2515           0 :                 DBG_ERR("Failed to initialize session_global: %s\n",
    2516             :                           nt_errstr(status));
    2517           0 :                 return status;
    2518             :         }
    2519             : 
    2520          53 :         status = dbwrap_traverse_read(smbXsrv_session_global_db_ctx,
    2521             :                                       smbXsrv_session_global_traverse_fn,
    2522             :                                       &state,
    2523             :                                       &count);
    2524          53 :         unbecome_root();
    2525             : 
    2526          53 :         return status;
    2527             : }

Generated by: LCOV version 1.14