ldb: move struct ldb_debug_ops to ldb_private.h
[samba.git] / source3 / smbd / smbXsrv_client.c
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 #include "source3/include/util_tdb.h"
43
44 struct smbXsrv_client_table {
45         struct {
46                 uint32_t max_clients;
47                 uint32_t num_clients;
48         } local;
49         struct {
50                 struct db_context *db_ctx;
51         } global;
52 };
53
54 static struct db_context *smbXsrv_client_global_db_ctx = NULL;
55
56 NTSTATUS smbXsrv_client_global_init(void)
57 {
58         const char *global_path = NULL;
59         struct db_context *backend = NULL;
60         struct db_context *db_ctx = NULL;
61
62         if (smbXsrv_client_global_db_ctx != NULL) {
63                 return NT_STATUS_OK;
64         }
65
66         /*
67          * This contains secret information like client keys!
68          */
69         global_path = lock_path(talloc_tos(), "smbXsrv_client_global.tdb");
70         if (global_path == NULL) {
71                 return NT_STATUS_NO_MEMORY;
72         }
73
74         backend = db_open(NULL, global_path,
75                           0, /* hash_size */
76                           TDB_DEFAULT |
77                           TDB_CLEAR_IF_FIRST |
78                           TDB_INCOMPATIBLE_HASH,
79                           O_RDWR | O_CREAT, 0600,
80                           DBWRAP_LOCK_ORDER_1,
81                           DBWRAP_FLAG_NONE);
82         if (backend == NULL) {
83                 NTSTATUS status;
84
85                 status = map_nt_error_from_unix_common(errno);
86
87                 return status;
88         }
89
90         db_ctx = db_open_watched(NULL, &backend, global_messaging_context());
91         if (db_ctx == NULL) {
92                 TALLOC_FREE(backend);
93                 return NT_STATUS_NO_MEMORY;
94         }
95
96         smbXsrv_client_global_db_ctx = db_ctx;
97
98         return NT_STATUS_OK;
99 }
100
101 #define SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE 16
102
103 static TDB_DATA smbXsrv_client_global_id_to_key(const struct GUID *client_guid,
104                                                 uint8_t *key_buf)
105 {
106         TDB_DATA key = { .dsize = 0, };
107         struct GUID_ndr_buf buf = { .buf = {0}, };
108
109         GUID_to_ndr_buf(client_guid, &buf);
110         memcpy(key_buf, buf.buf, SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE);
111
112         key = make_tdb_data(key_buf, SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE);
113
114         return key;
115 }
116
117 static struct db_record *smbXsrv_client_global_fetch_locked(
118                         struct db_context *db,
119                         const struct GUID *client_guid,
120                         TALLOC_CTX *mem_ctx)
121 {
122         TDB_DATA key;
123         uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE];
124         struct db_record *rec = NULL;
125
126         key = smbXsrv_client_global_id_to_key(client_guid, key_buf);
127
128         rec = dbwrap_fetch_locked(db, mem_ctx, key);
129
130         if (rec == NULL) {
131                 struct GUID_txt_buf buf;
132                 DBG_DEBUG("Failed to lock guid [%s], key '%s'\n",
133                           GUID_buf_string(client_guid, &buf),
134                           tdb_data_dbg(key));
135         }
136
137         return rec;
138 }
139
140 static NTSTATUS smbXsrv_client_table_create(TALLOC_CTX *mem_ctx,
141                                             struct messaging_context *msg_ctx,
142                                             uint32_t max_clients,
143                                             struct smbXsrv_client_table **_table)
144 {
145         struct smbXsrv_client_table *table;
146         NTSTATUS status;
147
148         if (max_clients > 1) {
149                 return NT_STATUS_INTERNAL_ERROR;
150         }
151
152         table = talloc_zero(mem_ctx, struct smbXsrv_client_table);
153         if (table == NULL) {
154                 return NT_STATUS_NO_MEMORY;
155         }
156
157         table->local.max_clients = max_clients;
158
159         status = smbXsrv_client_global_init();
160         if (!NT_STATUS_IS_OK(status)) {
161                 TALLOC_FREE(table);
162                 return status;
163         }
164
165         table->global.db_ctx = smbXsrv_client_global_db_ctx;
166
167         *_table = table;
168         return NT_STATUS_OK;
169 }
170
171 static int smbXsrv_client_global_destructor(struct smbXsrv_client_global0 *global)
172 {
173         return 0;
174 }
175
176 static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
177                                         bool *is_free,
178                                         bool *was_free,
179                                         TALLOC_CTX *mem_ctx,
180                                         const struct server_id *dead_server_id,
181                                         struct smbXsrv_client_global0 **_g,
182                                         uint32_t *pseqnum)
183 {
184         TDB_DATA key;
185         TDB_DATA val;
186         DATA_BLOB blob;
187         struct smbXsrv_client_globalB global_blob;
188         enum ndr_err_code ndr_err;
189         struct smbXsrv_client_global0 *global = NULL;
190         bool dead = false;
191         bool exists;
192         TALLOC_CTX *frame = talloc_stackframe();
193
194         *is_free = false;
195
196         if (was_free) {
197                 *was_free = false;
198         }
199         if (_g) {
200                 *_g = NULL;
201         }
202         if (pseqnum) {
203                 *pseqnum = 0;
204         }
205
206         key = dbwrap_record_get_key(db_rec);
207
208         val = dbwrap_record_get_value(db_rec);
209         if (val.dsize == 0) {
210                 TALLOC_FREE(frame);
211                 *is_free = true;
212                 if (was_free) {
213                         *was_free = true;
214                 }
215                 return;
216         }
217
218         blob = data_blob_const(val.dptr, val.dsize);
219
220         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
221                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_client_globalB);
222         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
223                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
224                 DBG_WARNING("key '%s' ndr_pull_struct_blob - %s\n",
225                             tdb_data_dbg(key),
226                             nt_errstr(status));
227                 TALLOC_FREE(frame);
228                 return;
229         }
230
231         DBG_DEBUG("client_global:\n");
232         if (DEBUGLVL(DBGLVL_DEBUG)) {
233                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
234         }
235
236         if (global_blob.version != SMBXSRV_VERSION_0) {
237                 DBG_ERR("key '%s' uses unsupported version %u\n",
238                         tdb_data_dbg(key),
239                         global_blob.version);
240                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
241                 TALLOC_FREE(frame);
242                 return;
243         }
244
245         global = global_blob.info.info0;
246
247         dead = server_id_equal(dead_server_id, &global->server_id);
248         if (dead) {
249                 struct server_id_buf tmp;
250
251                 DBG_NOTICE("key '%s' server_id %s is already dead.\n",
252                            tdb_data_dbg(key),
253                            server_id_str_buf(global->server_id, &tmp));
254                 if (DEBUGLVL(DBGLVL_NOTICE)) {
255                         NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
256                 }
257                 TALLOC_FREE(frame);
258                 dbwrap_record_delete(db_rec);
259                 *is_free = true;
260                 return;
261         }
262
263         exists = serverid_exists(&global->server_id);
264         if (!exists) {
265                 struct server_id_buf tmp;
266
267                 DBG_NOTICE("key '%s' server_id %s does not exist.\n",
268                            tdb_data_dbg(key),
269                            server_id_str_buf(global->server_id, &tmp));
270                 if (DEBUGLVL(DBGLVL_NOTICE)) {
271                         NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
272                 }
273                 TALLOC_FREE(frame);
274                 dbwrap_record_delete(db_rec);
275                 *is_free = true;
276                 return;
277         }
278
279         if (_g) {
280                 *_g = talloc_move(mem_ctx, &global);
281         }
282         if (pseqnum) {
283                 *pseqnum = global_blob.seqnum;
284         }
285         TALLOC_FREE(frame);
286 }
287
288 static NTSTATUS smb2srv_client_connection_pass(struct smbd_smb2_request *smb2req,
289                                                struct smbXsrv_client_global0 *global)
290 {
291         DATA_BLOB blob;
292         enum ndr_err_code ndr_err;
293         NTSTATUS status;
294         struct smbXsrv_connection_pass0 pass_info0;
295         struct smbXsrv_connection_passB pass_blob;
296         ssize_t reqlen;
297         struct iovec iov;
298
299         pass_info0 = (struct smbXsrv_connection_pass0) {
300                 .client_guid = global->client_guid,
301                 .src_server_id = smb2req->xconn->client->global->server_id,
302                 .xconn_connect_time = smb2req->xconn->client->global->initial_connect_time,
303                 .dst_server_id = global->server_id,
304                 .client_connect_time = global->initial_connect_time,
305         };
306
307         reqlen = iov_buflen(smb2req->in.vector, smb2req->in.vector_count);
308         if (reqlen == -1) {
309                 return NT_STATUS_INVALID_BUFFER_SIZE;
310         }
311
312         pass_info0.negotiate_request.length = reqlen;
313         pass_info0.negotiate_request.data = talloc_array(talloc_tos(), uint8_t,
314                                                          reqlen);
315         if (pass_info0.negotiate_request.data == NULL) {
316                 return NT_STATUS_NO_MEMORY;
317         }
318         iov_buf(smb2req->in.vector, smb2req->in.vector_count,
319                 pass_info0.negotiate_request.data,
320                 pass_info0.negotiate_request.length);
321
322         ZERO_STRUCT(pass_blob);
323         pass_blob.version = smbXsrv_version_global_current();
324         pass_blob.info.info0 = &pass_info0;
325
326         if (DEBUGLVL(DBGLVL_DEBUG)) {
327                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
328         }
329
330         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &pass_blob,
331                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_connection_passB);
332         data_blob_free(&pass_info0.negotiate_request);
333         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
334                 status = ndr_map_error2ntstatus(ndr_err);
335                 return status;
336         }
337
338         iov.iov_base = blob.data;
339         iov.iov_len = blob.length;
340
341         status = messaging_send_iov(smb2req->xconn->client->msg_ctx,
342                                     global->server_id,
343                                     MSG_SMBXSRV_CONNECTION_PASS,
344                                     &iov, 1,
345                                     &smb2req->xconn->transport.sock, 1);
346         data_blob_free(&blob);
347         if (!NT_STATUS_IS_OK(status)) {
348                 return status;
349         }
350
351         return NT_STATUS_OK;
352 }
353
354 static NTSTATUS smb2srv_client_connection_drop(struct smbd_smb2_request *smb2req,
355                                                struct smbXsrv_client_global0 *global)
356 {
357         DATA_BLOB blob;
358         enum ndr_err_code ndr_err;
359         NTSTATUS status;
360         struct smbXsrv_connection_drop0 drop_info0;
361         struct smbXsrv_connection_dropB drop_blob;
362         struct iovec iov;
363
364         drop_info0 = (struct smbXsrv_connection_drop0) {
365                 .client_guid = global->client_guid,
366                 .src_server_id = smb2req->xconn->client->global->server_id,
367                 .xconn_connect_time = smb2req->xconn->client->global->initial_connect_time,
368                 .dst_server_id = global->server_id,
369                 .client_connect_time = global->initial_connect_time,
370         };
371
372         ZERO_STRUCT(drop_blob);
373         drop_blob.version = smbXsrv_version_global_current();
374         drop_blob.info.info0 = &drop_info0;
375
376         if (DEBUGLVL(DBGLVL_DEBUG)) {
377                 NDR_PRINT_DEBUG(smbXsrv_connection_dropB, &drop_blob);
378         }
379
380         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &drop_blob,
381                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_connection_dropB);
382         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
383                 status = ndr_map_error2ntstatus(ndr_err);
384                 return status;
385         }
386
387         iov.iov_base = blob.data;
388         iov.iov_len = blob.length;
389
390         status = messaging_send_iov(smb2req->xconn->client->msg_ctx,
391                                     global->server_id,
392                                     MSG_SMBXSRV_CONNECTION_DROP,
393                                     &iov, 1,
394                                     NULL, 0);
395         data_blob_free(&blob);
396         if (!NT_STATUS_IS_OK(status)) {
397                 return status;
398         }
399
400         return NT_STATUS_OK;
401 }
402
403 static NTSTATUS smbXsrv_client_global_store(struct smbXsrv_client_global0 *global)
404 {
405         struct smbXsrv_client_globalB global_blob;
406         DATA_BLOB blob = data_blob_null;
407         TDB_DATA key;
408         TDB_DATA val;
409         NTSTATUS status;
410         enum ndr_err_code ndr_err;
411         bool saved_stored = global->stored;
412
413         /*
414          * TODO: if we use other versions than '0'
415          * we would add glue code here, that would be able to
416          * store the information in the old format.
417          */
418
419         SMB_ASSERT(global->local_address != NULL);
420         SMB_ASSERT(global->remote_address != NULL);
421         SMB_ASSERT(global->remote_name != NULL);
422
423         if (global->db_rec == NULL) {
424                 return NT_STATUS_INTERNAL_ERROR;
425         }
426
427         key = dbwrap_record_get_key(global->db_rec);
428         val = dbwrap_record_get_value(global->db_rec);
429
430         ZERO_STRUCT(global_blob);
431         global_blob.version = smbXsrv_version_global_current();
432         if (val.dsize >= 8) {
433                 global_blob.seqnum = IVAL(val.dptr, 4);
434         }
435         global_blob.seqnum += 1;
436         global_blob.info.info0 = global;
437
438         global->stored = true;
439         ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
440                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_client_globalB);
441         global->stored = saved_stored;
442         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
443                 status = ndr_map_error2ntstatus(ndr_err);
444                 DBG_WARNING("key '%s' ndr_push - %s\n",
445                         tdb_data_dbg(key),
446                         nt_errstr(status));
447                 TALLOC_FREE(global->db_rec);
448                 return status;
449         }
450
451         val = make_tdb_data(blob.data, blob.length);
452         status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
453         if (!NT_STATUS_IS_OK(status)) {
454                 DBG_WARNING("key '%s' store - %s\n",
455                         tdb_data_dbg(key),
456                         nt_errstr(status));
457                 TALLOC_FREE(global->db_rec);
458                 return status;
459         }
460
461         global->stored = true;
462
463         if (DEBUGLVL(DBGLVL_DEBUG)) {
464                 DBG_DEBUG("key '%s' stored\n",
465                           tdb_data_dbg(key));
466                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
467         }
468
469         TALLOC_FREE(global->db_rec);
470
471         return NT_STATUS_OK;
472 }
473
474 struct smb2srv_client_mc_negprot_state {
475         struct tevent_context *ev;
476         struct smbd_smb2_request *smb2req;
477         struct db_record *db_rec;
478         struct server_id sent_server_id;
479         uint64_t watch_instance;
480         uint32_t last_seqnum;
481         struct tevent_req *filter_subreq;
482 };
483
484 static void smb2srv_client_mc_negprot_cleanup(struct tevent_req *req,
485                                               enum tevent_req_state req_state)
486 {
487         struct smb2srv_client_mc_negprot_state *state =
488                 tevent_req_data(req,
489                 struct smb2srv_client_mc_negprot_state);
490
491         if (state->db_rec != NULL) {
492                 dbwrap_watched_watch_remove_instance(state->db_rec,
493                                                      state->watch_instance);
494                 state->watch_instance = 0;
495                 TALLOC_FREE(state->db_rec);
496         }
497 }
498
499 static void smb2srv_client_mc_negprot_next(struct tevent_req *req);
500 static bool smb2srv_client_mc_negprot_filter(struct messaging_rec *rec, void *private_data);
501 static void smb2srv_client_mc_negprot_done(struct tevent_req *subreq);
502 static void smb2srv_client_mc_negprot_watched(struct tevent_req *subreq);
503
504 struct tevent_req *smb2srv_client_mc_negprot_send(TALLOC_CTX *mem_ctx,
505                                                   struct tevent_context *ev,
506                                                   struct smbd_smb2_request *smb2req)
507 {
508         struct tevent_req *req = NULL;
509         struct smb2srv_client_mc_negprot_state *state = NULL;
510
511         req = tevent_req_create(mem_ctx, &state,
512                                 struct smb2srv_client_mc_negprot_state);
513         if (req == NULL) {
514                 return NULL;
515         }
516         state->ev = ev;
517         state->smb2req = smb2req;
518
519         tevent_req_set_cleanup_fn(req, smb2srv_client_mc_negprot_cleanup);
520
521         server_id_set_disconnected(&state->sent_server_id);
522
523         smb2srv_client_mc_negprot_next(req);
524
525         if (!tevent_req_is_in_progress(req)) {
526                 return tevent_req_post(req, ev);
527         }
528
529         return req;
530 }
531
532 static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
533 {
534         struct smb2srv_client_mc_negprot_state *state =
535                 tevent_req_data(req,
536                 struct smb2srv_client_mc_negprot_state);
537         struct smbXsrv_connection *xconn = state->smb2req->xconn;
538         struct smbXsrv_client *client = xconn->client;
539         struct smbXsrv_client_table *table = client->table;
540         struct GUID client_guid = xconn->smb2.client.guid;
541         struct smbXsrv_client_global0 *global = NULL;
542         bool is_free = false;
543         struct tevent_req *subreq = NULL;
544         NTSTATUS status;
545         uint32_t seqnum = 0;
546         struct server_id last_server_id = { .pid = 0, };
547
548         SMB_ASSERT(state->db_rec == NULL);
549         state->db_rec = smbXsrv_client_global_fetch_locked(table->global.db_ctx,
550                                                            &client_guid,
551                                                            state);
552         if (state->db_rec == NULL) {
553                 tevent_req_nterror(req, NT_STATUS_INTERNAL_DB_ERROR);
554                 return;
555         }
556
557 verify_again:
558         TALLOC_FREE(global);
559
560         smbXsrv_client_global_verify_record(state->db_rec,
561                                             &is_free,
562                                             NULL,
563                                             state,
564                                             &last_server_id,
565                                             &global,
566                                             &seqnum);
567         if (is_free) {
568                 dbwrap_watched_watch_remove_instance(state->db_rec,
569                                                      state->watch_instance);
570                 state->watch_instance = 0;
571
572                 /*
573                  * This stores the new client information in
574                  * smbXsrv_client_global.tdb
575                  */
576                 client->global->client_guid = xconn->smb2.client.guid;
577
578                 client->global->db_rec = state->db_rec;
579                 state->db_rec = NULL;
580                 status = smbXsrv_client_global_store(client->global);
581                 SMB_ASSERT(client->global->db_rec == NULL);
582                 if (!NT_STATUS_IS_OK(status)) {
583                         struct GUID_txt_buf buf;
584                         DBG_ERR("client_guid[%s] store failed - %s\n",
585                                 GUID_buf_string(&client->global->client_guid,
586                                                 &buf),
587                                 nt_errstr(status));
588                         tevent_req_nterror(req, status);
589                         return;
590                 }
591
592                 if (DEBUGLVL(DBGLVL_DEBUG)) {
593                         struct smbXsrv_clientB client_blob = {
594                                 .version = SMBXSRV_VERSION_0,
595                                 .info.info0 = client,
596                         };
597                         struct GUID_txt_buf buf;
598
599                         DBG_DEBUG("client_guid[%s] stored\n",
600                                   GUID_buf_string(&client->global->client_guid,
601                                                   &buf));
602                         NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
603                 }
604
605                 xconn->smb2.client.guid_verified = true;
606                 tevent_req_done(req);
607                 return;
608         }
609
610         if (global == NULL) {
611                 /*
612                  * most likely ndr_pull_struct_blob() failed
613                  */
614                 tevent_req_nterror(req, NT_STATUS_INTERNAL_DB_CORRUPTION);
615                 return;
616         }
617
618         if (server_id_equal(&state->sent_server_id, &global->server_id)) {
619                 /*
620                  * We hit a race with other concurrent connections,
621                  * which have woken us.
622                  *
623                  * We already sent the pass or drop message to
624                  * the process, so we need to wait for a
625                  * response and not pass the connection
626                  * again! Otherwise the process would
627                  * receive the same tcp connection via
628                  * more than one file descriptor and
629                  * create more than one smbXsrv_connection
630                  * structure for the same tcp connection,
631                  * which means the client would see more
632                  * than one SMB2 negprot response to its
633                  * single SMB2 netprot request and we
634                  * as server get the session keys and
635                  * message id validation wrong
636                  */
637                 goto watch_again;
638         }
639
640         server_id_set_disconnected(&state->sent_server_id);
641
642         /*
643          * If last_server_id is set, we expect
644          * smbXsrv_client_global_verify_record()
645          * to detect the already dead global->server_id
646          * as state->db_rec is still locked and its
647          * value didn't change.
648          */
649         SMB_ASSERT(last_server_id.pid == 0);
650         last_server_id = global->server_id;
651
652         TALLOC_FREE(state->filter_subreq);
653         if (procid_is_local(&global->server_id)) {
654                 subreq = messaging_filtered_read_send(state,
655                                                       state->ev,
656                                                       client->msg_ctx,
657                                                       smb2srv_client_mc_negprot_filter,
658                                                       NULL);
659                 if (tevent_req_nomem(subreq, req)) {
660                         return;
661                 }
662                 tevent_req_set_callback(subreq, smb2srv_client_mc_negprot_done, req);
663                 state->filter_subreq = subreq;
664         }
665
666         if (procid_is_local(&global->server_id)) {
667                 status = smb2srv_client_connection_pass(state->smb2req,
668                                                         global);
669                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
670                         /*
671                          * We remembered last_server_id = global->server_id
672                          * above, so we'll treat it as dead in the
673                          * next round to smbXsrv_client_global_verify_record().
674                          */
675                         goto verify_again;
676                 }
677                 state->sent_server_id = global->server_id;
678                 if (tevent_req_nterror(req, status)) {
679                         return;
680                 }
681         } else {
682                 status = smb2srv_client_connection_drop(state->smb2req,
683                                                         global);
684                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
685                         /*
686                          * We remembered last_server_id = global->server_id
687                          * above, so we'll treat it as dead in the
688                          * next round to smbXsrv_client_global_verify_record().
689                          */
690                         goto verify_again;
691                 }
692                 state->sent_server_id = global->server_id;
693                 if (tevent_req_nterror(req, status)) {
694                         return;
695                 }
696         }
697
698 watch_again:
699
700         /*
701          * If the record changed, but we are not happy with the change yet,
702          * we better remove ourself from the waiter list
703          * (most likely the first position)
704          * and re-add us at the end of the list.
705          *
706          * This gives other waiters a change
707          * to make progress.
708          *
709          * Otherwise we'll keep our waiter instance alive,
710          * keep waiting (most likely at first position).
711          * It means the order of watchers stays fair.
712          */
713         if (state->last_seqnum != seqnum) {
714                 state->last_seqnum = seqnum;
715                 dbwrap_watched_watch_remove_instance(state->db_rec,
716                                                      state->watch_instance);
717                 state->watch_instance =
718                         dbwrap_watched_watch_add_instance(state->db_rec);
719         }
720
721         subreq = dbwrap_watched_watch_send(state,
722                                            state->ev,
723                                            state->db_rec,
724                                            state->watch_instance,
725                                            global->server_id);
726         if (tevent_req_nomem(subreq, req)) {
727                 return;
728         }
729         tevent_req_set_callback(subreq, smb2srv_client_mc_negprot_watched, req);
730
731         TALLOC_FREE(global);
732         TALLOC_FREE(state->db_rec);
733         return;
734 }
735
736 static bool smb2srv_client_mc_negprot_filter(struct messaging_rec *rec, void *private_data)
737 {
738         if (rec->msg_type != MSG_SMBXSRV_CONNECTION_PASSED) {
739                 return false;
740         }
741
742         if (rec->num_fds != 0) {
743                 return false;
744         }
745
746         return true;
747 }
748
749 static void smb2srv_client_mc_negprot_done(struct tevent_req *subreq)
750 {
751         struct tevent_req *req =
752                 tevent_req_callback_data(subreq,
753                 struct tevent_req);
754         struct smb2srv_client_mc_negprot_state *state =
755                 tevent_req_data(req,
756                 struct smb2srv_client_mc_negprot_state);
757         struct smbXsrv_connection *xconn = state->smb2req->xconn;
758         struct smbXsrv_client *client = xconn->client;
759         struct messaging_rec *rec = NULL;
760         struct smbXsrv_connection_passB passed_blob;
761         enum ndr_err_code ndr_err;
762         struct smbXsrv_connection_pass0 *passed_info0 = NULL;
763         NTSTATUS status;
764         int ret;
765
766         SMB_ASSERT(state->filter_subreq == subreq);
767         state->filter_subreq = NULL;
768
769         ret = messaging_filtered_read_recv(subreq, state, &rec);
770         TALLOC_FREE(subreq);
771         if (ret != 0) {
772                 status = map_nt_error_from_unix_common(ret);
773                 DBG_ERR("messaging_filtered_read_recv() - %s\n",
774                         nt_errstr(status));
775                 tevent_req_nterror(req, status);
776                 return;
777         }
778
779         DBG_DEBUG("MSG_SMBXSRV_CONNECTION_PASSED: received...\n");
780
781         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &passed_blob,
782                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_connection_passB);
783         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
784                 status = ndr_map_error2ntstatus(ndr_err);
785                 DBG_ERR("ndr_pull_struct_blob - %s\n", nt_errstr(status));
786                 tevent_req_nterror(req, status);
787                 return;
788         }
789
790         if (DEBUGLVL(DBGLVL_DEBUG)) {
791                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
792         }
793
794         if (passed_blob.version != SMBXSRV_VERSION_0) {
795                 DBG_ERR("ignore invalid version %u\n", passed_blob.version);
796                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
797                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
798                 return;
799         }
800
801         passed_info0 = passed_blob.info.info0;
802         if (passed_info0 == NULL) {
803                 DBG_ERR("ignore NULL info %u\n", passed_blob.version);
804                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
805                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
806                 return;
807         }
808
809         if (!GUID_equal(&xconn->smb2.client.guid, &passed_info0->client_guid)) {
810                 struct GUID_txt_buf buf1, buf2;
811
812                 DBG_ERR("client's client_guid [%s] != passed guid [%s]\n",
813                         GUID_buf_string(&xconn->smb2.client.guid,
814                                         &buf1),
815                         GUID_buf_string(&passed_info0->client_guid,
816                                         &buf2));
817                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
818                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
819                 return;
820         }
821
822         if (client->global->initial_connect_time !=
823             passed_info0->xconn_connect_time)
824         {
825                 DBG_ERR("client's initial connect time [%s] (%llu) != "
826                         "passed xconn connect time [%s] (%llu)\n",
827                         nt_time_string(talloc_tos(),
828                                        client->global->initial_connect_time),
829                         (unsigned long long)client->global->initial_connect_time,
830                         nt_time_string(talloc_tos(),
831                                        passed_info0->xconn_connect_time),
832                         (unsigned long long)passed_info0->xconn_connect_time);
833                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
834                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
835                 return;
836         }
837
838         if (passed_info0->negotiate_request.length != 0) {
839                 DBG_ERR("negotiate_request.length[%zu]\n",
840                         passed_info0->negotiate_request.length);
841                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
842                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
843                 return;
844         }
845
846         tevent_req_nterror(req, NT_STATUS_MESSAGE_RETRIEVED);
847 }
848
849 static void smb2srv_client_mc_negprot_watched(struct tevent_req *subreq)
850 {
851         struct tevent_req *req =
852                 tevent_req_callback_data(subreq,
853                 struct tevent_req);
854         struct smb2srv_client_mc_negprot_state *state =
855                 tevent_req_data(req,
856                 struct smb2srv_client_mc_negprot_state);
857         NTSTATUS status;
858         uint64_t instance = 0;
859
860         status = dbwrap_watched_watch_recv(subreq, &instance, NULL, NULL);
861         TALLOC_FREE(subreq);
862         if (tevent_req_nterror(req, status)) {
863                 return;
864         }
865
866         state->watch_instance = instance;
867
868         smb2srv_client_mc_negprot_next(req);
869 }
870
871 NTSTATUS smb2srv_client_mc_negprot_recv(struct tevent_req *req)
872 {
873         return tevent_req_simple_recv_ntstatus(req);
874 }
875
876 static NTSTATUS smbXsrv_client_global_remove(struct smbXsrv_client_global0 *global)
877 {
878         TDB_DATA key;
879         NTSTATUS status;
880
881         /*
882          * TODO: if we use other versions than '0'
883          * we would add glue code here, that would be able to
884          * store the information in the old format.
885          */
886
887         if (global->db_rec == NULL) {
888                 return NT_STATUS_INTERNAL_ERROR;
889         }
890
891         key = dbwrap_record_get_key(global->db_rec);
892
893         status = dbwrap_record_delete(global->db_rec);
894         if (!NT_STATUS_IS_OK(status)) {
895                 DBG_WARNING("key '%s' delete - %s\n",
896                         tdb_data_dbg(key),
897                         nt_errstr(status));
898                 TALLOC_FREE(global->db_rec);
899                 return status;
900         }
901         global->stored = false;
902         DBG_DEBUG("key '%s' delete\n", tdb_data_dbg(key));
903
904         TALLOC_FREE(global->db_rec);
905
906         return NT_STATUS_OK;
907 }
908
909 static int smbXsrv_client_destructor(struct smbXsrv_client *client)
910 {
911         NTSTATUS status;
912
913         status = smbXsrv_client_remove(client);
914         if (!NT_STATUS_IS_OK(status)) {
915                 DBG_ERR("smbXsrv_client_remove() failed: %s\n",
916                         nt_errstr(status));
917         }
918
919         TALLOC_FREE(client->global);
920
921         return 0;
922 }
923
924 static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data);
925 static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq);
926 static bool smbXsrv_client_connection_drop_filter(struct messaging_rec *rec, void *private_data);
927 static void smbXsrv_client_connection_drop_loop(struct tevent_req *subreq);
928
929 NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx,
930                                struct tevent_context *ev_ctx,
931                                struct messaging_context *msg_ctx,
932                                NTTIME now,
933                                struct smbXsrv_client **_client)
934 {
935         struct smbXsrv_client_table *table;
936         struct smbXsrv_client *client = NULL;
937         struct smbXsrv_client_global0 *global = NULL;
938         NTSTATUS status;
939         struct tevent_req *subreq = NULL;
940
941         status = smbXsrv_client_table_create(mem_ctx,
942                                              msg_ctx,
943                                              1, /* max_clients */
944                                              &table);
945         if (!NT_STATUS_IS_OK(status)) {
946                 return status;
947         }
948
949         if (table->local.num_clients >= table->local.max_clients) {
950                 TALLOC_FREE(table);
951                 return NT_STATUS_INSUFFICIENT_RESOURCES;
952         }
953
954         client = talloc_zero(mem_ctx, struct smbXsrv_client);
955         if (client == NULL) {
956                 TALLOC_FREE(table);
957                 return NT_STATUS_NO_MEMORY;
958         }
959         client->raw_ev_ctx = ev_ctx;
960         client->msg_ctx = msg_ctx;
961
962         client->server_multi_channel_enabled =
963                 smbXsrv_server_multi_channel_enabled();
964         if (client->server_multi_channel_enabled) {
965                 client->next_channel_id = 1;
966         }
967         client->table = talloc_move(client, &table);
968         table = client->table;
969
970         global = talloc_zero(client, struct smbXsrv_client_global0);
971         if (global == NULL) {
972                 TALLOC_FREE(client);
973                 return NT_STATUS_NO_MEMORY;
974         }
975         talloc_set_destructor(global, smbXsrv_client_global_destructor);
976         client->global = global;
977
978         global->initial_connect_time = now;
979
980         global->server_id = messaging_server_id(client->msg_ctx);
981
982         table->local.num_clients += 1;
983
984         talloc_set_destructor(client, smbXsrv_client_destructor);
985
986         if (DEBUGLVL(DBGLVL_DEBUG)) {
987                 struct smbXsrv_clientB client_blob = {
988                         .version = SMBXSRV_VERSION_0,
989                         .info.info0 = client,
990                 };
991                 struct GUID_txt_buf buf;
992
993                 DBG_DEBUG("client_guid[%s] created\n",
994                           GUID_buf_string(&global->client_guid, &buf));
995                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
996         }
997
998         subreq = messaging_filtered_read_send(client,
999                                         client->raw_ev_ctx,
1000                                         client->msg_ctx,
1001                                         smbXsrv_client_connection_pass_filter,
1002                                         client);
1003         if (subreq == NULL) {
1004                 TALLOC_FREE(client);
1005                 return NT_STATUS_NO_MEMORY;
1006         }
1007         tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
1008         client->connection_pass_subreq = subreq;
1009
1010         subreq = messaging_filtered_read_send(client,
1011                                         client->raw_ev_ctx,
1012                                         client->msg_ctx,
1013                                         smbXsrv_client_connection_drop_filter,
1014                                         client);
1015         if (subreq == NULL) {
1016                 TALLOC_FREE(client);
1017                 return NT_STATUS_NO_MEMORY;
1018         }
1019         tevent_req_set_callback(subreq, smbXsrv_client_connection_drop_loop, client);
1020         client->connection_drop_subreq = subreq;
1021
1022         *_client = client;
1023         return NT_STATUS_OK;
1024 }
1025
1026 static NTSTATUS smb2srv_client_connection_passed(struct smbXsrv_client *client,
1027                                 const struct smbXsrv_connection_pass0 *recv_info0)
1028 {
1029         DATA_BLOB blob;
1030         enum ndr_err_code ndr_err;
1031         NTSTATUS status;
1032         struct smbXsrv_connection_pass0 passed_info0;
1033         struct smbXsrv_connection_passB passed_blob;
1034         struct iovec iov;
1035
1036         /*
1037          * We echo back the message with a cleared negotiate_request
1038          */
1039         passed_info0 = *recv_info0;
1040         passed_info0.negotiate_request = data_blob_null;
1041
1042         ZERO_STRUCT(passed_blob);
1043         passed_blob.version = smbXsrv_version_global_current();
1044         passed_blob.info.info0 = &passed_info0;
1045
1046         if (DEBUGLVL(DBGLVL_DEBUG)) {
1047                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
1048         }
1049
1050         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &passed_blob,
1051                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_connection_passB);
1052         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1053                 status = ndr_map_error2ntstatus(ndr_err);
1054                 return status;
1055         }
1056
1057         iov.iov_base = blob.data;
1058         iov.iov_len = blob.length;
1059
1060         status = messaging_send_iov(client->msg_ctx,
1061                                     recv_info0->src_server_id,
1062                                     MSG_SMBXSRV_CONNECTION_PASSED,
1063                                     &iov, 1,
1064                                     NULL, 0);
1065         data_blob_free(&blob);
1066         if (!NT_STATUS_IS_OK(status)) {
1067                 return status;
1068         }
1069
1070         return NT_STATUS_OK;
1071 }
1072
1073 static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data)
1074 {
1075         if (rec->msg_type != MSG_SMBXSRV_CONNECTION_PASS) {
1076                 return false;
1077         }
1078
1079         if (rec->num_fds != 1) {
1080                 return false;
1081         }
1082
1083         return true;
1084 }
1085
1086 static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq)
1087 {
1088         struct smbXsrv_client *client =
1089                 tevent_req_callback_data(subreq,
1090                 struct smbXsrv_client);
1091         struct smbXsrv_connection *xconn = NULL;
1092         int ret;
1093         struct messaging_rec *rec = NULL;
1094         struct smbXsrv_connection_passB pass_blob;
1095         enum ndr_err_code ndr_err;
1096         struct smbXsrv_connection_pass0 *pass_info0 = NULL;
1097         NTSTATUS status;
1098         int sock_fd = -1;
1099         uint64_t seq_low;
1100
1101         client->connection_pass_subreq = NULL;
1102
1103         ret = messaging_filtered_read_recv(subreq, talloc_tos(), &rec);
1104         TALLOC_FREE(subreq);
1105         if (ret != 0) {
1106                 goto next;
1107         }
1108
1109         if (rec->num_fds != 1) {
1110                 DBG_ERR("MSG_SMBXSRV_CONNECTION_PASS: num_fds[%u]\n",
1111                         rec->num_fds);
1112                 goto next;
1113         }
1114
1115         sock_fd = rec->fds[0];
1116         DBG_DEBUG("MSG_SMBXSRV_CONNECTION_PASS: got sock_fd[%d]\n", sock_fd);
1117
1118         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &pass_blob,
1119                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_connection_passB);
1120         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1121                 status = ndr_map_error2ntstatus(ndr_err);
1122                 DBG_WARNING("ndr_pull_struct_blob - %s\n", nt_errstr(status));
1123                 goto next;
1124         }
1125
1126         if (DEBUGLVL(DBGLVL_DEBUG)) {
1127                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
1128         }
1129
1130         if (pass_blob.version != SMBXSRV_VERSION_0) {
1131                 DBG_ERR("ignore invalid version %u\n", pass_blob.version);
1132                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
1133                 goto next;
1134         }
1135
1136         pass_info0 = pass_blob.info.info0;
1137         if (pass_info0 == NULL) {
1138                 DBG_ERR("ignore NULL info %u\n", pass_blob.version);
1139                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
1140                 goto next;
1141         }
1142
1143         if (!GUID_equal(&client->global->client_guid, &pass_info0->client_guid))
1144         {
1145                 struct GUID_txt_buf buf1, buf2;
1146
1147                 DBG_WARNING("client's client_guid [%s] != passed guid [%s]\n",
1148                             GUID_buf_string(&client->global->client_guid,
1149                                             &buf1),
1150                             GUID_buf_string(&pass_info0->client_guid,
1151                                             &buf2));
1152                 if (DEBUGLVL(DBGLVL_WARNING)) {
1153                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
1154                 }
1155                 goto next;
1156         }
1157
1158         if (client->global->initial_connect_time !=
1159             pass_info0->client_connect_time)
1160         {
1161                 DBG_WARNING("client's initial connect time [%s] (%llu) != "
1162                         "passed initial connect time [%s] (%llu)\n",
1163                         nt_time_string(talloc_tos(),
1164                                        client->global->initial_connect_time),
1165                         (unsigned long long)client->global->initial_connect_time,
1166                         nt_time_string(talloc_tos(),
1167                                        pass_info0->client_connect_time),
1168                         (unsigned long long)pass_info0->client_connect_time);
1169                 if (DEBUGLVL(DBGLVL_WARNING)) {
1170                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
1171                 }
1172                 goto next;
1173         }
1174
1175         if (pass_info0->negotiate_request.length < SMB2_HDR_BODY) {
1176                 DBG_WARNING("negotiate_request.length[%zu]\n",
1177                             pass_info0->negotiate_request.length);
1178                 if (DEBUGLVL(DBGLVL_WARNING)) {
1179                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
1180                 }
1181                 goto next;
1182         }
1183
1184         status = smb2srv_client_connection_passed(client, pass_info0);
1185         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1186                 /*
1187                  * We hit a race where, the client dropped the connection
1188                  * while the socket was passed to us and the origin
1189                  * process already existed.
1190                  */
1191                 DBG_DEBUG("smb2srv_client_connection_passed() ignore %s\n",
1192                           nt_errstr(status));
1193                 status = NT_STATUS_OK;
1194         }
1195         if (!NT_STATUS_IS_OK(status)) {
1196                 const char *r = "smb2srv_client_connection_passed() failed";
1197                 DBG_ERR("%s => %s\n", r, nt_errstr(status));
1198                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
1199                 exit_server_cleanly(r);
1200                 return;
1201         }
1202
1203         status = smbd_add_connection(client,
1204                                      sock_fd,
1205                                      pass_info0->xconn_connect_time,
1206                                      &xconn);
1207         if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) {
1208                 rec->num_fds = 0;
1209                 smbd_server_connection_terminate(xconn, nt_errstr(status));
1210         }
1211         if (!NT_STATUS_IS_OK(status)) {
1212                 DBG_ERR("smbd_add_connection => %s\n", nt_errstr(status));
1213                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
1214                 goto next;
1215         }
1216         rec->num_fds = 0;
1217
1218         /*
1219          * Set seq_low to mid received in negprot
1220          */
1221         seq_low = BVAL(pass_info0->negotiate_request.data,
1222                        SMB2_HDR_MESSAGE_ID);
1223
1224         xconn->smb2.client.guid_verified = true;
1225         smbd_smb2_process_negprot(xconn, seq_low,
1226                                   pass_info0->negotiate_request.data,
1227                                   pass_info0->negotiate_request.length);
1228
1229 next:
1230         if (rec != NULL) {
1231                 uint8_t fd_idx;
1232
1233                 for (fd_idx = 0; fd_idx < rec->num_fds; fd_idx++) {
1234                         sock_fd = rec->fds[fd_idx];
1235                         close(sock_fd);
1236                 }
1237                 rec->num_fds = 0;
1238
1239                 TALLOC_FREE(rec);
1240         }
1241
1242         subreq = messaging_filtered_read_send(client,
1243                                         client->raw_ev_ctx,
1244                                         client->msg_ctx,
1245                                         smbXsrv_client_connection_pass_filter,
1246                                         client);
1247         if (subreq == NULL) {
1248                 const char *r;
1249                 r = "messaging_read_send(MSG_SMBXSRV_CONNECTION_PASS failed";
1250                 exit_server_cleanly(r);
1251                 return;
1252         }
1253         tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
1254         client->connection_pass_subreq = subreq;
1255 }
1256
1257 static bool smbXsrv_client_connection_drop_filter(struct messaging_rec *rec, void *private_data)
1258 {
1259         if (rec->msg_type != MSG_SMBXSRV_CONNECTION_DROP) {
1260                 return false;
1261         }
1262
1263         if (rec->num_fds != 0) {
1264                 return false;
1265         }
1266
1267         return true;
1268 }
1269
1270 static void smbXsrv_client_connection_drop_loop(struct tevent_req *subreq)
1271 {
1272         struct smbXsrv_client *client =
1273                 tevent_req_callback_data(subreq,
1274                 struct smbXsrv_client);
1275         int ret;
1276         struct messaging_rec *rec = NULL;
1277         struct smbXsrv_connection_dropB drop_blob;
1278         enum ndr_err_code ndr_err;
1279         struct smbXsrv_connection_drop0 *drop_info0 = NULL;
1280         struct server_id_buf src_server_id_buf = {};
1281         NTSTATUS status;
1282
1283         client->connection_drop_subreq = NULL;
1284
1285         ret = messaging_filtered_read_recv(subreq, talloc_tos(), &rec);
1286         TALLOC_FREE(subreq);
1287         if (ret != 0) {
1288                 goto next;
1289         }
1290
1291         if (rec->num_fds != 0) {
1292                 DBG_ERR("MSG_SMBXSRV_CONNECTION_DROP: num_fds[%u]\n",
1293                         rec->num_fds);
1294                 goto next;
1295         }
1296
1297         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &drop_blob,
1298                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_connection_dropB);
1299         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1300                 status = ndr_map_error2ntstatus(ndr_err);
1301                 DBG_WARNING("ndr_pull_struct_blob - %s\n", nt_errstr(status));
1302                 goto next;
1303         }
1304
1305         if (DEBUGLVL(DBGLVL_DEBUG)) {
1306                 NDR_PRINT_DEBUG(smbXsrv_connection_dropB, &drop_blob);
1307         }
1308
1309         if (drop_blob.version != SMBXSRV_VERSION_0) {
1310                 DBG_ERR("ignore invalid version %u\n", drop_blob.version);
1311                 NDR_PRINT_DEBUG(smbXsrv_connection_dropB, &drop_blob);
1312                 goto next;
1313         }
1314
1315         drop_info0 = drop_blob.info.info0;
1316         if (drop_info0 == NULL) {
1317                 DBG_ERR("ignore NULL info %u\n", drop_blob.version);
1318                 NDR_PRINT_DEBUG(smbXsrv_connection_dropB, &drop_blob);
1319                 goto next;
1320         }
1321
1322         if (!GUID_equal(&client->global->client_guid, &drop_info0->client_guid))
1323         {
1324                 struct GUID_txt_buf buf1, buf2;
1325
1326                 DBG_WARNING("client's client_guid [%s] != dropped guid [%s]\n",
1327                             GUID_buf_string(&client->global->client_guid,
1328                                             &buf1),
1329                             GUID_buf_string(&drop_info0->client_guid,
1330                                             &buf2));
1331                 if (DEBUGLVL(DBGLVL_WARNING)) {
1332                         NDR_PRINT_DEBUG(smbXsrv_connection_dropB, &drop_blob);
1333                 }
1334                 goto next;
1335         }
1336
1337         if (client->global->initial_connect_time !=
1338             drop_info0->client_connect_time)
1339         {
1340                 DBG_WARNING("client's initial connect time [%s] (%llu) != "
1341                         "dropped initial connect time [%s] (%llu)\n",
1342                         nt_time_string(talloc_tos(),
1343                                        client->global->initial_connect_time),
1344                         (unsigned long long)client->global->initial_connect_time,
1345                         nt_time_string(talloc_tos(),
1346                                        drop_info0->client_connect_time),
1347                         (unsigned long long)drop_info0->client_connect_time);
1348                 if (DEBUGLVL(DBGLVL_WARNING)) {
1349                         NDR_PRINT_DEBUG(smbXsrv_connection_dropB, &drop_blob);
1350                 }
1351                 goto next;
1352         }
1353
1354         /*
1355          * Disconnect all client connections, which means we will tear down all
1356          * sessions, tcons and non-durable opens. At the end we will remove our
1357          * smbXsrv_client_global.tdb record, which will wake up the watcher on
1358          * the other node in order to let it take over the client.
1359          *
1360          * The client will have to reopen all sessions, tcons and durable opens.
1361          */
1362         smbd_server_disconnect_client(client,
1363                 server_id_str_buf(drop_info0->src_server_id, &src_server_id_buf));
1364         return;
1365
1366 next:
1367         if (rec != NULL) {
1368                 int sock_fd;
1369                 uint8_t fd_idx;
1370
1371                 for (fd_idx = 0; fd_idx < rec->num_fds; fd_idx++) {
1372                         sock_fd = rec->fds[fd_idx];
1373                         close(sock_fd);
1374                 }
1375                 rec->num_fds = 0;
1376
1377                 TALLOC_FREE(rec);
1378         }
1379
1380         subreq = messaging_filtered_read_send(client,
1381                                         client->raw_ev_ctx,
1382                                         client->msg_ctx,
1383                                         smbXsrv_client_connection_drop_filter,
1384                                         client);
1385         if (subreq == NULL) {
1386                 const char *r;
1387                 r = "messaging_read_send(MSG_SMBXSRV_CONNECTION_DROP failed";
1388                 exit_server_cleanly(r);
1389                 return;
1390         }
1391         tevent_req_set_callback(subreq, smbXsrv_client_connection_drop_loop, client);
1392         client->connection_drop_subreq = subreq;
1393 }
1394
1395 NTSTATUS smbXsrv_client_remove(struct smbXsrv_client *client)
1396 {
1397         struct smbXsrv_client_table *table = client->table;
1398         NTSTATUS status;
1399
1400         if (client->global->db_rec != NULL) {
1401                 struct GUID_txt_buf buf;
1402                 DBG_ERR("client_guid[%s]: Called with db_rec != NULL'\n",
1403                         GUID_buf_string(&client->global->client_guid,
1404                                         &buf));
1405                 return NT_STATUS_INTERNAL_ERROR;
1406         }
1407
1408         if (!client->global->stored) {
1409                 return NT_STATUS_OK;
1410         }
1411
1412         TALLOC_FREE(client->connection_pass_subreq);
1413         TALLOC_FREE(client->connection_drop_subreq);
1414
1415         client->global->db_rec = smbXsrv_client_global_fetch_locked(
1416                                         table->global.db_ctx,
1417                                         &client->global->client_guid,
1418                                         client->global /* TALLOC_CTX */);
1419         if (client->global->db_rec == NULL) {
1420                 return NT_STATUS_INTERNAL_DB_ERROR;
1421         }
1422
1423         status = smbXsrv_client_global_remove(client->global);
1424         if (!NT_STATUS_IS_OK(status)) {
1425                 struct GUID_txt_buf buf;
1426                 DBG_ERR("client_guid[%s] store failed - %s\n",
1427                         GUID_buf_string(&client->global->client_guid, &buf),
1428                         nt_errstr(status));
1429                 return status;
1430         }
1431
1432         if (DEBUGLVL(DBGLVL_DEBUG)) {
1433                 struct smbXsrv_clientB client_blob = {
1434                         .version = SMBXSRV_VERSION_0,
1435                         .info.info0 = client,
1436                 };
1437                 struct GUID_txt_buf buf;
1438
1439                 DBG_DEBUG("client_guid[%s] stored\n",
1440                           GUID_buf_string(&client->global->client_guid, &buf));
1441                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
1442         }
1443
1444         return NT_STATUS_OK;
1445 }