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