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

Generated by: LCOV version 1.13