LCOV - code coverage report
Current view: top level - source3/smbd - smbXsrv_tcon.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 334 517 64.6 %
Date: 2024-02-14 10:14:15 Functions: 29 31 93.5 %

          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 "lib/util/server_id.h"
      24             : #include "smbd/smbd.h"
      25             : #include "smbd/globals.h"
      26             : #include "dbwrap/dbwrap.h"
      27             : #include "dbwrap/dbwrap_rbt.h"
      28             : #include "dbwrap/dbwrap_open.h"
      29             : #include "messages.h"
      30             : #include "lib/util/util_tdb.h"
      31             : #include "librpc/gen_ndr/ndr_smbXsrv.h"
      32             : #include "serverid.h"
      33             : #include "source3/include/util_tdb.h"
      34             : 
      35             : struct smbXsrv_tcon_table {
      36             :         struct {
      37             :                 struct db_context *db_ctx;
      38             :                 uint32_t lowest_id;
      39             :                 uint32_t highest_id;
      40             :                 uint32_t max_tcons;
      41             :                 uint32_t num_tcons;
      42             :         } local;
      43             :         struct {
      44             :                 struct db_context *db_ctx;
      45             :         } global;
      46             : };
      47             : 
      48             : static struct db_context *smbXsrv_tcon_global_db_ctx = NULL;
      49             : 
      50        4973 : NTSTATUS smbXsrv_tcon_global_init(void)
      51             : {
      52        4973 :         char *global_path = NULL;
      53        4973 :         struct db_context *db_ctx = NULL;
      54             : 
      55        4973 :         if (smbXsrv_tcon_global_db_ctx != NULL) {
      56        4966 :                 return NT_STATUS_OK;
      57             :         }
      58             : 
      59           7 :         global_path = lock_path(talloc_tos(), "smbXsrv_tcon_global.tdb");
      60           7 :         if (global_path == NULL) {
      61           0 :                 return NT_STATUS_NO_MEMORY;
      62             :         }
      63             : 
      64           7 :         db_ctx = db_open(NULL, global_path,
      65             :                          SMBD_VOLATILE_TDB_HASH_SIZE,
      66             :                          SMBD_VOLATILE_TDB_FLAGS,
      67             :                          O_RDWR | O_CREAT, 0600,
      68             :                          DBWRAP_LOCK_ORDER_1,
      69             :                          DBWRAP_FLAG_NONE);
      70           7 :         TALLOC_FREE(global_path);
      71           7 :         if (db_ctx == NULL) {
      72             :                 NTSTATUS status;
      73             : 
      74           0 :                 status = map_nt_error_from_unix_common(errno);
      75             : 
      76           0 :                 return status;
      77             :         }
      78             : 
      79           7 :         smbXsrv_tcon_global_db_ctx = db_ctx;
      80             : 
      81           7 :         return NT_STATUS_OK;
      82             : }
      83             : 
      84             : /*
      85             :  * NOTE:
      86             :  * We need to store the keys in big endian so that dbwrap_rbt's memcmp
      87             :  * has the same result as integer comparison between the uint32_t
      88             :  * values.
      89             :  *
      90             :  * TODO: implement string based key
      91             :  */
      92             : 
      93             : #define SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
      94             : 
      95       16710 : static TDB_DATA smbXsrv_tcon_global_id_to_key(uint32_t id,
      96             :                                               uint8_t *key_buf)
      97             : {
      98             :         TDB_DATA key;
      99             : 
     100       16710 :         RSIVAL(key_buf, 0, id);
     101             : 
     102       16710 :         key = make_tdb_data(key_buf, SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE);
     103             : 
     104       16710 :         return key;
     105             : }
     106             : 
     107             : #if 0
     108             : static NTSTATUS smbXsrv_tcon_global_key_to_id(TDB_DATA key, uint32_t *id)
     109             : {
     110             :         if (id == NULL) {
     111             :                 return NT_STATUS_INVALID_PARAMETER;
     112             :         }
     113             : 
     114             :         if (key.dsize != SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE) {
     115             :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     116             :         }
     117             : 
     118             :         *id = RIVAL(key.dptr, 0);
     119             : 
     120             :         return NT_STATUS_OK;
     121             : }
     122             : #endif
     123             : 
     124             : #define SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
     125             : 
     126      144395 : static TDB_DATA smbXsrv_tcon_local_id_to_key(uint32_t id,
     127             :                                              uint8_t *key_buf)
     128             : {
     129             :         TDB_DATA key;
     130             : 
     131      144395 :         RSIVAL(key_buf, 0, id);
     132             : 
     133      144395 :         key = make_tdb_data(key_buf, SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE);
     134             : 
     135      144395 :         return key;
     136             : }
     137             : 
     138           0 : static NTSTATUS smbXsrv_tcon_local_key_to_id(TDB_DATA key, uint32_t *id)
     139             : {
     140           0 :         if (id == NULL) {
     141           0 :                 return NT_STATUS_INVALID_PARAMETER;
     142             :         }
     143             : 
     144           0 :         if (key.dsize != SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE) {
     145           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     146             :         }
     147             : 
     148           0 :         *id = RIVAL(key.dptr, 0);
     149             : 
     150           0 :         return NT_STATUS_OK;
     151             : }
     152             : 
     153       16710 : static struct db_record *smbXsrv_tcon_global_fetch_locked(
     154             :                         struct db_context *db,
     155             :                         uint32_t id,
     156             :                         TALLOC_CTX *mem_ctx)
     157             : {
     158             :         TDB_DATA key;
     159             :         uint8_t key_buf[SMBXSRV_TCON_GLOBAL_TDB_KEY_SIZE];
     160       16710 :         struct db_record *rec = NULL;
     161             : 
     162       16710 :         key = smbXsrv_tcon_global_id_to_key(id, key_buf);
     163             : 
     164       16710 :         rec = dbwrap_fetch_locked(db, mem_ctx, key);
     165             : 
     166       16710 :         if (rec == NULL) {
     167           0 :                 DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id,
     168             :                           tdb_data_dbg(key));
     169             :         }
     170             : 
     171       16710 :         return rec;
     172             : }
     173             : 
     174        8065 : static struct db_record *smbXsrv_tcon_local_fetch_locked(
     175             :                         struct db_context *db,
     176             :                         uint32_t id,
     177             :                         TALLOC_CTX *mem_ctx)
     178             : {
     179             :         TDB_DATA key;
     180             :         uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE];
     181        8065 :         struct db_record *rec = NULL;
     182             : 
     183        8065 :         key = smbXsrv_tcon_local_id_to_key(id, key_buf);
     184             : 
     185        8065 :         rec = dbwrap_fetch_locked(db, mem_ctx, key);
     186             : 
     187        8065 :         if (rec == NULL) {
     188           0 :                 DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id,
     189             :                           tdb_data_dbg(key));
     190             :         }
     191             : 
     192        8065 :         return rec;
     193             : }
     194             : 
     195        4952 : static NTSTATUS smbXsrv_tcon_table_init(TALLOC_CTX *mem_ctx,
     196             :                                         struct smbXsrv_tcon_table *table,
     197             :                                         uint32_t lowest_id,
     198             :                                         uint32_t highest_id,
     199             :                                         uint32_t max_tcons)
     200             : {
     201             :         NTSTATUS status;
     202             :         uint64_t max_range;
     203             : 
     204        4952 :         if (lowest_id > highest_id) {
     205           0 :                 return NT_STATUS_INTERNAL_ERROR;
     206             :         }
     207             : 
     208        4952 :         max_range = highest_id;
     209        4952 :         max_range -= lowest_id;
     210        4952 :         max_range += 1;
     211             : 
     212        4952 :         if (max_tcons > max_range) {
     213           0 :                 return NT_STATUS_INTERNAL_ERROR;
     214             :         }
     215             : 
     216        4952 :         ZERO_STRUCTP(table);
     217        4952 :         table->local.db_ctx = db_open_rbt(table);
     218        4952 :         if (table->local.db_ctx == NULL) {
     219           0 :                 return NT_STATUS_NO_MEMORY;
     220             :         }
     221        4952 :         table->local.lowest_id = lowest_id;
     222        4952 :         table->local.highest_id = highest_id;
     223        4952 :         table->local.max_tcons = max_tcons;
     224             : 
     225        4952 :         status = smbXsrv_tcon_global_init();
     226        4952 :         if (!NT_STATUS_IS_OK(status)) {
     227           0 :                 return status;
     228             :         }
     229             : 
     230        4952 :         table->global.db_ctx = smbXsrv_tcon_global_db_ctx;
     231             : 
     232        4952 :         return NT_STATUS_OK;
     233             : }
     234             : 
     235             : struct smb1srv_tcon_local_allocate_state {
     236             :         const uint32_t lowest_id;
     237             :         const uint32_t highest_id;
     238             :         uint32_t last_id;
     239             :         uint32_t useable_id;
     240             :         NTSTATUS status;
     241             : };
     242             : 
     243           0 : static int smb1srv_tcon_local_allocate_traverse(struct db_record *rec,
     244             :                                                    void *private_data)
     245             : {
     246           0 :         struct smb1srv_tcon_local_allocate_state *state =
     247             :                 (struct smb1srv_tcon_local_allocate_state *)private_data;
     248           0 :         TDB_DATA key = dbwrap_record_get_key(rec);
     249           0 :         uint32_t id = 0;
     250             :         NTSTATUS status;
     251             : 
     252           0 :         status = smbXsrv_tcon_local_key_to_id(key, &id);
     253           0 :         if (!NT_STATUS_IS_OK(status)) {
     254           0 :                 state->status = status;
     255           0 :                 return -1;
     256             :         }
     257             : 
     258           0 :         if (id <= state->last_id) {
     259           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     260           0 :                 return -1;
     261             :         }
     262           0 :         state->last_id = id;
     263             : 
     264           0 :         if (id > state->useable_id) {
     265           0 :                 state->status = NT_STATUS_OK;
     266           0 :                 return -1;
     267             :         }
     268             : 
     269           0 :         if (state->useable_id == state->highest_id) {
     270           0 :                 state->status = NT_STATUS_INSUFFICIENT_RESOURCES;
     271           0 :                 return -1;
     272             :         }
     273             : 
     274           0 :         state->useable_id +=1;
     275           0 :         return 0;
     276             : }
     277             : 
     278          28 : static NTSTATUS smb1srv_tcon_local_allocate_id(struct db_context *db,
     279             :                                                uint32_t lowest_id,
     280             :                                                uint32_t highest_id,
     281             :                                                TALLOC_CTX *mem_ctx,
     282             :                                                struct db_record **_rec,
     283             :                                                uint32_t *_id)
     284             : {
     285          28 :         struct smb1srv_tcon_local_allocate_state state = {
     286             :                 .lowest_id = lowest_id,
     287             :                 .highest_id = highest_id,
     288             :                 .last_id = 0,
     289             :                 .useable_id = lowest_id,
     290             :                 .status = NT_STATUS_INTERNAL_ERROR,
     291             :         };
     292             :         uint32_t i;
     293             :         uint32_t range;
     294             :         NTSTATUS status;
     295          28 :         int count = 0;
     296             : 
     297          28 :         *_rec = NULL;
     298          28 :         *_id = 0;
     299             : 
     300          28 :         if (lowest_id > highest_id) {
     301           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
     302             :         }
     303             : 
     304             :         /*
     305             :          * first we try randomly
     306             :          */
     307          28 :         range = (highest_id - lowest_id) + 1;
     308             : 
     309          28 :         for (i = 0; i < (range / 2); i++) {
     310             :                 uint32_t id;
     311             :                 TDB_DATA val;
     312          28 :                 struct db_record *rec = NULL;
     313             : 
     314          28 :                 id = generate_random() % range;
     315          28 :                 id += lowest_id;
     316             : 
     317          28 :                 if (id < lowest_id) {
     318           0 :                         id = lowest_id;
     319             :                 }
     320          28 :                 if (id > highest_id) {
     321           0 :                         id = highest_id;
     322             :                 }
     323             : 
     324          28 :                 rec = smbXsrv_tcon_local_fetch_locked(db, id, mem_ctx);
     325          28 :                 if (rec == NULL) {
     326           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     327             :                 }
     328             : 
     329          28 :                 val = dbwrap_record_get_value(rec);
     330          28 :                 if (val.dsize != 0) {
     331           0 :                         TALLOC_FREE(rec);
     332           0 :                         continue;
     333             :                 }
     334             : 
     335          28 :                 *_rec = rec;
     336          28 :                 *_id = id;
     337          28 :                 return NT_STATUS_OK;
     338             :         }
     339             : 
     340             :         /*
     341             :          * if the range is almost full,
     342             :          * we traverse the whole table
     343             :          * (this relies on sorted behavior of dbwrap_rbt)
     344             :          */
     345           0 :         status = dbwrap_traverse_read(db, smb1srv_tcon_local_allocate_traverse,
     346             :                                       &state, &count);
     347           0 :         if (NT_STATUS_IS_OK(status)) {
     348           0 :                 if (NT_STATUS_IS_OK(state.status)) {
     349           0 :                         return NT_STATUS_INTERNAL_ERROR;
     350             :                 }
     351             : 
     352           0 :                 if (!NT_STATUS_EQUAL(state.status, NT_STATUS_INTERNAL_ERROR)) {
     353           0 :                         return state.status;
     354             :                 }
     355             : 
     356           0 :                 if (state.useable_id <= state.highest_id) {
     357           0 :                         state.status = NT_STATUS_OK;
     358             :                 } else {
     359           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     360             :                 }
     361           0 :         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_CORRUPTION)) {
     362             :                 /*
     363             :                  * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
     364             :                  *
     365             :                  * If we get anything else it is an error, because it
     366             :                  * means we did not manage to find a free slot in
     367             :                  * the db.
     368             :                  */
     369           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
     370             :         }
     371             : 
     372           0 :         if (NT_STATUS_IS_OK(state.status)) {
     373             :                 uint32_t id;
     374             :                 TDB_DATA val;
     375           0 :                 struct db_record *rec = NULL;
     376             : 
     377           0 :                 id = state.useable_id;
     378             : 
     379           0 :                 rec = smbXsrv_tcon_local_fetch_locked(db, id, mem_ctx);
     380           0 :                 if (rec == NULL) {
     381           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     382             :                 }
     383             : 
     384           0 :                 val = dbwrap_record_get_value(rec);
     385           0 :                 if (val.dsize != 0) {
     386           0 :                         TALLOC_FREE(rec);
     387           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     388             :                 }
     389             : 
     390           0 :                 *_rec = rec;
     391           0 :                 *_id = id;
     392           0 :                 return NT_STATUS_OK;
     393             :         }
     394             : 
     395           0 :         return state.status;
     396             : }
     397             : 
     398             : struct smbXsrv_tcon_local_fetch_state {
     399             :         struct smbXsrv_tcon *tcon;
     400             :         NTSTATUS status;
     401             : };
     402             : 
     403      136320 : static void smbXsrv_tcon_local_fetch_parser(TDB_DATA key, TDB_DATA data,
     404             :                                             void *private_data)
     405             : {
     406      136320 :         struct smbXsrv_tcon_local_fetch_state *state =
     407             :                 (struct smbXsrv_tcon_local_fetch_state *)private_data;
     408             :         void *ptr;
     409             : 
     410      136320 :         if (data.dsize != sizeof(ptr)) {
     411           0 :                 state->status = NT_STATUS_INTERNAL_DB_ERROR;
     412           0 :                 return;
     413             :         }
     414             : 
     415      136320 :         memcpy(&ptr, data.dptr, data.dsize);
     416      136320 :         state->tcon = talloc_get_type_abort(ptr, struct smbXsrv_tcon);
     417      136320 :         state->status = NT_STATUS_OK;
     418             : }
     419             : 
     420      139969 : static NTSTATUS smbXsrv_tcon_local_lookup(struct smbXsrv_tcon_table *table,
     421             :                                           uint32_t tcon_local_id,
     422             :                                           NTTIME now,
     423             :                                           struct smbXsrv_tcon **_tcon)
     424             : {
     425      139969 :         struct smbXsrv_tcon_local_fetch_state state = {
     426             :                 .tcon = NULL,
     427             :                 .status = NT_STATUS_INTERNAL_ERROR,
     428             :         };
     429             :         uint8_t key_buf[SMBXSRV_TCON_LOCAL_TDB_KEY_SIZE];
     430             :         TDB_DATA key;
     431             :         NTSTATUS status;
     432             : 
     433      139969 :         *_tcon = NULL;
     434             : 
     435      139969 :         if (tcon_local_id == 0) {
     436        3639 :                 return NT_STATUS_NETWORK_NAME_DELETED;
     437             :         }
     438             : 
     439      136330 :         if (table == NULL) {
     440             :                 /* this might happen before the end of negprot */
     441           0 :                 return NT_STATUS_NETWORK_NAME_DELETED;
     442             :         }
     443             : 
     444      136330 :         if (table->local.db_ctx == NULL) {
     445           0 :                 return NT_STATUS_INTERNAL_ERROR;
     446             :         }
     447             : 
     448      136330 :         key = smbXsrv_tcon_local_id_to_key(tcon_local_id, key_buf);
     449             : 
     450      136330 :         status = dbwrap_parse_record(table->local.db_ctx, key,
     451             :                                      smbXsrv_tcon_local_fetch_parser,
     452             :                                      &state);
     453      136330 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     454          10 :                 return NT_STATUS_NETWORK_NAME_DELETED;
     455      136320 :         } else if (!NT_STATUS_IS_OK(status)) {
     456           0 :                 return status;
     457             :         }
     458      136320 :         if (!NT_STATUS_IS_OK(state.status)) {
     459           0 :                 return state.status;
     460             :         }
     461             : 
     462      136320 :         if (NT_STATUS_EQUAL(state.tcon->status, NT_STATUS_NETWORK_NAME_DELETED)) {
     463           0 :                 return NT_STATUS_NETWORK_NAME_DELETED;
     464             :         }
     465             : 
     466      136320 :         state.tcon->idle_time = now;
     467             : 
     468      136320 :         *_tcon = state.tcon;
     469      136320 :         return state.tcon->status;
     470             : }
     471             : 
     472        5627 : static int smbXsrv_tcon_global_destructor(struct smbXsrv_tcon_global0 *global)
     473             : {
     474        5627 :         return 0;
     475             : }
     476             : 
     477             : static void smbXsrv_tcon_global_verify_record(struct db_record *db_rec,
     478             :                                         bool *is_free,
     479             :                                         bool *was_free,
     480             :                                         TALLOC_CTX *mem_ctx,
     481             :                                         struct smbXsrv_tcon_global0 **_g);
     482             : 
     483        5627 : static NTSTATUS smbXsrv_tcon_global_allocate(struct db_context *db,
     484             :                                         TALLOC_CTX *mem_ctx,
     485             :                                         struct smbXsrv_tcon_global0 **_global)
     486             : {
     487             :         uint32_t i;
     488        5627 :         struct smbXsrv_tcon_global0 *global = NULL;
     489        5627 :         uint32_t last_free = 0;
     490        5627 :         const uint32_t min_tries = 3;
     491             : 
     492        5627 :         *_global = NULL;
     493             : 
     494        5627 :         global = talloc_zero(mem_ctx, struct smbXsrv_tcon_global0);
     495        5627 :         if (global == NULL) {
     496           0 :                 return NT_STATUS_NO_MEMORY;
     497             :         }
     498        5627 :         talloc_set_destructor(global, smbXsrv_tcon_global_destructor);
     499             : 
     500             :         /*
     501             :          * Here we just randomly try the whole 32-bit space
     502             :          *
     503             :          * We use just 32-bit, because we want to reuse the
     504             :          * ID for SRVSVC.
     505             :          */
     506        5627 :         for (i = 0; i < UINT32_MAX; i++) {
     507        5627 :                 bool is_free = false;
     508        5627 :                 bool was_free = false;
     509             :                 uint32_t id;
     510             : 
     511        5627 :                 if (i >= min_tries && last_free != 0) {
     512           0 :                         id = last_free;
     513             :                 } else {
     514        5627 :                         id = generate_random();
     515             :                 }
     516        5627 :                 if (id == 0) {
     517           0 :                         id++;
     518             :                 }
     519        5627 :                 if (id == UINT32_MAX) {
     520           0 :                         id--;
     521             :                 }
     522             : 
     523        5627 :                 global->db_rec = smbXsrv_tcon_global_fetch_locked(db, id,
     524             :                                                                   mem_ctx);
     525        5627 :                 if (global->db_rec == NULL) {
     526           0 :                         talloc_free(global);
     527           0 :                         return NT_STATUS_INSUFFICIENT_RESOURCES;
     528             :                 }
     529             : 
     530        5627 :                 smbXsrv_tcon_global_verify_record(global->db_rec,
     531             :                                                   &is_free,
     532             :                                                   &was_free,
     533             :                                                   NULL, NULL);
     534             : 
     535        5627 :                 if (!is_free) {
     536           0 :                         TALLOC_FREE(global->db_rec);
     537           0 :                         continue;
     538             :                 }
     539             : 
     540        5627 :                 if (!was_free && i < min_tries) {
     541             :                         /*
     542             :                          * The session_id is free now,
     543             :                          * but was not free before.
     544             :                          *
     545             :                          * This happens if a smbd crashed
     546             :                          * and did not cleanup the record.
     547             :                          *
     548             :                          * If this is one of our first tries,
     549             :                          * then we try to find a real free one.
     550             :                          */
     551           0 :                         if (last_free == 0) {
     552           0 :                                 last_free = id;
     553             :                         }
     554           0 :                         TALLOC_FREE(global->db_rec);
     555           0 :                         continue;
     556             :                 }
     557             : 
     558        5627 :                 global->tcon_global_id = id;
     559             : 
     560        5627 :                 *_global = global;
     561        5627 :                 return NT_STATUS_OK;
     562             :         }
     563             : 
     564             :         /* should not be reached */
     565           0 :         talloc_free(global);
     566           0 :         return NT_STATUS_INTERNAL_ERROR;
     567             : }
     568             : 
     569        5627 : static void smbXsrv_tcon_global_verify_record(struct db_record *db_rec,
     570             :                                         bool *is_free,
     571             :                                         bool *was_free,
     572             :                                         TALLOC_CTX *mem_ctx,
     573             :                                         struct smbXsrv_tcon_global0 **_g)
     574             : {
     575             :         TDB_DATA key;
     576             :         TDB_DATA val;
     577             :         DATA_BLOB blob;
     578             :         struct smbXsrv_tcon_globalB global_blob;
     579             :         enum ndr_err_code ndr_err;
     580        5627 :         struct smbXsrv_tcon_global0 *global = NULL;
     581             :         bool exists;
     582        5627 :         TALLOC_CTX *frame = talloc_stackframe();
     583             : 
     584        5627 :         *is_free = false;
     585             : 
     586        5627 :         if (was_free) {
     587        5627 :                 *was_free = false;
     588             :         }
     589        5627 :         if (_g) {
     590           0 :                 *_g = NULL;
     591             :         }
     592             : 
     593        5627 :         key = dbwrap_record_get_key(db_rec);
     594             : 
     595        5627 :         val = dbwrap_record_get_value(db_rec);
     596        5627 :         if (val.dsize == 0) {
     597        5627 :                 TALLOC_FREE(frame);
     598        5627 :                 *is_free = true;
     599        5627 :                 if (was_free) {
     600        5627 :                         *was_free = true;
     601             :                 }
     602        5627 :                 return;
     603             :         }
     604             : 
     605           0 :         blob = data_blob_const(val.dptr, val.dsize);
     606             : 
     607           0 :         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
     608             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_tcon_globalB);
     609           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     610           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     611           0 :                 DEBUG(1,("smbXsrv_tcon_global_verify_record: "
     612             :                          "key '%s' ndr_pull_struct_blob - %s\n",
     613             :                          tdb_data_dbg(key),
     614             :                          nt_errstr(status)));
     615           0 :                 TALLOC_FREE(frame);
     616           0 :                 return;
     617             :         }
     618             : 
     619           0 :         DEBUG(10,("smbXsrv_tcon_global_verify_record\n"));
     620           0 :         if (DEBUGLVL(10)) {
     621           0 :                 NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
     622             :         }
     623             : 
     624           0 :         if (global_blob.version != SMBXSRV_VERSION_0) {
     625           0 :                 DEBUG(0,("smbXsrv_tcon_global_verify_record: "
     626             :                          "key '%s' use unsupported version %u\n",
     627             :                          tdb_data_dbg(key),
     628             :                          global_blob.version));
     629           0 :                 NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
     630           0 :                 TALLOC_FREE(frame);
     631           0 :                 return;
     632             :         }
     633             : 
     634           0 :         global = global_blob.info.info0;
     635             : 
     636           0 :         exists = serverid_exists(&global->server_id);
     637           0 :         if (!exists) {
     638             :                 struct server_id_buf idbuf;
     639           0 :                 DEBUG(2,("smbXsrv_tcon_global_verify_record: "
     640             :                          "key '%s' server_id %s does not exist.\n",
     641             :                          tdb_data_dbg(key),
     642             :                          server_id_str_buf(global->server_id, &idbuf)));
     643           0 :                 if (DEBUGLVL(2)) {
     644           0 :                         NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
     645             :                 }
     646           0 :                 TALLOC_FREE(frame);
     647           0 :                 dbwrap_record_delete(db_rec);
     648           0 :                 *is_free = true;
     649           0 :                 return;
     650             :         }
     651             : 
     652           0 :         if (_g) {
     653           0 :                 *_g = talloc_move(mem_ctx, &global);
     654             :         }
     655           0 :         TALLOC_FREE(frame);
     656             : }
     657             : 
     658       11091 : static NTSTATUS smbXsrv_tcon_global_store(struct smbXsrv_tcon_global0 *global)
     659             : {
     660             :         struct smbXsrv_tcon_globalB global_blob;
     661       11091 :         DATA_BLOB blob = data_blob_null;
     662             :         TDB_DATA key;
     663             :         TDB_DATA val;
     664             :         NTSTATUS status;
     665             :         enum ndr_err_code ndr_err;
     666             : 
     667             :         /*
     668             :          * TODO: if we use other versions than '0'
     669             :          * we would add glue code here, that would be able to
     670             :          * store the information in the old format.
     671             :          */
     672             : 
     673       11091 :         if (global->db_rec == NULL) {
     674           0 :                 return NT_STATUS_INTERNAL_ERROR;
     675             :         }
     676             : 
     677       11091 :         key = dbwrap_record_get_key(global->db_rec);
     678       11091 :         val = dbwrap_record_get_value(global->db_rec);
     679             : 
     680       11091 :         ZERO_STRUCT(global_blob);
     681       11091 :         global_blob.version = smbXsrv_version_global_current();
     682       11091 :         if (val.dsize >= 8) {
     683        5464 :                 global_blob.seqnum = IVAL(val.dptr, 4);
     684             :         }
     685       11091 :         global_blob.seqnum += 1;
     686       11091 :         global_blob.info.info0 = global;
     687             : 
     688       11091 :         ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
     689             :                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_tcon_globalB);
     690       11091 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     691           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     692           0 :                 DEBUG(1,("smbXsrv_tcon_global_store: key '%s' ndr_push - %s\n",
     693             :                          tdb_data_dbg(key),
     694             :                          nt_errstr(status)));
     695           0 :                 TALLOC_FREE(global->db_rec);
     696           0 :                 return status;
     697             :         }
     698             : 
     699       11091 :         val = make_tdb_data(blob.data, blob.length);
     700       11091 :         status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
     701       11091 :         if (!NT_STATUS_IS_OK(status)) {
     702           0 :                 DEBUG(1,("smbXsrv_tcon_global_store: key '%s' store - %s\n",
     703             :                          tdb_data_dbg(key),
     704             :                          nt_errstr(status)));
     705           0 :                 TALLOC_FREE(global->db_rec);
     706           0 :                 return status;
     707             :         }
     708             : 
     709       11091 :         if (DEBUGLVL(10)) {
     710           0 :                 DEBUG(10,("smbXsrv_tcon_global_store: key '%s' stored\n",
     711             :                           tdb_data_dbg(key)));
     712           0 :                 NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
     713             :         }
     714             : 
     715       11091 :         TALLOC_FREE(global->db_rec);
     716             : 
     717       11091 :         return NT_STATUS_OK;
     718             : }
     719             : 
     720        5627 : static int smbXsrv_tcon_destructor(struct smbXsrv_tcon *tcon)
     721             : {
     722             :         NTSTATUS status;
     723             : 
     724        5627 :         status = smbXsrv_tcon_disconnect(tcon, 0);
     725        5627 :         if (!NT_STATUS_IS_OK(status)) {
     726           0 :                 DEBUG(0, ("smbXsrv_tcon_destructor: "
     727             :                           "smbXsrv_tcon_disconnect() failed - %s\n",
     728             :                           nt_errstr(status)));
     729             :         }
     730             : 
     731        5627 :         TALLOC_FREE(tcon->global);
     732             : 
     733        5627 :         return 0;
     734             : }
     735             : 
     736        5627 : static NTSTATUS smbXsrv_tcon_create(struct smbXsrv_tcon_table *table,
     737             :                                     enum protocol_types protocol,
     738             :                                     struct server_id server_id,
     739             :                                     NTTIME now,
     740             :                                     uint32_t session_global_id,
     741             :                                     uint8_t encryption_flags,
     742             :                                     const char *share_name,
     743             :                                     struct smbXsrv_tcon **_tcon)
     744             : {
     745        5627 :         struct db_record *local_rec = NULL;
     746        5627 :         struct smbXsrv_tcon *tcon = NULL;
     747        5627 :         void *ptr = NULL;
     748             :         TDB_DATA val;
     749        5627 :         struct smbXsrv_tcon_global0 *global = NULL;
     750             :         NTSTATUS status;
     751             : 
     752        5627 :         if (table->local.num_tcons >= table->local.max_tcons) {
     753           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
     754             :         }
     755             : 
     756        5627 :         tcon = talloc_zero(table, struct smbXsrv_tcon);
     757        5627 :         if (tcon == NULL) {
     758           0 :                 return NT_STATUS_NO_MEMORY;
     759             :         }
     760        5627 :         tcon->table = table;
     761        5627 :         tcon->status = NT_STATUS_INTERNAL_ERROR;
     762        5627 :         tcon->idle_time = now;
     763             : 
     764        5627 :         status = smbXsrv_tcon_global_allocate(table->global.db_ctx,
     765             :                                               tcon, &global);
     766        5627 :         if (!NT_STATUS_IS_OK(status)) {
     767           0 :                 TALLOC_FREE(tcon);
     768           0 :                 return status;
     769             :         }
     770        5627 :         tcon->global = global;
     771             : 
     772        5627 :         global->session_global_id = session_global_id;
     773        5627 :         global->encryption_flags = encryption_flags;
     774        5627 :         global->share_name = talloc_strdup(global, share_name);
     775        5627 :         if (global->share_name == NULL) {
     776           0 :                 TALLOC_FREE(tcon);
     777           0 :                 return NT_STATUS_NO_MEMORY;
     778             :         }
     779             : 
     780        5627 :         if (protocol >= PROTOCOL_SMB2_02) {
     781        5599 :                 uint64_t id = global->tcon_global_id;
     782             : 
     783        5599 :                 global->tcon_wire_id = id;
     784             : 
     785        5599 :                 tcon->local_id = global->tcon_global_id;
     786             : 
     787        5599 :                 local_rec = smbXsrv_tcon_local_fetch_locked(table->local.db_ctx,
     788             :                                                         tcon->local_id,
     789             :                                                         tcon /* TALLOC_CTX */);
     790        5599 :                 if (local_rec == NULL) {
     791           0 :                         TALLOC_FREE(tcon);
     792           0 :                         return NT_STATUS_NO_MEMORY;
     793             :                 }
     794             : 
     795        5599 :                 val = dbwrap_record_get_value(local_rec);
     796        5599 :                 if (val.dsize != 0) {
     797           0 :                         TALLOC_FREE(tcon);
     798           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     799             :                 }
     800             :         } else {
     801             : 
     802          28 :                 status = smb1srv_tcon_local_allocate_id(table->local.db_ctx,
     803             :                                                         table->local.lowest_id,
     804             :                                                         table->local.highest_id,
     805             :                                                         tcon,
     806             :                                                         &local_rec,
     807             :                                                         &tcon->local_id);
     808          28 :                 if (!NT_STATUS_IS_OK(status)) {
     809           0 :                         TALLOC_FREE(tcon);
     810           0 :                         return status;
     811             :                 }
     812             : 
     813          28 :                 global->tcon_wire_id = tcon->local_id;
     814             :         }
     815             : 
     816        5627 :         global->creation_time = now;
     817             : 
     818        5627 :         global->server_id = server_id;
     819             : 
     820        5627 :         ptr = tcon;
     821        5627 :         val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
     822        5627 :         status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
     823        5627 :         TALLOC_FREE(local_rec);
     824        5627 :         if (!NT_STATUS_IS_OK(status)) {
     825           0 :                 TALLOC_FREE(tcon);
     826           0 :                 return status;
     827             :         }
     828        5627 :         table->local.num_tcons += 1;
     829             : 
     830        5627 :         talloc_set_destructor(tcon, smbXsrv_tcon_destructor);
     831             : 
     832        5627 :         status = smbXsrv_tcon_global_store(global);
     833        5627 :         if (!NT_STATUS_IS_OK(status)) {
     834           0 :                 DEBUG(0,("smbXsrv_tcon_create: "
     835             :                          "global_id (0x%08x) store failed - %s\n",
     836             :                          tcon->global->tcon_global_id,
     837             :                          nt_errstr(status)));
     838           0 :                 TALLOC_FREE(tcon);
     839           0 :                 return status;
     840             :         }
     841             : 
     842        5627 :         if (DEBUGLVL(10)) {
     843           0 :                 struct smbXsrv_tconB tcon_blob = {
     844             :                         .version = SMBXSRV_VERSION_0,
     845             :                         .info.info0 = tcon,
     846             :                 };
     847             : 
     848           0 :                 DEBUG(10,("smbXsrv_tcon_create: global_id (0x%08x) stored\n",
     849             :                          tcon->global->tcon_global_id));
     850           0 :                 NDR_PRINT_DEBUG(smbXsrv_tconB, &tcon_blob);
     851             :         }
     852             : 
     853        5627 :         *_tcon = tcon;
     854        5627 :         return NT_STATUS_OK;
     855             : }
     856             : 
     857        5464 : NTSTATUS smbXsrv_tcon_update(struct smbXsrv_tcon *tcon)
     858             : {
     859        5464 :         struct smbXsrv_tcon_table *table = tcon->table;
     860             :         NTSTATUS status;
     861             : 
     862        5464 :         if (tcon->global->db_rec != NULL) {
     863           0 :                 DEBUG(0, ("smbXsrv_tcon_update(0x%08x): "
     864             :                           "Called with db_rec != NULL'\n",
     865             :                           tcon->global->tcon_global_id));
     866           0 :                 return NT_STATUS_INTERNAL_ERROR;
     867             :         }
     868             : 
     869       10928 :         tcon->global->db_rec = smbXsrv_tcon_global_fetch_locked(
     870             :                                                 table->global.db_ctx,
     871        5464 :                                                 tcon->global->tcon_global_id,
     872        5464 :                                                 tcon->global /* TALLOC_CTX */);
     873        5464 :         if (tcon->global->db_rec == NULL) {
     874           0 :                 return NT_STATUS_INTERNAL_DB_ERROR;
     875             :         }
     876             : 
     877        5464 :         status = smbXsrv_tcon_global_store(tcon->global);
     878        5464 :         if (!NT_STATUS_IS_OK(status)) {
     879           0 :                 DEBUG(0,("smbXsrv_tcon_update: "
     880             :                          "global_id (0x%08x) store failed - %s\n",
     881             :                          tcon->global->tcon_global_id,
     882             :                          nt_errstr(status)));
     883           0 :                 return status;
     884             :         }
     885             : 
     886        5464 :         if (DEBUGLVL(10)) {
     887           0 :                 struct smbXsrv_tconB tcon_blob = {
     888             :                         .version = SMBXSRV_VERSION_0,
     889             :                         .info.info0 = tcon,
     890             :                 };
     891             : 
     892           0 :                 DEBUG(10,("smbXsrv_tcon_update: global_id (0x%08x) stored\n",
     893             :                           tcon->global->tcon_global_id));
     894           0 :                 NDR_PRINT_DEBUG(smbXsrv_tconB, &tcon_blob);
     895             :         }
     896             : 
     897        5464 :         return NT_STATUS_OK;
     898             : }
     899             : 
     900       11242 : NTSTATUS smbXsrv_tcon_disconnect(struct smbXsrv_tcon *tcon, uint64_t vuid)
     901             : {
     902             :         struct smbXsrv_tcon_table *table;
     903       11242 :         struct db_record *local_rec = NULL;
     904       11242 :         struct db_record *global_rec = NULL;
     905             :         NTSTATUS status;
     906       11242 :         NTSTATUS error = NT_STATUS_OK;
     907             : 
     908       11242 :         if (tcon->table == NULL) {
     909        5615 :                 return NT_STATUS_OK;
     910             :         }
     911             : 
     912        5627 :         table = tcon->table;
     913        5627 :         tcon->table = NULL;
     914             : 
     915        5627 :         if (tcon->compat) {
     916             :                 bool ok;
     917             : 
     918        5615 :                 ok = chdir_current_service(tcon->compat);
     919        5615 :                 if (!ok) {
     920           8 :                         status = NT_STATUS_INTERNAL_ERROR;
     921           8 :                         DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
     922             :                                   "chdir_current_service() failed: %s\n",
     923             :                                   tcon->global->tcon_global_id,
     924             :                                   tcon->global->share_name,
     925             :                                   nt_errstr(status)));
     926             :                         /*
     927             :                          * We must call close_cnum() on
     928             :                          * error, as the caller is going
     929             :                          * to free tcon and tcon->compat
     930             :                          * so we must ensure tcon->compat is
     931             :                          * removed from the linked list
     932             :                          * conn->sconn->connections.
     933             :                          */
     934           8 :                         close_cnum(tcon->compat, vuid, ERROR_CLOSE);
     935           8 :                         tcon->compat = NULL;
     936           8 :                         return status;
     937             :                 }
     938             : 
     939        5607 :                 close_cnum(tcon->compat, vuid, SHUTDOWN_CLOSE);
     940        5607 :                 tcon->compat = NULL;
     941             :         }
     942             : 
     943        5619 :         tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
     944             : 
     945        5619 :         global_rec = tcon->global->db_rec;
     946        5619 :         tcon->global->db_rec = NULL;
     947        5619 :         if (global_rec == NULL) {
     948        5619 :                 global_rec = smbXsrv_tcon_global_fetch_locked(
     949             :                                                 table->global.db_ctx,
     950        5619 :                                                 tcon->global->tcon_global_id,
     951        5619 :                                                 tcon->global /* TALLOC_CTX */);
     952        5619 :                 if (global_rec == NULL) {
     953           0 :                         error = NT_STATUS_INTERNAL_ERROR;
     954             :                 }
     955             :         }
     956             : 
     957        5619 :         if (global_rec != NULL) {
     958        5619 :                 status = dbwrap_record_delete(global_rec);
     959        5619 :                 if (!NT_STATUS_IS_OK(status)) {
     960           0 :                         TDB_DATA key = dbwrap_record_get_key(global_rec);
     961             : 
     962           0 :                         DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
     963             :                                   "failed to delete global key '%s': %s\n",
     964             :                                   tcon->global->tcon_global_id,
     965             :                                   tcon->global->share_name,
     966             :                                   tdb_data_dbg(key),
     967             :                                   nt_errstr(status)));
     968           0 :                         error = status;
     969             :                 }
     970             :         }
     971        5619 :         TALLOC_FREE(global_rec);
     972             : 
     973        5619 :         local_rec = tcon->db_rec;
     974        5619 :         if (local_rec == NULL) {
     975        2438 :                 local_rec = smbXsrv_tcon_local_fetch_locked(table->local.db_ctx,
     976             :                                                         tcon->local_id,
     977             :                                                         tcon /* TALLOC_CTX */);
     978        2438 :                 if (local_rec == NULL) {
     979           0 :                         error = NT_STATUS_INTERNAL_ERROR;
     980             :                 }
     981             :         }
     982             : 
     983        5619 :         if (local_rec != NULL) {
     984        5619 :                 status = dbwrap_record_delete(local_rec);
     985        5619 :                 if (!NT_STATUS_IS_OK(status)) {
     986           0 :                         TDB_DATA key = dbwrap_record_get_key(local_rec);
     987             : 
     988           0 :                         DEBUG(0, ("smbXsrv_tcon_disconnect(0x%08x, '%s'): "
     989             :                                   "failed to delete local key '%s': %s\n",
     990             :                                   tcon->global->tcon_global_id,
     991             :                                   tcon->global->share_name,
     992             :                                   tdb_data_dbg(key),
     993             :                                   nt_errstr(status)));
     994           0 :                         error = status;
     995             :                 }
     996        5619 :                 table->local.num_tcons -= 1;
     997             :         }
     998        5619 :         if (tcon->db_rec == NULL) {
     999        2438 :                 TALLOC_FREE(local_rec);
    1000             :         }
    1001        5619 :         tcon->db_rec = NULL;
    1002             : 
    1003        5619 :         return error;
    1004             : }
    1005             : 
    1006             : struct smbXsrv_tcon_disconnect_all_state {
    1007             :         uint64_t vuid;
    1008             :         NTSTATUS first_status;
    1009             :         int errors;
    1010             : };
    1011             : 
    1012             : static int smbXsrv_tcon_disconnect_all_callback(struct db_record *local_rec,
    1013             :                                                 void *private_data);
    1014             : 
    1015       10165 : static NTSTATUS smbXsrv_tcon_disconnect_all(struct smbXsrv_tcon_table *table,
    1016             :                                             uint64_t vuid)
    1017             : {
    1018             :         struct smbXsrv_tcon_disconnect_all_state state;
    1019             :         NTSTATUS status;
    1020       10165 :         int count = 0;
    1021             : 
    1022       10165 :         if (table == NULL) {
    1023        5213 :                 return NT_STATUS_OK;
    1024             :         }
    1025             : 
    1026        4952 :         ZERO_STRUCT(state);
    1027        4952 :         state.vuid = vuid;
    1028             : 
    1029        4952 :         status = dbwrap_traverse(table->local.db_ctx,
    1030             :                                  smbXsrv_tcon_disconnect_all_callback,
    1031             :                                  &state, &count);
    1032        4952 :         if (!NT_STATUS_IS_OK(status)) {
    1033           0 :                 DEBUG(0, ("smbXsrv_tcon_disconnect_all: "
    1034             :                           "dbwrap_traverse() failed: %s\n",
    1035             :                           nt_errstr(status)));
    1036           0 :                 return status;
    1037             :         }
    1038             : 
    1039        4952 :         if (!NT_STATUS_IS_OK(state.first_status)) {
    1040           8 :                 DEBUG(0, ("smbXsrv_tcon_disconnect_all: "
    1041             :                           "count[%d] errors[%d] first[%s]\n",
    1042             :                           count, state.errors,
    1043             :                           nt_errstr(state.first_status)));
    1044           8 :                 return state.first_status;
    1045             :         }
    1046             : 
    1047        4944 :         return NT_STATUS_OK;
    1048             : }
    1049             : 
    1050        3189 : static int smbXsrv_tcon_disconnect_all_callback(struct db_record *local_rec,
    1051             :                                                 void *private_data)
    1052             : {
    1053        3189 :         struct smbXsrv_tcon_disconnect_all_state *state =
    1054             :                 (struct smbXsrv_tcon_disconnect_all_state *)private_data;
    1055             :         TDB_DATA val;
    1056        3189 :         void *ptr = NULL;
    1057        3189 :         struct smbXsrv_tcon *tcon = NULL;
    1058             :         uint64_t vuid;
    1059             :         NTSTATUS status;
    1060             : 
    1061        3189 :         val = dbwrap_record_get_value(local_rec);
    1062        3189 :         if (val.dsize != sizeof(ptr)) {
    1063           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    1064           0 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    1065           0 :                         state->first_status = status;
    1066             :                 }
    1067           0 :                 state->errors++;
    1068           0 :                 return 0;
    1069             :         }
    1070             : 
    1071        3189 :         memcpy(&ptr, val.dptr, val.dsize);
    1072        3189 :         tcon = talloc_get_type_abort(ptr, struct smbXsrv_tcon);
    1073             : 
    1074        3189 :         vuid = state->vuid;
    1075        3189 :         if (vuid == 0 && tcon->compat) {
    1076           0 :                 vuid = tcon->compat->vuid;
    1077             :         }
    1078             : 
    1079        3189 :         tcon->db_rec = local_rec;
    1080        3189 :         status = smbXsrv_tcon_disconnect(tcon, vuid);
    1081        3189 :         tcon->db_rec = NULL;
    1082        3189 :         if (!NT_STATUS_IS_OK(status)) {
    1083           8 :                 if (NT_STATUS_IS_OK(state->first_status)) {
    1084           8 :                         state->first_status = status;
    1085             :                 }
    1086           8 :                 state->errors++;
    1087           8 :                 return 0;
    1088             :         }
    1089             : 
    1090        3181 :         return 0;
    1091             : }
    1092             : 
    1093          38 : NTSTATUS smb1srv_tcon_table_init(struct smbXsrv_connection *conn)
    1094             : {
    1095          38 :         struct smbXsrv_client *client = conn->client;
    1096             : 
    1097             :         /*
    1098             :          * Allow a range from 1..65534 with 65534 values.
    1099             :          */
    1100          38 :         client->tcon_table = talloc_zero(client, struct smbXsrv_tcon_table);
    1101          38 :         if (client->tcon_table == NULL) {
    1102           0 :                 return NT_STATUS_NO_MEMORY;
    1103             :         }
    1104             : 
    1105          38 :         return smbXsrv_tcon_table_init(client, client->tcon_table,
    1106             :                                        1, UINT16_MAX - 1,
    1107             :                                        UINT16_MAX - 1);
    1108             : }
    1109             : 
    1110          28 : NTSTATUS smb1srv_tcon_create(struct smbXsrv_connection *conn,
    1111             :                              uint32_t session_global_id,
    1112             :                              const char *share_name,
    1113             :                              NTTIME now,
    1114             :                              struct smbXsrv_tcon **_tcon)
    1115             : {
    1116          28 :         struct server_id id = messaging_server_id(conn->client->msg_ctx);
    1117          28 :         const uint8_t encryption_flags = 0;
    1118             : 
    1119          28 :         return smbXsrv_tcon_create(conn->client->tcon_table,
    1120             :                                    conn->protocol,
    1121             :                                    id, now,
    1122             :                                    session_global_id,
    1123             :                                    encryption_flags,
    1124             :                                    share_name,
    1125             :                                    _tcon);
    1126             : }
    1127             : 
    1128        3675 : NTSTATUS smb1srv_tcon_lookup(struct smbXsrv_connection *conn,
    1129             :                              uint16_t tree_id, NTTIME now,
    1130             :                              struct smbXsrv_tcon **tcon)
    1131             : {
    1132        3675 :         uint32_t local_id = tree_id;
    1133             : 
    1134        3675 :         return smbXsrv_tcon_local_lookup(conn->client->tcon_table,
    1135             :                                          local_id, now, tcon);
    1136             : }
    1137             : 
    1138        5251 : NTSTATUS smb1srv_tcon_disconnect_all(struct smbXsrv_client *client)
    1139             : {
    1140             : 
    1141             :         /*
    1142             :          * We do not pass a vuid here,
    1143             :          * which means the vuid is taken from
    1144             :          * the tcon->compat->vuid.
    1145             :          *
    1146             :          * NOTE: that tcon->compat->vuid may point to
    1147             :          * a none existing vuid (or the wrong one)
    1148             :          * as the tcon can exist without a session
    1149             :          * in SMB1.
    1150             :          *
    1151             :          * This matches the old behavior of
    1152             :          * conn_close_all(), but we should think
    1153             :          * about how to fix this in future.
    1154             :          */
    1155        5251 :         return smbXsrv_tcon_disconnect_all(client->tcon_table, 0);
    1156             : }
    1157             : 
    1158        4914 : NTSTATUS smb2srv_tcon_table_init(struct smbXsrv_session *session)
    1159             : {
    1160             :         /*
    1161             :          * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
    1162             :          */
    1163        4914 :         session->tcon_table = talloc_zero(session, struct smbXsrv_tcon_table);
    1164        4914 :         if (session->tcon_table == NULL) {
    1165           0 :                 return NT_STATUS_NO_MEMORY;
    1166             :         }
    1167             : 
    1168        4914 :         return smbXsrv_tcon_table_init(session, session->tcon_table,
    1169             :                                        1, UINT32_MAX - 1,
    1170             :                                        UINT16_MAX - 1);
    1171             : }
    1172             : 
    1173        5599 : NTSTATUS smb2srv_tcon_create(struct smbXsrv_session *session,
    1174             :                              uint32_t session_global_id,
    1175             :                              uint8_t encryption_flags,
    1176             :                              const char *share_name,
    1177             :                              NTTIME now,
    1178             :                              struct smbXsrv_tcon **_tcon)
    1179             : {
    1180        5599 :         struct server_id id = messaging_server_id(session->client->msg_ctx);
    1181             : 
    1182        5599 :         return smbXsrv_tcon_create(session->tcon_table,
    1183             :                                    PROTOCOL_SMB2_02,
    1184             :                                    id, now,
    1185             :                                    session_global_id,
    1186             :                                    encryption_flags,
    1187             :                                    share_name,
    1188             :                                    _tcon);
    1189             : }
    1190             : 
    1191      136294 : NTSTATUS smb2srv_tcon_lookup(struct smbXsrv_session *session,
    1192             :                              uint32_t tree_id, NTTIME now,
    1193             :                              struct smbXsrv_tcon **tcon)
    1194             : {
    1195      136294 :         uint32_t local_id = tree_id;
    1196             : 
    1197      136294 :         return smbXsrv_tcon_local_lookup(session->tcon_table,
    1198             :                                          local_id, now, tcon);
    1199             : }
    1200             : 
    1201        4914 : NTSTATUS smb2srv_tcon_disconnect_all(struct smbXsrv_session *session)
    1202             : {
    1203        4914 :         uint64_t vuid = session->global->session_wire_id;
    1204             : 
    1205        4914 :         return smbXsrv_tcon_disconnect_all(session->tcon_table, vuid);
    1206             : }
    1207             : 
    1208             : struct smbXsrv_tcon_global_traverse_state {
    1209             :         int (*fn)(struct smbXsrv_tcon_global0 *, void *);
    1210             :         void *private_data;
    1211             : };
    1212             : 
    1213          91 : static int smbXsrv_tcon_global_traverse_fn(struct db_record *rec, void *data)
    1214             : {
    1215          91 :         int ret = -1;
    1216          91 :         struct smbXsrv_tcon_global_traverse_state *state =
    1217             :                 (struct smbXsrv_tcon_global_traverse_state*)data;
    1218          91 :         TDB_DATA key = dbwrap_record_get_key(rec);
    1219          91 :         TDB_DATA val = dbwrap_record_get_value(rec);
    1220          91 :         DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
    1221             :         struct smbXsrv_tcon_globalB global_blob;
    1222             :         enum ndr_err_code ndr_err;
    1223          91 :         TALLOC_CTX *frame = talloc_stackframe();
    1224             : 
    1225          91 :         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
    1226             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_tcon_globalB);
    1227          91 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1228           0 :                 DEBUG(1,("Invalid record in smbXsrv_tcon_global.tdb:"
    1229             :                          "key '%s' ndr_pull_struct_blob - %s\n",
    1230             :                          tdb_data_dbg(key),
    1231             :                          ndr_errstr(ndr_err)));
    1232           0 :                 goto done;
    1233             :         }
    1234             : 
    1235          91 :         if (global_blob.version != SMBXSRV_VERSION_0) {
    1236           0 :                 DEBUG(1,("Invalid record in smbXsrv_tcon_global.tdb:"
    1237             :                          "key '%s' unsupported version - %d\n",
    1238             :                          tdb_data_dbg(key),
    1239             :                          (int)global_blob.version));
    1240           0 :                 goto done;
    1241             :         }
    1242             : 
    1243          91 :         if (global_blob.info.info0 == NULL) {
    1244           0 :                 DEBUG(1,("Invalid record in smbXsrv_tcon_global.tdb:"
    1245             :                          "key '%s' info0 NULL pointer\n",
    1246             :                          tdb_data_dbg(key)));
    1247           0 :                 goto done;
    1248             :         }
    1249             : 
    1250          91 :         global_blob.info.info0->db_rec = rec;
    1251          91 :         ret = state->fn(global_blob.info.info0, state->private_data);
    1252          91 : done:
    1253          91 :         TALLOC_FREE(frame);
    1254          91 :         return ret;
    1255             : }
    1256             : 
    1257          21 : NTSTATUS smbXsrv_tcon_global_traverse(
    1258             :                         int (*fn)(struct smbXsrv_tcon_global0 *, void *),
    1259             :                         void *private_data)
    1260             : {
    1261             :         NTSTATUS status;
    1262          21 :         int count = 0;
    1263          21 :         struct smbXsrv_tcon_global_traverse_state state = {
    1264             :                 .fn = fn,
    1265             :                 .private_data = private_data,
    1266             :         };
    1267             : 
    1268          21 :         become_root();
    1269          21 :         status = smbXsrv_tcon_global_init();
    1270          21 :         if (!NT_STATUS_IS_OK(status)) {
    1271           0 :                 unbecome_root();
    1272           0 :                 DEBUG(0, ("Failed to initialize tcon_global: %s\n",
    1273             :                           nt_errstr(status)));
    1274           0 :                 return status;
    1275             :         }
    1276             : 
    1277          21 :         status = dbwrap_traverse_read(smbXsrv_tcon_global_db_ctx,
    1278             :                                       smbXsrv_tcon_global_traverse_fn,
    1279             :                                       &state,
    1280             :                                       &count);
    1281          21 :         unbecome_root();
    1282             : 
    1283          21 :         return status;
    1284             : }

Generated by: LCOV version 1.14