LCOV - code coverage report
Current view: top level - source3/smbd - smbXsrv_session.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 735 1099 66.9 %
Date: 2024-02-14 10:14:15 Functions: 49 54 90.7 %

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

Generated by: LCOV version 1.14