LCOV - code coverage report
Current view: top level - source3/smbd - smbXsrv_client.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 327 488 67.0 %
Date: 2021-09-23 10:06:22 Functions: 23 25 92.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Stefan Metzmacher 2014
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/filesys.h"
      22             : #include <tevent.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 "dbwrap/dbwrap_watch.h"
      30             : #include "session.h"
      31             : #include "auth.h"
      32             : #include "auth/gensec/gensec.h"
      33             : #include "../lib/tsocket/tsocket.h"
      34             : #include "../libcli/security/security.h"
      35             : #include "messages.h"
      36             : #include "lib/util/util_tdb.h"
      37             : #include "librpc/gen_ndr/ndr_smbXsrv.h"
      38             : #include "serverid.h"
      39             : #include "lib/util/tevent_ntstatus.h"
      40             : #include "lib/util/iov_buf.h"
      41             : #include "lib/global_contexts.h"
      42             : 
      43             : struct smbXsrv_client_table {
      44             :         struct {
      45             :                 uint32_t max_clients;
      46             :                 uint32_t num_clients;
      47             :         } local;
      48             :         struct {
      49             :                 struct db_context *db_ctx;
      50             :         } global;
      51             : };
      52             : 
      53             : static struct db_context *smbXsrv_client_global_db_ctx = NULL;
      54             : 
      55       27326 : NTSTATUS smbXsrv_client_global_init(void)
      56             : {
      57       27326 :         const char *global_path = NULL;
      58       27326 :         struct db_context *backend = NULL;
      59       27326 :         struct db_context *db_ctx = NULL;
      60             : 
      61       27326 :         if (smbXsrv_client_global_db_ctx != NULL) {
      62       27263 :                 return NT_STATUS_OK;
      63             :         }
      64             : 
      65             :         /*
      66             :          * This contains secret information like client keys!
      67             :          */
      68          63 :         global_path = lock_path(talloc_tos(), "smbXsrv_client_global.tdb");
      69          63 :         if (global_path == NULL) {
      70           0 :                 return NT_STATUS_NO_MEMORY;
      71             :         }
      72             : 
      73          63 :         backend = db_open(NULL, global_path,
      74             :                           0, /* hash_size */
      75             :                           TDB_DEFAULT |
      76             :                           TDB_CLEAR_IF_FIRST |
      77             :                           TDB_INCOMPATIBLE_HASH,
      78             :                           O_RDWR | O_CREAT, 0600,
      79             :                           DBWRAP_LOCK_ORDER_1,
      80             :                           DBWRAP_FLAG_NONE);
      81          63 :         if (backend == NULL) {
      82             :                 NTSTATUS status;
      83             : 
      84           0 :                 status = map_nt_error_from_unix_common(errno);
      85             : 
      86           0 :                 return status;
      87             :         }
      88             : 
      89          63 :         db_ctx = db_open_watched(NULL, &backend, global_messaging_context());
      90          63 :         if (db_ctx == NULL) {
      91           0 :                 TALLOC_FREE(backend);
      92           0 :                 return NT_STATUS_NO_MEMORY;
      93             :         }
      94             : 
      95          63 :         smbXsrv_client_global_db_ctx = db_ctx;
      96             : 
      97          63 :         return NT_STATUS_OK;
      98             : }
      99             : 
     100             : /*
     101             :  * NOTE:
     102             :  * We need to store the keys in big endian so that dbwrap_rbt's memcmp
     103             :  * has the same result as integer comparison between the uint32_t
     104             :  * values.
     105             :  *
     106             :  * TODO: implement string based key
     107             :  */
     108             : 
     109             : #define SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE 16
     110             : 
     111       42474 : static TDB_DATA smbXsrv_client_global_id_to_key(const struct GUID *client_guid,
     112             :                                                 uint8_t *key_buf)
     113             : {
     114       42474 :         TDB_DATA key = { .dsize = 0, };
     115             :         NTSTATUS status;
     116       42474 :         struct GUID_ndr_buf buf = { .buf = {0}, };
     117             : 
     118       42474 :         status = GUID_to_ndr_buf(client_guid, &buf);
     119       42474 :         if (!NT_STATUS_IS_OK(status)) {
     120           0 :                 return key;
     121             :         }
     122       42474 :         memcpy(key_buf, buf.buf, SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE);
     123             : 
     124       42474 :         key = make_tdb_data(key_buf, SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE);
     125             : 
     126       42474 :         return key;
     127             : }
     128             : 
     129       42474 : static struct db_record *smbXsrv_client_global_fetch_locked(
     130             :                         struct db_context *db,
     131             :                         const struct GUID *client_guid,
     132             :                         TALLOC_CTX *mem_ctx)
     133             : {
     134             :         TDB_DATA key;
     135             :         uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE];
     136       42474 :         struct db_record *rec = NULL;
     137             : 
     138       42474 :         key = smbXsrv_client_global_id_to_key(client_guid, key_buf);
     139             : 
     140       42474 :         rec = dbwrap_fetch_locked(db, mem_ctx, key);
     141             : 
     142       42474 :         if (rec == NULL) {
     143             :                 struct GUID_txt_buf buf;
     144           0 :                 DBG_DEBUG("Failed to lock guid [%s], key '%s'\n",
     145             :                           GUID_buf_string(client_guid, &buf),
     146             :                           hex_encode_talloc(talloc_tos(), key.dptr, key.dsize));
     147             :         }
     148             : 
     149       42474 :         return rec;
     150             : }
     151             : 
     152       27263 : static NTSTATUS smbXsrv_client_table_create(TALLOC_CTX *mem_ctx,
     153             :                                             struct messaging_context *msg_ctx,
     154             :                                             uint32_t max_clients,
     155             :                                             struct smbXsrv_client_table **_table)
     156             : {
     157             :         struct smbXsrv_client_table *table;
     158             :         NTSTATUS status;
     159             : 
     160       27263 :         if (max_clients > 1) {
     161           0 :                 return NT_STATUS_INTERNAL_ERROR;
     162             :         }
     163             : 
     164       27263 :         table = talloc_zero(mem_ctx, struct smbXsrv_client_table);
     165       27263 :         if (table == NULL) {
     166           0 :                 return NT_STATUS_NO_MEMORY;
     167             :         }
     168             : 
     169       27263 :         table->local.max_clients = max_clients;
     170             : 
     171       27263 :         status = smbXsrv_client_global_init();
     172       27263 :         if (!NT_STATUS_IS_OK(status)) {
     173           0 :                 TALLOC_FREE(table);
     174           0 :                 return status;
     175             :         }
     176             : 
     177       27263 :         table->global.db_ctx = smbXsrv_client_global_db_ctx;
     178             : 
     179       27263 :         *_table = table;
     180       27263 :         return NT_STATUS_OK;
     181             : }
     182             : 
     183       27249 : static int smbXsrv_client_global_destructor(struct smbXsrv_client_global0 *global)
     184             : {
     185       27249 :         return 0;
     186             : }
     187             : 
     188       21734 : static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
     189             :                                         bool *is_free,
     190             :                                         bool *was_free,
     191             :                                         TALLOC_CTX *mem_ctx,
     192             :                                         struct smbXsrv_client_global0 **_g)
     193             : {
     194             :         TDB_DATA key;
     195             :         TDB_DATA val;
     196             :         DATA_BLOB blob;
     197             :         struct smbXsrv_client_globalB global_blob;
     198             :         enum ndr_err_code ndr_err;
     199       21734 :         struct smbXsrv_client_global0 *global = NULL;
     200             :         bool exists;
     201       21734 :         TALLOC_CTX *frame = talloc_stackframe();
     202             : 
     203       21734 :         *is_free = false;
     204             : 
     205       21734 :         if (was_free) {
     206           0 :                 *was_free = false;
     207             :         }
     208       21734 :         if (_g) {
     209       21734 :                 *_g = NULL;
     210             :         }
     211             : 
     212       21734 :         key = dbwrap_record_get_key(db_rec);
     213             : 
     214       21734 :         val = dbwrap_record_get_value(db_rec);
     215       21734 :         if (val.dsize == 0) {
     216       20742 :                 TALLOC_FREE(frame);
     217       20742 :                 *is_free = true;
     218       20742 :                 if (was_free) {
     219           0 :                         *was_free = true;
     220             :                 }
     221       38115 :                 return;
     222             :         }
     223             : 
     224         992 :         blob = data_blob_const(val.dptr, val.dsize);
     225             : 
     226         992 :         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
     227             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_client_globalB);
     228         992 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     229           0 :                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
     230           0 :                 DBG_WARNING("smbXsrv_client_global_verify_record: "
     231             :                             "key '%s' ndr_pull_struct_blob - %s\n",
     232             :                             hex_encode_talloc(frame, key.dptr, key.dsize),
     233             :                             nt_errstr(status));
     234           0 :                 TALLOC_FREE(frame);
     235           0 :                 return;
     236             :         }
     237             : 
     238         992 :         DBG_DEBUG("client_global:\n");
     239         992 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     240           0 :                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
     241             :         }
     242             : 
     243         992 :         if (global_blob.version != SMBXSRV_VERSION_0) {
     244           0 :                 DBG_ERR("key '%s' use unsupported version %u\n",
     245             :                         hex_encode_talloc(frame, key.dptr, key.dsize),
     246             :                         global_blob.version);
     247           0 :                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
     248           0 :                 TALLOC_FREE(frame);
     249           0 :                 return;
     250             :         }
     251             : 
     252         992 :         global = global_blob.info.info0;
     253             : 
     254         992 :         exists = serverid_exists(&global->server_id);
     255         992 :         if (!exists) {
     256             :                 struct server_id_buf tmp;
     257             : 
     258           0 :                 DBG_NOTICE("key '%s' server_id %s does not exist.\n",
     259             :                            hex_encode_talloc(frame, key.dptr, key.dsize),
     260             :                            server_id_str_buf(global->server_id, &tmp));
     261           0 :                 if (DEBUGLVL(DBGLVL_NOTICE)) {
     262           0 :                         NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
     263             :                 }
     264           0 :                 TALLOC_FREE(frame);
     265           0 :                 dbwrap_record_delete(db_rec);
     266           0 :                 *is_free = true;
     267           0 :                 return;
     268             :         }
     269             : 
     270         992 :         if (_g) {
     271         992 :                 *_g = talloc_move(mem_ctx, &global);
     272             :         }
     273         992 :         TALLOC_FREE(frame);
     274             : }
     275             : 
     276         992 : static NTSTATUS smb2srv_client_connection_pass(struct smbd_smb2_request *smb2req,
     277             :                                                struct smbXsrv_client_global0 *global)
     278             : {
     279             :         DATA_BLOB blob;
     280             :         enum ndr_err_code ndr_err;
     281             :         NTSTATUS status;
     282             :         struct smbXsrv_connection_pass0 pass_info0;
     283             :         struct smbXsrv_connection_passB pass_blob;
     284             :         ssize_t reqlen;
     285             :         struct iovec iov;
     286             : 
     287         992 :         pass_info0 = (struct smbXsrv_connection_pass0) {
     288         992 :                 .client_guid = global->client_guid,
     289         992 :                 .src_server_id = smb2req->xconn->client->global->server_id,
     290         992 :                 .xconn_connect_time = smb2req->xconn->client->global->initial_connect_time,
     291         992 :                 .dst_server_id = global->server_id,
     292         992 :                 .client_connect_time = global->initial_connect_time,
     293             :         };
     294             : 
     295         992 :         reqlen = iov_buflen(smb2req->in.vector, smb2req->in.vector_count);
     296         992 :         if (reqlen == -1) {
     297           0 :                 return NT_STATUS_INVALID_BUFFER_SIZE;
     298             :         }
     299             : 
     300         992 :         pass_info0.negotiate_request.length = reqlen;
     301         992 :         pass_info0.negotiate_request.data = talloc_array(talloc_tos(), uint8_t,
     302             :                                                          reqlen);
     303         992 :         if (pass_info0.negotiate_request.data == NULL) {
     304           0 :                 return NT_STATUS_NO_MEMORY;
     305             :         }
     306         992 :         iov_buf(smb2req->in.vector, smb2req->in.vector_count,
     307             :                 pass_info0.negotiate_request.data,
     308             :                 pass_info0.negotiate_request.length);
     309             : 
     310         992 :         ZERO_STRUCT(pass_blob);
     311         992 :         pass_blob.version = smbXsrv_version_global_current();
     312         992 :         pass_blob.info.info0 = &pass_info0;
     313             : 
     314         992 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     315           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
     316             :         }
     317             : 
     318         992 :         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &pass_blob,
     319             :                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_connection_passB);
     320         992 :         data_blob_free(&pass_info0.negotiate_request);
     321         992 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     322           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     323           0 :                 return status;
     324             :         }
     325             : 
     326         992 :         iov.iov_base = blob.data;
     327         992 :         iov.iov_len = blob.length;
     328             : 
     329         992 :         status = messaging_send_iov(smb2req->xconn->client->msg_ctx,
     330             :                                     global->server_id,
     331             :                                     MSG_SMBXSRV_CONNECTION_PASS,
     332             :                                     &iov, 1,
     333         992 :                                     &smb2req->xconn->transport.sock, 1);
     334         992 :         data_blob_free(&blob);
     335         992 :         if (!NT_STATUS_IS_OK(status)) {
     336           0 :                 return status;
     337             :         }
     338             : 
     339         992 :         return NT_STATUS_OK;
     340             : }
     341             : 
     342       20742 : static NTSTATUS smbXsrv_client_global_store(struct smbXsrv_client_global0 *global)
     343             : {
     344             :         struct smbXsrv_client_globalB global_blob;
     345       20742 :         DATA_BLOB blob = data_blob_null;
     346             :         TDB_DATA key;
     347             :         TDB_DATA val;
     348             :         NTSTATUS status;
     349             :         enum ndr_err_code ndr_err;
     350       20742 :         bool saved_stored = global->stored;
     351             : 
     352             :         /*
     353             :          * TODO: if we use other versions than '0'
     354             :          * we would add glue code here, that would be able to
     355             :          * store the information in the old format.
     356             :          */
     357             : 
     358       20742 :         SMB_ASSERT(global->local_address != NULL);
     359       20742 :         SMB_ASSERT(global->remote_address != NULL);
     360       20742 :         SMB_ASSERT(global->remote_name != NULL);
     361             : 
     362       20742 :         if (global->db_rec == NULL) {
     363           0 :                 return NT_STATUS_INTERNAL_ERROR;
     364             :         }
     365             : 
     366       20742 :         key = dbwrap_record_get_key(global->db_rec);
     367       20742 :         val = dbwrap_record_get_value(global->db_rec);
     368             : 
     369       20742 :         ZERO_STRUCT(global_blob);
     370       20742 :         global_blob.version = smbXsrv_version_global_current();
     371       20742 :         if (val.dsize >= 8) {
     372           0 :                 global_blob.seqnum = IVAL(val.dptr, 4);
     373             :         }
     374       20742 :         global_blob.seqnum += 1;
     375       20742 :         global_blob.info.info0 = global;
     376             : 
     377       20742 :         global->stored = true;
     378       20742 :         ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
     379             :                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_client_globalB);
     380       20742 :         global->stored = saved_stored;
     381       20742 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     382           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     383           0 :                 DBG_WARNING("key '%s' ndr_push - %s\n",
     384             :                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
     385             :                         nt_errstr(status));
     386           0 :                 TALLOC_FREE(global->db_rec);
     387           0 :                 return status;
     388             :         }
     389             : 
     390       20742 :         val = make_tdb_data(blob.data, blob.length);
     391       20742 :         status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
     392       20742 :         if (!NT_STATUS_IS_OK(status)) {
     393           0 :                 DBG_WARNING("key '%s' store - %s\n",
     394             :                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
     395             :                         nt_errstr(status));
     396           0 :                 TALLOC_FREE(global->db_rec);
     397           0 :                 return status;
     398             :         }
     399             : 
     400       20742 :         global->stored = true;
     401             : 
     402       20742 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     403           0 :                 DBG_DEBUG("key '%s' stored\n",
     404             :                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize));
     405           0 :                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
     406             :         }
     407             : 
     408       20742 :         TALLOC_FREE(global->db_rec);
     409             : 
     410       20742 :         return NT_STATUS_OK;
     411             : }
     412             : 
     413             : struct smb2srv_client_mc_negprot_state {
     414             :         struct tevent_context *ev;
     415             :         struct smbd_smb2_request *smb2req;
     416             :         struct db_record *db_rec;
     417             : };
     418             : 
     419       43468 : static void smb2srv_client_mc_negprot_cleanup(struct tevent_req *req,
     420             :                                               enum tevent_req_state req_state)
     421             : {
     422       37038 :         struct smb2srv_client_mc_negprot_state *state =
     423       43468 :                 tevent_req_data(req,
     424             :                 struct smb2srv_client_mc_negprot_state);
     425             : 
     426       43468 :         TALLOC_FREE(state->db_rec);
     427       43468 : }
     428             : 
     429             : static void smb2srv_client_mc_negprot_next(struct tevent_req *req);
     430             : static bool smb2srv_client_mc_negprot_filter(struct messaging_rec *rec, void *private_data);
     431             : static void smb2srv_client_mc_negprot_done(struct tevent_req *subreq);
     432             : static void smb2srv_client_mc_negprot_watched(struct tevent_req *subreq);
     433             : 
     434       21734 : struct tevent_req *smb2srv_client_mc_negprot_send(TALLOC_CTX *mem_ctx,
     435             :                                                   struct tevent_context *ev,
     436             :                                                   struct smbd_smb2_request *smb2req)
     437             : {
     438       21734 :         struct tevent_req *req = NULL;
     439       21734 :         struct smb2srv_client_mc_negprot_state *state = NULL;
     440             : 
     441       21734 :         req = tevent_req_create(mem_ctx, &state,
     442             :                                 struct smb2srv_client_mc_negprot_state);
     443       21734 :         if (req == NULL) {
     444           0 :                 return NULL;
     445             :         }
     446       21734 :         state->ev = ev;
     447       21734 :         state->smb2req = smb2req;
     448             : 
     449       21734 :         tevent_req_set_cleanup_fn(req, smb2srv_client_mc_negprot_cleanup);
     450             : 
     451       21734 :         smb2srv_client_mc_negprot_next(req);
     452             : 
     453       21734 :         if (!tevent_req_is_in_progress(req)) {
     454       20742 :                 return tevent_req_post(req, ev);
     455             :         }
     456             : 
     457         992 :         return req;
     458             : }
     459             : 
     460       21734 : static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
     461             : {
     462       18519 :         struct smb2srv_client_mc_negprot_state *state =
     463       21734 :                 tevent_req_data(req,
     464             :                 struct smb2srv_client_mc_negprot_state);
     465       21734 :         struct smbXsrv_connection *xconn = state->smb2req->xconn;
     466       21734 :         struct smbXsrv_client *client = xconn->client;
     467       21734 :         struct smbXsrv_client_table *table = client->table;
     468       21734 :         struct GUID client_guid = xconn->smb2.client.guid;
     469       21734 :         struct smbXsrv_client_global0 *global = NULL;
     470       21734 :         bool is_free = false;
     471       21734 :         struct tevent_req *subreq = NULL;
     472             :         NTSTATUS status;
     473             : 
     474       21734 :         SMB_ASSERT(state->db_rec == NULL);
     475       21734 :         state->db_rec = smbXsrv_client_global_fetch_locked(table->global.db_ctx,
     476             :                                                            &client_guid,
     477             :                                                            state);
     478       21734 :         if (state->db_rec == NULL) {
     479           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_DB_ERROR);
     480           0 :                 return;
     481             :         }
     482             : 
     483       21734 :         smbXsrv_client_global_verify_record(state->db_rec,
     484             :                                             &is_free,
     485             :                                             NULL,
     486             :                                             state,
     487             :                                             &global);
     488       21734 :         if (is_free) {
     489             :                 /*
     490             :                  * This stores the new client information in
     491             :                  * smbXsrv_client_global.tdb
     492             :                  */
     493       20742 :                 client->global->client_guid = xconn->smb2.client.guid;
     494             : 
     495       20742 :                 client->global->db_rec = state->db_rec;
     496       20742 :                 state->db_rec = NULL;
     497       20742 :                 status = smbXsrv_client_global_store(client->global);
     498       20742 :                 SMB_ASSERT(client->global->db_rec == NULL);
     499       20742 :                 if (!NT_STATUS_IS_OK(status)) {
     500             :                         struct GUID_txt_buf buf;
     501           0 :                         DBG_ERR("client_guid[%s] store failed - %s\n",
     502             :                                 GUID_buf_string(&client->global->client_guid,
     503             :                                                 &buf),
     504             :                                 nt_errstr(status));
     505           0 :                         tevent_req_nterror(req, status);
     506           0 :                         return;
     507             :                 }
     508             : 
     509       20742 :                 if (DEBUGLVL(DBGLVL_DEBUG)) {
     510           0 :                         struct smbXsrv_clientB client_blob = {
     511             :                                 .version = SMBXSRV_VERSION_0,
     512             :                                 .info.info0 = client,
     513             :                         };
     514             :                         struct GUID_txt_buf buf;
     515             : 
     516           0 :                         DBG_DEBUG("client_guid[%s] stored\n",
     517             :                                   GUID_buf_string(&client->global->client_guid,
     518             :                                                   &buf));
     519           0 :                         NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
     520             :                 }
     521             : 
     522       20742 :                 xconn->smb2.client.guid_verified = true;
     523       20742 :                 tevent_req_done(req);
     524       20742 :                 return;
     525             :         }
     526             : 
     527         992 :         if (global == NULL) {
     528             :                 /*
     529             :                  * most likely ndr_pull_struct_blob() failed
     530             :                  */
     531           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_DB_CORRUPTION);
     532           0 :                 return;
     533             :         }
     534             : 
     535         992 :         subreq = messaging_filtered_read_send(state,
     536             :                                               state->ev,
     537             :                                               client->msg_ctx,
     538             :                                               smb2srv_client_mc_negprot_filter,
     539             :                                               NULL);
     540         992 :         if (tevent_req_nomem(subreq, req)) {
     541           0 :                 return;
     542             :         }
     543         992 :         tevent_req_set_callback(subreq, smb2srv_client_mc_negprot_done, req);
     544             : 
     545         992 :         subreq = dbwrap_watched_watch_send(state,
     546             :                                            state->ev,
     547             :                                            state->db_rec,
     548         992 :                                            global->server_id);
     549         992 :         if (tevent_req_nomem(subreq, req)) {
     550           0 :                 return;
     551             :         }
     552         992 :         tevent_req_set_callback(subreq, smb2srv_client_mc_negprot_watched, req);
     553             : 
     554         992 :         status = smb2srv_client_connection_pass(state->smb2req,
     555             :                                                 global);
     556         992 :         TALLOC_FREE(global);
     557         992 :         if (tevent_req_nterror(req, status)) {
     558           0 :                 return;
     559             :         }
     560             : 
     561         992 :         TALLOC_FREE(state->db_rec);
     562         992 :         return;
     563             : }
     564             : 
     565         992 : static bool smb2srv_client_mc_negprot_filter(struct messaging_rec *rec, void *private_data)
     566             : {
     567         992 :         if (rec->msg_type != MSG_SMBXSRV_CONNECTION_PASSED) {
     568           0 :                 return false;
     569             :         }
     570             : 
     571         992 :         if (rec->num_fds != 0) {
     572           0 :                 return false;
     573             :         }
     574             : 
     575         992 :         if (rec->buf.length < SMB2_HDR_BODY) {
     576           0 :                 return false;
     577             :         }
     578             : 
     579         992 :         return true;
     580             : }
     581             : 
     582         992 : static void smb2srv_client_mc_negprot_done(struct tevent_req *subreq)
     583             : {
     584         756 :         struct tevent_req *req =
     585         992 :                 tevent_req_callback_data(subreq,
     586             :                 struct tevent_req);
     587         756 :         struct smb2srv_client_mc_negprot_state *state =
     588         992 :                 tevent_req_data(req,
     589             :                 struct smb2srv_client_mc_negprot_state);
     590         992 :         struct smbXsrv_connection *xconn = state->smb2req->xconn;
     591         992 :         struct smbXsrv_client *client = xconn->client;
     592         992 :         struct messaging_rec *rec = NULL;
     593             :         struct smbXsrv_connection_passB passed_blob;
     594             :         enum ndr_err_code ndr_err;
     595         992 :         struct smbXsrv_connection_pass0 *passed_info0 = NULL;
     596             :         NTSTATUS status;
     597             :         int ret;
     598             : 
     599         992 :         ret = messaging_filtered_read_recv(subreq, state, &rec);
     600         992 :         TALLOC_FREE(subreq);
     601         992 :         if (ret != 0) {
     602           0 :                 status = map_nt_error_from_unix_common(ret);
     603           0 :                 DBG_ERR("messaging_filtered_read_recv() - %s\n",
     604             :                         nt_errstr(status));
     605           0 :                 tevent_req_nterror(req, status);
     606           0 :                 return;
     607             :         }
     608             : 
     609         992 :         DBG_DEBUG("MSG_SMBXSRV_CONNECTION_PASSED: received...\n");
     610             : 
     611         992 :         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &passed_blob,
     612             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_connection_passB);
     613         992 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     614           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     615           0 :                 DBG_ERR("ndr_pull_struct_blob - %s\n", nt_errstr(status));
     616           0 :                 tevent_req_nterror(req, status);
     617           0 :                 return;
     618             :         }
     619             : 
     620         992 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     621           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
     622             :         }
     623             : 
     624         992 :         if (passed_blob.version != SMBXSRV_VERSION_0) {
     625           0 :                 DBG_ERR("ignore invalid version %u\n", passed_blob.version);
     626           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
     627           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     628           0 :                 return;
     629             :         }
     630             : 
     631         992 :         passed_info0 = passed_blob.info.info0;
     632         992 :         if (passed_info0 == NULL) {
     633           0 :                 DBG_ERR("ignore NULL info %u\n", passed_blob.version);
     634           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
     635           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     636           0 :                 return;
     637             :         }
     638             : 
     639         992 :         if (!GUID_equal(&xconn->smb2.client.guid, &passed_info0->client_guid)) {
     640             :                 struct GUID_txt_buf buf1, buf2;
     641             : 
     642           0 :                 DBG_ERR("client's client_guid [%s] != passed guid [%s]\n",
     643             :                         GUID_buf_string(&xconn->smb2.client.guid,
     644             :                                         &buf1),
     645             :                         GUID_buf_string(&passed_info0->client_guid,
     646             :                                         &buf2));
     647           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
     648           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     649           0 :                 return;
     650             :         }
     651             : 
     652        1748 :         if (client->global->initial_connect_time !=
     653         992 :             passed_info0->xconn_connect_time)
     654             :         {
     655           0 :                 DBG_ERR("client's initial connect time [%s] (%llu) != "
     656             :                         "passed xconn connect time [%s] (%llu)\n",
     657             :                         nt_time_string(talloc_tos(),
     658             :                                        client->global->initial_connect_time),
     659             :                         (unsigned long long)client->global->initial_connect_time,
     660             :                         nt_time_string(talloc_tos(),
     661             :                                        passed_info0->xconn_connect_time),
     662             :                         (unsigned long long)passed_info0->xconn_connect_time);
     663           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
     664           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     665           0 :                 return;
     666             :         }
     667             : 
     668         992 :         tevent_req_nterror(req, NT_STATUS_MESSAGE_RETRIEVED);
     669             : }
     670             : 
     671           0 : static void smb2srv_client_mc_negprot_watched(struct tevent_req *subreq)
     672             : {
     673           0 :         struct tevent_req *req =
     674           0 :                 tevent_req_callback_data(subreq,
     675             :                 struct tevent_req);
     676             :         NTSTATUS status;
     677             : 
     678           0 :         status = dbwrap_watched_watch_recv(subreq, NULL, NULL);
     679           0 :         TALLOC_FREE(subreq);
     680           0 :         if (tevent_req_nterror(req, status)) {
     681           0 :                 return;
     682             :         }
     683             : 
     684           0 :         smb2srv_client_mc_negprot_next(req);
     685             : }
     686             : 
     687       21734 : NTSTATUS smb2srv_client_mc_negprot_recv(struct tevent_req *req)
     688             : {
     689       21734 :         return tevent_req_simple_recv_ntstatus(req);
     690             : }
     691             : 
     692       20740 : static NTSTATUS smbXsrv_client_global_remove(struct smbXsrv_client_global0 *global)
     693             : {
     694             :         TDB_DATA key;
     695             :         NTSTATUS status;
     696             : 
     697             :         /*
     698             :          * TODO: if we use other versions than '0'
     699             :          * we would add glue code here, that would be able to
     700             :          * store the information in the old format.
     701             :          */
     702             : 
     703       20740 :         if (global->db_rec == NULL) {
     704           0 :                 return NT_STATUS_INTERNAL_ERROR;
     705             :         }
     706             : 
     707       20740 :         key = dbwrap_record_get_key(global->db_rec);
     708             : 
     709       20740 :         status = dbwrap_record_delete(global->db_rec);
     710       20740 :         if (!NT_STATUS_IS_OK(status)) {
     711           0 :                 DBG_WARNING("key '%s' delete - %s\n",
     712             :                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
     713             :                         nt_errstr(status));
     714           0 :                 TALLOC_FREE(global->db_rec);
     715           0 :                 return status;
     716             :         }
     717       20740 :         global->stored = false;
     718       20740 :         DBG_DEBUG("key '%s' delete\n",
     719             :                   hex_encode_talloc(global->db_rec, key.dptr, key.dsize));
     720             : 
     721       20740 :         TALLOC_FREE(global->db_rec);
     722             : 
     723       20740 :         return NT_STATUS_OK;
     724             : }
     725             : 
     726       27249 : static int smbXsrv_client_destructor(struct smbXsrv_client *client)
     727             : {
     728             :         NTSTATUS status;
     729             : 
     730       27249 :         status = smbXsrv_client_remove(client);
     731       27249 :         if (!NT_STATUS_IS_OK(status)) {
     732           0 :                 DBG_ERR("smbXsrv_client_remove() failed: %s\n",
     733             :                         nt_errstr(status));
     734             :         }
     735             : 
     736       27249 :         TALLOC_FREE(client->global);
     737             : 
     738       27249 :         return 0;
     739             : }
     740             : 
     741             : static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data);
     742             : static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq);
     743             : 
     744       27263 : NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx,
     745             :                                struct tevent_context *ev_ctx,
     746             :                                struct messaging_context *msg_ctx,
     747             :                                NTTIME now,
     748             :                                struct smbXsrv_client **_client)
     749             : {
     750             :         struct smbXsrv_client_table *table;
     751       27263 :         struct smbXsrv_client *client = NULL;
     752       27263 :         struct smbXsrv_client_global0 *global = NULL;
     753             :         NTSTATUS status;
     754       27263 :         struct tevent_req *subreq = NULL;
     755             : 
     756       27263 :         status = smbXsrv_client_table_create(mem_ctx,
     757             :                                              msg_ctx,
     758             :                                              1, /* max_clients */
     759             :                                              &table);
     760       27263 :         if (!NT_STATUS_IS_OK(status)) {
     761           0 :                 return status;
     762             :         }
     763             : 
     764       27263 :         if (table->local.num_clients >= table->local.max_clients) {
     765           0 :                 TALLOC_FREE(table);
     766           0 :                 return NT_STATUS_INSUFFICIENT_RESOURCES;
     767             :         }
     768             : 
     769       27263 :         client = talloc_zero(mem_ctx, struct smbXsrv_client);
     770       27263 :         if (client == NULL) {
     771           0 :                 TALLOC_FREE(table);
     772           0 :                 return NT_STATUS_NO_MEMORY;
     773             :         }
     774       27263 :         client->raw_ev_ctx = ev_ctx;
     775       27263 :         client->msg_ctx = msg_ctx;
     776             : 
     777       27263 :         client->server_multi_channel_enabled =
     778       27263 :                 smbXsrv_server_multi_channel_enabled();
     779       27263 :         if (client->server_multi_channel_enabled) {
     780       27263 :                 client->next_channel_id = 1;
     781             :         }
     782       27263 :         client->table = talloc_move(client, &table);
     783       27263 :         table = client->table;
     784             : 
     785       27263 :         global = talloc_zero(client, struct smbXsrv_client_global0);
     786       27263 :         if (global == NULL) {
     787           0 :                 TALLOC_FREE(client);
     788           0 :                 return NT_STATUS_NO_MEMORY;
     789             :         }
     790       27263 :         talloc_set_destructor(global, smbXsrv_client_global_destructor);
     791       27263 :         client->global = global;
     792             : 
     793       27263 :         global->initial_connect_time = now;
     794             : 
     795       27263 :         global->server_id = messaging_server_id(client->msg_ctx);
     796             : 
     797       27263 :         table->local.num_clients += 1;
     798             : 
     799       27263 :         talloc_set_destructor(client, smbXsrv_client_destructor);
     800             : 
     801       27263 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     802           0 :                 struct smbXsrv_clientB client_blob = {
     803             :                         .version = SMBXSRV_VERSION_0,
     804             :                         .info.info0 = client,
     805             :                 };
     806             :                 struct GUID_txt_buf buf;
     807             : 
     808           0 :                 DBG_DEBUG("client_guid[%s] created\n",
     809             :                           GUID_buf_string(&global->client_guid, &buf));
     810           0 :                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
     811             :         }
     812             : 
     813       27263 :         subreq = messaging_filtered_read_send(client,
     814             :                                         client->raw_ev_ctx,
     815             :                                         client->msg_ctx,
     816             :                                         smbXsrv_client_connection_pass_filter,
     817             :                                         client);
     818       27263 :         if (subreq == NULL) {
     819           0 :                 TALLOC_FREE(client);
     820           0 :                 return NT_STATUS_NO_MEMORY;
     821             :         }
     822       27263 :         tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
     823       27263 :         client->connection_pass_subreq = subreq;
     824             : 
     825       27263 :         *_client = client;
     826       27263 :         return NT_STATUS_OK;
     827             : }
     828             : 
     829         930 : static NTSTATUS smb2srv_client_connection_passed(struct smbXsrv_client *client,
     830             :                                 const struct smbXsrv_connection_pass0 *recv_info0)
     831             : {
     832             :         DATA_BLOB blob;
     833             :         enum ndr_err_code ndr_err;
     834             :         NTSTATUS status;
     835             :         struct smbXsrv_connection_pass0 passed_info0;
     836             :         struct smbXsrv_connection_passB passed_blob;
     837             :         struct iovec iov;
     838             : 
     839             :         /*
     840             :          * We echo back the message with a cleared negotiate_request
     841             :          */
     842         930 :         passed_info0 = *recv_info0;
     843         930 :         passed_info0.negotiate_request = data_blob_null;
     844             : 
     845         930 :         ZERO_STRUCT(passed_blob);
     846         930 :         passed_blob.version = smbXsrv_version_global_current();
     847         930 :         passed_blob.info.info0 = &passed_info0;
     848             : 
     849         930 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     850           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
     851             :         }
     852             : 
     853         930 :         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &passed_blob,
     854             :                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_connection_passB);
     855         930 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     856           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     857           0 :                 return status;
     858             :         }
     859             : 
     860         930 :         iov.iov_base = blob.data;
     861         930 :         iov.iov_len = blob.length;
     862             : 
     863         930 :         status = messaging_send_iov(client->msg_ctx,
     864             :                                     recv_info0->src_server_id,
     865             :                                     MSG_SMBXSRV_CONNECTION_PASSED,
     866             :                                     &iov, 1,
     867             :                                     NULL, 0);
     868         930 :         data_blob_free(&blob);
     869         930 :         if (!NT_STATUS_IS_OK(status)) {
     870           0 :                 return status;
     871             :         }
     872             : 
     873         930 :         return NT_STATUS_OK;
     874             : }
     875             : 
     876       45005 : static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data)
     877             : {
     878       45005 :         if (rec->msg_type != MSG_SMBXSRV_CONNECTION_PASS) {
     879       44073 :                 return false;
     880             :         }
     881             : 
     882         930 :         if (rec->num_fds != 1) {
     883           0 :                 return false;
     884             :         }
     885             : 
     886         930 :         if (rec->buf.length < SMB2_HDR_BODY) {
     887           0 :                 return false;
     888             :         }
     889             : 
     890             :         /* TODO: verify client_guid...? */
     891             : 
     892         930 :         return true;
     893             : }
     894             : 
     895         930 : static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq)
     896             : {
     897         694 :         struct smbXsrv_client *client =
     898         930 :                 tevent_req_callback_data(subreq,
     899             :                 struct smbXsrv_client);
     900         930 :         struct smbXsrv_connection *xconn = NULL;
     901             :         int ret;
     902         930 :         struct messaging_rec *rec = NULL;
     903             :         struct smbXsrv_connection_passB pass_blob;
     904             :         enum ndr_err_code ndr_err;
     905         930 :         struct smbXsrv_connection_pass0 *pass_info0 = NULL;
     906             :         NTSTATUS status;
     907         930 :         int sock_fd = -1;
     908             :         uint64_t seq_low;
     909             : 
     910         930 :         client->connection_pass_subreq = NULL;
     911             : 
     912         930 :         ret = messaging_filtered_read_recv(subreq, talloc_tos(), &rec);
     913         930 :         TALLOC_FREE(subreq);
     914         930 :         if (ret != 0) {
     915           0 :                 goto next;
     916             :         }
     917             : 
     918         930 :         if (rec->num_fds != 1) {
     919           0 :                 DBG_ERR("MSG_SMBXSRV_CONNECTION_PASS: num_fds[%u]\n",
     920             :                         rec->num_fds);
     921           0 :                 goto next;
     922             :         }
     923             : 
     924         930 :         sock_fd = rec->fds[0];
     925         930 :         DBG_DEBUG("MSG_SMBXSRV_CONNECTION_PASS: got sock_fd[%d]\n", sock_fd);
     926             : 
     927         930 :         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &pass_blob,
     928             :                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_connection_passB);
     929         930 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     930           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     931           0 :                 DBG_WARNING("ndr_pull_struct_blob - %s\n", nt_errstr(status));
     932           0 :                 goto next;
     933             :         }
     934             : 
     935         930 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
     936           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
     937             :         }
     938             : 
     939         930 :         if (pass_blob.version != SMBXSRV_VERSION_0) {
     940           0 :                 DBG_ERR("ignore invalid version %u\n", pass_blob.version);
     941           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
     942           0 :                 goto next;
     943             :         }
     944             : 
     945         930 :         pass_info0 = pass_blob.info.info0;
     946         930 :         if (pass_info0 == NULL) {
     947           0 :                 DBG_ERR("ignore NULL info %u\n", pass_blob.version);
     948           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
     949           0 :                 goto next;
     950             :         }
     951             : 
     952         930 :         if (!GUID_equal(&client->global->client_guid, &pass_info0->client_guid))
     953             :         {
     954             :                 struct GUID_txt_buf buf1, buf2;
     955             : 
     956           0 :                 DBG_WARNING("client's client_guid [%s] != passed guid [%s]\n",
     957             :                             GUID_buf_string(&client->global->client_guid,
     958             :                                             &buf1),
     959             :                             GUID_buf_string(&pass_info0->client_guid,
     960             :                                             &buf2));
     961           0 :                 if (DEBUGLVL(DBGLVL_WARNING)) {
     962           0 :                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
     963             :                 }
     964           0 :                 goto next;
     965             :         }
     966             : 
     967        1624 :         if (client->global->initial_connect_time !=
     968         930 :             pass_info0->client_connect_time)
     969             :         {
     970           0 :                 DBG_WARNING("client's initial connect time [%s] (%llu) != "
     971             :                         "passed initial connect time [%s] (%llu)\n",
     972             :                         nt_time_string(talloc_tos(),
     973             :                                        client->global->initial_connect_time),
     974             :                         (unsigned long long)client->global->initial_connect_time,
     975             :                         nt_time_string(talloc_tos(),
     976             :                                        pass_info0->client_connect_time),
     977             :                         (unsigned long long)pass_info0->client_connect_time);
     978           0 :                 if (DEBUGLVL(DBGLVL_WARNING)) {
     979           0 :                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
     980             :                 }
     981           0 :                 goto next;
     982             :         }
     983             : 
     984         930 :         status = smb2srv_client_connection_passed(client, pass_info0);
     985         930 :         if (!NT_STATUS_IS_OK(status)) {
     986           0 :                 const char *r = "smb2srv_client_connection_passed() failed";
     987           0 :                 DBG_ERR("%s => %s\n", r, nt_errstr(status));
     988           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
     989           0 :                 exit_server_cleanly(r);
     990             :                 return;
     991             :         }
     992             : 
     993         930 :         status = smbd_add_connection(client,
     994             :                                      sock_fd,
     995             :                                      pass_info0->xconn_connect_time,
     996             :                                      &xconn);
     997         930 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
     998           0 :                 rec->num_fds = 0;
     999           0 :                 smbd_server_connection_terminate(xconn, nt_errstr(status));
    1000             :         }
    1001         930 :         if (!NT_STATUS_IS_OK(status)) {
    1002           0 :                 DBG_ERR("smbd_add_connection => %s\n", nt_errstr(status));
    1003           0 :                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
    1004           0 :                 goto next;
    1005             :         }
    1006         930 :         rec->num_fds = 0;
    1007             : 
    1008             :         /*
    1009             :          * Set seq_low to mid received in negprot
    1010             :          */
    1011         930 :         seq_low = BVAL(pass_info0->negotiate_request.data,
    1012             :                        SMB2_HDR_MESSAGE_ID);
    1013             : 
    1014         930 :         xconn->smb2.client.guid_verified = true;
    1015        1624 :         smbd_smb2_process_negprot(xconn, seq_low,
    1016         930 :                                   pass_info0->negotiate_request.data,
    1017             :                                   pass_info0->negotiate_request.length);
    1018             : 
    1019         930 : next:
    1020         930 :         if (rec != NULL) {
    1021             :                 uint8_t fd_idx;
    1022             : 
    1023         930 :                 for (fd_idx = 0; fd_idx < rec->num_fds; fd_idx++) {
    1024           0 :                         sock_fd = rec->fds[fd_idx];
    1025           0 :                         close(sock_fd);
    1026             :                 }
    1027         930 :                 rec->num_fds = 0;
    1028             : 
    1029         930 :                 TALLOC_FREE(rec);
    1030             :         }
    1031             : 
    1032         930 :         subreq = messaging_filtered_read_send(client,
    1033             :                                         client->raw_ev_ctx,
    1034             :                                         client->msg_ctx,
    1035             :                                         smbXsrv_client_connection_pass_filter,
    1036             :                                         client);
    1037         930 :         if (subreq == NULL) {
    1038             :                 const char *r;
    1039           0 :                 r = "messaging_read_send(MSG_SMBXSRV_CONNECTION_PASS failed";
    1040           0 :                 exit_server_cleanly(r);
    1041             :                 return;
    1042             :         }
    1043         930 :         tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
    1044         930 :         client->connection_pass_subreq = subreq;
    1045         694 : }
    1046             : 
    1047       54498 : NTSTATUS smbXsrv_client_remove(struct smbXsrv_client *client)
    1048             : {
    1049       54498 :         struct smbXsrv_client_table *table = client->table;
    1050             :         NTSTATUS status;
    1051             : 
    1052       54498 :         if (client->global->db_rec != NULL) {
    1053             :                 struct GUID_txt_buf buf;
    1054           0 :                 DBG_ERR("client_guid[%s]: Called with db_rec != NULL'\n",
    1055             :                         GUID_buf_string(&client->global->client_guid,
    1056             :                                         &buf));
    1057           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1058             :         }
    1059             : 
    1060       54498 :         if (!client->global->stored) {
    1061       33758 :                 return NT_STATUS_OK;
    1062             :         }
    1063             : 
    1064       20740 :         TALLOC_FREE(client->connection_pass_subreq);
    1065             : 
    1066       23719 :         client->global->db_rec = smbXsrv_client_global_fetch_locked(
    1067             :                                         table->global.db_ctx,
    1068       20740 :                                         &client->global->client_guid,
    1069       20740 :                                         client->global /* TALLOC_CTX */);
    1070       20740 :         if (client->global->db_rec == NULL) {
    1071           0 :                 return NT_STATUS_INTERNAL_DB_ERROR;
    1072             :         }
    1073             : 
    1074       20740 :         status = smbXsrv_client_global_remove(client->global);
    1075       20740 :         if (!NT_STATUS_IS_OK(status)) {
    1076             :                 struct GUID_txt_buf buf;
    1077           0 :                 DBG_ERR("client_guid[%s] store failed - %s\n",
    1078             :                         GUID_buf_string(&client->global->client_guid, &buf),
    1079             :                         nt_errstr(status));
    1080           0 :                 return status;
    1081             :         }
    1082             : 
    1083       20740 :         if (DEBUGLVL(DBGLVL_DEBUG)) {
    1084           0 :                 struct smbXsrv_clientB client_blob = {
    1085             :                         .version = SMBXSRV_VERSION_0,
    1086             :                         .info.info0 = client,
    1087             :                 };
    1088             :                 struct GUID_txt_buf buf;
    1089             : 
    1090           0 :                 DBG_DEBUG("client_guid[%s] stored\n",
    1091             :                           GUID_buf_string(&client->global->client_guid, &buf));
    1092           0 :                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
    1093             :         }
    1094             : 
    1095       20740 :         return NT_STATUS_OK;
    1096             : }

Generated by: LCOV version 1.13