smbd: Fix CID 1351215 Improper use of negative value
[gd/samba-autobuild/.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 "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "dbwrap/dbwrap.h"
26 #include "dbwrap/dbwrap_rbt.h"
27 #include "dbwrap/dbwrap_open.h"
28 #include "dbwrap/dbwrap_watch.h"
29 #include "session.h"
30 #include "auth.h"
31 #include "auth/gensec/gensec.h"
32 #include "../lib/tsocket/tsocket.h"
33 #include "../libcli/security/security.h"
34 #include "messages.h"
35 #include "lib/util/util_tdb.h"
36 #include "librpc/gen_ndr/ndr_smbXsrv.h"
37 #include "serverid.h"
38 #include "lib/util/tevent_ntstatus.h"
39 #include "lib/util/iov_buf.h"
40
41 struct smbXsrv_client_table {
42         struct {
43                 uint32_t max_clients;
44                 uint32_t num_clients;
45         } local;
46         struct {
47                 struct db_context *db_ctx;
48         } global;
49 };
50
51 static struct db_context *smbXsrv_client_global_db_ctx = NULL;
52
53 NTSTATUS smbXsrv_client_global_init(void)
54 {
55         const char *global_path = NULL;
56         struct db_context *db_ctx = NULL;
57
58         if (smbXsrv_client_global_db_ctx != NULL) {
59                 return NT_STATUS_OK;
60         }
61
62         /*
63          * This contains secret information like client keys!
64          */
65         global_path = lock_path("smbXsrv_client_global.tdb");
66         if (global_path == NULL) {
67                 return NT_STATUS_NO_MEMORY;
68         }
69
70         db_ctx = db_open(NULL, global_path,
71                          0, /* hash_size */
72                          TDB_DEFAULT |
73                          TDB_CLEAR_IF_FIRST |
74                          TDB_INCOMPATIBLE_HASH,
75                          O_RDWR | O_CREAT, 0600,
76                          DBWRAP_LOCK_ORDER_1,
77                          DBWRAP_FLAG_NONE);
78         if (db_ctx == NULL) {
79                 NTSTATUS status;
80
81                 status = map_nt_error_from_unix_common(errno);
82
83                 return status;
84         }
85
86         smbXsrv_client_global_db_ctx = db_ctx;
87
88         return NT_STATUS_OK;
89 }
90
91 /*
92  * NOTE:
93  * We need to store the keys in big endian so that dbwrap_rbt's memcmp
94  * has the same result as integer comparison between the uint32_t
95  * values.
96  *
97  * TODO: implement string based key
98  */
99
100 #define SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE 16
101
102 static TDB_DATA smbXsrv_client_global_id_to_key(const struct GUID *client_guid,
103                                                 uint8_t *key_buf)
104 {
105         TDB_DATA key = { .dsize = 0, };
106         NTSTATUS status;
107         DATA_BLOB b;
108
109         status = GUID_to_ndr_blob(client_guid, talloc_tos(), &b);
110         if (!NT_STATUS_IS_OK(status)) {
111                 return key;
112         }
113         memcpy(key_buf, b.data, SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE);
114         data_blob_free(&b);
115
116         key = make_tdb_data(key_buf, SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE);
117
118         return key;
119 }
120
121 static NTSTATUS smbXsrv_client_table_create(TALLOC_CTX *mem_ctx,
122                                             struct messaging_context *msg_ctx,
123                                             uint32_t max_clients,
124                                             struct smbXsrv_client_table **_table)
125 {
126         struct smbXsrv_client_table *table;
127         NTSTATUS status;
128
129         if (max_clients > 1) {
130                 return NT_STATUS_INTERNAL_ERROR;
131         }
132
133         table = talloc_zero(mem_ctx, struct smbXsrv_client_table);
134         if (table == NULL) {
135                 return NT_STATUS_NO_MEMORY;
136         }
137
138         table->local.max_clients = max_clients;
139
140         status = smbXsrv_client_global_init();
141         if (!NT_STATUS_IS_OK(status)) {
142                 TALLOC_FREE(table);
143                 return status;
144         }
145
146         table->global.db_ctx = smbXsrv_client_global_db_ctx;
147
148         dbwrap_watch_db(table->global.db_ctx, msg_ctx);
149
150         *_table = table;
151         return NT_STATUS_OK;
152 }
153
154 static int smbXsrv_client_global_destructor(struct smbXsrv_client_global0 *global)
155 {
156         return 0;
157 }
158
159 static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
160                                         bool *is_free,
161                                         bool *was_free,
162                                         TALLOC_CTX *mem_ctx,
163                                         struct smbXsrv_client_global0 **_g)
164 {
165         TDB_DATA key;
166         TDB_DATA val;
167         DATA_BLOB blob;
168         struct smbXsrv_client_globalB global_blob;
169         enum ndr_err_code ndr_err;
170         struct smbXsrv_client_global0 *global = NULL;
171         bool exists;
172         TALLOC_CTX *frame = talloc_stackframe();
173
174         *is_free = false;
175
176         if (was_free) {
177                 *was_free = false;
178         }
179         if (_g) {
180                 *_g = NULL;
181         }
182
183         key = dbwrap_record_get_key(db_rec);
184
185         val = dbwrap_record_get_value(db_rec);
186         if (val.dsize == 0) {
187                 TALLOC_FREE(frame);
188                 *is_free = true;
189                 if (was_free) {
190                         *was_free = true;
191                 }
192                 return;
193         }
194
195         blob = data_blob_const(val.dptr, val.dsize);
196
197         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
198                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_client_globalB);
199         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
200                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
201                 DBG_WARNING("smbXsrv_client_global_verify_record: "
202                             "key '%s' ndr_pull_struct_blob - %s\n",
203                             hex_encode_talloc(frame, key.dptr, key.dsize),
204                             nt_errstr(status));
205                 TALLOC_FREE(frame);
206                 return;
207         }
208
209         DBG_DEBUG("client_global:\n");
210         if (DEBUGLVL(DBGLVL_DEBUG)) {
211                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
212         }
213
214         if (global_blob.version != SMBXSRV_VERSION_0) {
215                 DBG_ERR("key '%s' use unsupported version %u\n",
216                         hex_encode_talloc(frame, key.dptr, key.dsize),
217                         global_blob.version);
218                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
219                 TALLOC_FREE(frame);
220                 return;
221         }
222
223         global = global_blob.info.info0;
224
225         exists = serverid_exists(&global->server_id);
226         if (!exists) {
227                 struct server_id_buf tmp;
228
229                 DBG_NOTICE("key '%s' server_id %s does not exist.\n",
230                            hex_encode_talloc(frame, key.dptr, key.dsize),
231                            server_id_str_buf(global->server_id, &tmp));
232                 if (DEBUGLVL(DBGLVL_NOTICE)) {
233                         NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
234                 }
235                 TALLOC_FREE(frame);
236                 dbwrap_record_delete(db_rec);
237                 *is_free = true;
238                 return;
239         }
240
241         if (_g) {
242                 *_g = talloc_move(mem_ctx, &global);
243         }
244         TALLOC_FREE(frame);
245 }
246
247 NTSTATUS smb2srv_client_lookup_global(struct smbXsrv_client *client,
248                                       struct GUID client_guid,
249                                       TALLOC_CTX *mem_ctx,
250                                       struct smbXsrv_client_global0 **_global)
251 {
252         struct smbXsrv_client_table *table = client->table;
253         struct smbXsrv_client_global0 *global = NULL;
254         bool is_free = false;
255         uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE];
256         TDB_DATA key;
257         struct db_record *db_rec;
258
259         key = smbXsrv_client_global_id_to_key(&client_guid, key_buf);
260
261         db_rec = dbwrap_fetch_locked(table->global.db_ctx,
262                                      talloc_tos(), key);
263         if (db_rec == NULL) {
264                 DBG_ERR("guid [%s]: Failed to lock key '%s'\n",
265                         GUID_string(talloc_tos(), &client_guid),
266                         hex_encode_talloc(talloc_tos(), key.dptr, key.dsize));
267                 return NT_STATUS_INTERNAL_DB_ERROR;
268         }
269
270         smbXsrv_client_global_verify_record(db_rec,
271                                             &is_free,
272                                             NULL,
273                                             mem_ctx,
274                                             &global);
275         TALLOC_FREE(db_rec);
276
277         if (is_free) {
278                 return NT_STATUS_OBJECTID_NOT_FOUND;
279         }
280
281         *_global = global;
282         return NT_STATUS_OK;
283 }
284
285 NTSTATUS smb2srv_client_connection_pass(struct smbd_smb2_request *smb2req,
286                                         struct smbXsrv_client_global0 *global)
287 {
288         DATA_BLOB blob;
289         enum ndr_err_code ndr_err;
290         NTSTATUS status;
291         struct smbXsrv_connection_pass0 pass_info0;
292         struct smbXsrv_connection_passB pass_blob;
293         ssize_t reqlen;
294         struct iovec iov;
295
296         pass_info0.initial_connect_time = global->initial_connect_time;
297         pass_info0.client_guid = global->client_guid;
298
299         reqlen = iov_buflen(smb2req->in.vector, smb2req->in.vector_count);
300         if (reqlen == -1) {
301                 return NT_STATUS_INVALID_BUFFER_SIZE;
302         }
303
304         pass_info0.negotiate_request.length = reqlen;
305         pass_info0.negotiate_request.data = talloc_array(talloc_tos(), uint8_t,
306                                                          reqlen);
307         if (pass_info0.negotiate_request.data == NULL) {
308                 return NT_STATUS_NO_MEMORY;
309         }
310         iov_buf(smb2req->in.vector, smb2req->in.vector_count,
311                 pass_info0.negotiate_request.data,
312                 pass_info0.negotiate_request.length);
313
314         ZERO_STRUCT(pass_blob);
315         pass_blob.version = smbXsrv_version_global_current();
316         pass_blob.info.info0 = &pass_info0;
317
318         if (DEBUGLVL(DBGLVL_DEBUG)) {
319                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
320         }
321
322         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &pass_blob,
323                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_connection_passB);
324         data_blob_free(&pass_info0.negotiate_request);
325         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
326                 status = ndr_map_error2ntstatus(ndr_err);
327                 return status;
328         }
329
330         iov.iov_base = blob.data;
331         iov.iov_len = blob.length;
332
333         status = messaging_send_iov(smb2req->xconn->msg_ctx,
334                                     global->server_id,
335                                     MSG_SMBXSRV_CONNECTION_PASS,
336                                     &iov, 1,
337                                     &smb2req->xconn->transport.sock, 1);
338         data_blob_free(&blob);
339         if (!NT_STATUS_IS_OK(status)) {
340                 return status;
341         }
342
343         return NT_STATUS_OK;
344 }
345
346 static NTSTATUS smbXsrv_client_global_store(struct smbXsrv_client_global0 *global)
347 {
348         struct smbXsrv_client_globalB global_blob;
349         DATA_BLOB blob = data_blob_null;
350         TDB_DATA key;
351         TDB_DATA val;
352         NTSTATUS status;
353         enum ndr_err_code ndr_err;
354         bool saved_stored = global->stored;
355
356         /*
357          * TODO: if we use other versions than '0'
358          * we would add glue code here, that would be able to
359          * store the information in the old format.
360          */
361
362         if (global->db_rec == NULL) {
363                 return NT_STATUS_INTERNAL_ERROR;
364         }
365
366         key = dbwrap_record_get_key(global->db_rec);
367         val = dbwrap_record_get_value(global->db_rec);
368
369         ZERO_STRUCT(global_blob);
370         global_blob.version = smbXsrv_version_global_current();
371         if (val.dsize >= 8) {
372                 global_blob.seqnum = IVAL(val.dptr, 4);
373         }
374         global_blob.seqnum += 1;
375         global_blob.info.info0 = global;
376
377         global->stored = true;
378         ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
379                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_client_globalB);
380         global->stored = saved_stored;
381         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
382                 status = ndr_map_error2ntstatus(ndr_err);
383                 DBG_WARNING("key '%s' ndr_push - %s\n",
384                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
385                         nt_errstr(status));
386                 TALLOC_FREE(global->db_rec);
387                 return status;
388         }
389
390         val = make_tdb_data(blob.data, blob.length);
391         status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
392         if (!NT_STATUS_IS_OK(status)) {
393                 DBG_WARNING("key '%s' store - %s\n",
394                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
395                         nt_errstr(status));
396                 TALLOC_FREE(global->db_rec);
397                 return status;
398         }
399
400         global->stored = true;
401
402         if (DEBUGLVL(DBGLVL_DEBUG)) {
403                 DBG_DEBUG("key '%s' stored\n",
404                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize));
405                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
406         }
407
408         TALLOC_FREE(global->db_rec);
409
410         return NT_STATUS_OK;
411 }
412
413 static NTSTATUS smbXsrv_client_global_remove(struct smbXsrv_client_global0 *global)
414 {
415         struct smbXsrv_client_globalB global_blob;
416         TDB_DATA key;
417         NTSTATUS status;
418
419         /*
420          * TODO: if we use other versions than '0'
421          * we would add glue code here, that would be able to
422          * store the information in the old format.
423          */
424
425         if (global->db_rec == NULL) {
426                 return NT_STATUS_INTERNAL_ERROR;
427         }
428
429         key = dbwrap_record_get_key(global->db_rec);
430
431         status = dbwrap_record_delete(global->db_rec);
432         if (!NT_STATUS_IS_OK(status)) {
433                 DBG_WARNING("key '%s' delete - %s\n",
434                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
435                         nt_errstr(status));
436                 TALLOC_FREE(global->db_rec);
437                 return status;
438         }
439         global->stored = false;
440         if (DEBUGLVL(DBGLVL_DEBUG)) {
441                 DBG_DEBUG("key '%s' delete\n",
442                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize));
443                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
444         }
445
446         TALLOC_FREE(global->db_rec);
447
448         return NT_STATUS_OK;
449 }
450
451 static int smbXsrv_client_destructor(struct smbXsrv_client *client)
452 {
453         NTSTATUS status;
454
455         status = smbXsrv_client_remove(client);
456         if (!NT_STATUS_IS_OK(status)) {
457                 DBG_ERR("smbXsrv_client_remove() failed: %s\n",
458                         nt_errstr(status));
459         }
460
461         TALLOC_FREE(client->global);
462
463         return 0;
464 }
465
466 static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data);
467 static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq);
468
469 NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx,
470                                struct tevent_context *ev_ctx,
471                                struct messaging_context *msg_ctx,
472                                NTTIME now,
473                                struct smbXsrv_client **_client)
474 {
475         struct smbXsrv_client_table *table;
476         struct smbXsrv_client *client = NULL;
477         struct smbXsrv_client_global0 *global = NULL;
478         NTSTATUS status;
479         struct tevent_req *subreq = NULL;
480
481         status = smbXsrv_client_table_create(mem_ctx,
482                                              msg_ctx,
483                                              1, /* max_clients */
484                                              &table);
485         if (!NT_STATUS_IS_OK(status)) {
486                 return status;
487         }
488
489         if (table->local.num_clients >= table->local.max_clients) {
490                 TALLOC_FREE(table);
491                 return NT_STATUS_INSUFFICIENT_RESOURCES;
492         }
493
494         client = talloc_zero(mem_ctx, struct smbXsrv_client);
495         if (client == NULL) {
496                 TALLOC_FREE(table);
497                 return NT_STATUS_NO_MEMORY;
498         }
499         client->ev_ctx = ev_ctx;
500         client->msg_ctx = msg_ctx;
501
502         client->table = talloc_move(client, &table);
503         table = client->table;
504
505         global = talloc_zero(client, struct smbXsrv_client_global0);
506         if (global == NULL) {
507                 TALLOC_FREE(client);
508                 return NT_STATUS_NO_MEMORY;
509         }
510         talloc_set_destructor(global, smbXsrv_client_global_destructor);
511         client->global = global;
512
513         global->initial_connect_time = now;
514
515         global->server_id = messaging_server_id(client->msg_ctx);
516
517         table->local.num_clients += 1;
518
519         talloc_set_destructor(client, smbXsrv_client_destructor);
520
521         if (DEBUGLVL(DBGLVL_DEBUG)) {
522                 struct smbXsrv_clientB client_blob;
523
524                 ZERO_STRUCT(client_blob);
525                 client_blob.version = SMBXSRV_VERSION_0;
526                 client_blob.info.info0 = client;
527
528                 DBG_DEBUG("client_guid[%s] stored\n",
529                           GUID_string(talloc_tos(), &global->client_guid));
530                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
531         }
532
533         subreq = messaging_filtered_read_send(client, client->ev_ctx, client->msg_ctx,
534                                               smbXsrv_client_connection_pass_filter,
535                                               client);
536         if (subreq == NULL) {
537                 TALLOC_FREE(client);
538                 return NT_STATUS_NO_MEMORY;
539         }
540         tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
541
542         *_client = client;
543         return NT_STATUS_OK;
544 }
545
546 static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data)
547 {
548         if (rec->msg_type != MSG_SMBXSRV_CONNECTION_PASS) {
549                 return false;
550         }
551
552         if (rec->num_fds != 1) {
553                 return false;
554         }
555
556         if (rec->buf.length < SMB2_HDR_BODY) {
557                 return false;
558         }
559
560         /* TODO: verify client_guid...? */
561
562         return true;
563 }
564
565 static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq)
566 {
567         struct smbXsrv_client *client =
568                 tevent_req_callback_data(subreq,
569                 struct smbXsrv_client);
570         struct smbXsrv_connection *xconn = NULL;
571         int ret;
572         struct messaging_rec *rec = NULL;
573         struct smbXsrv_connection_passB pass_blob;
574         enum ndr_err_code ndr_err;
575         struct smbXsrv_connection_pass0 *pass_info0 = NULL;
576         NTSTATUS status;
577         int sock_fd = -1;
578         uint64_t seq_low;
579
580         ret = messaging_filtered_read_recv(subreq, talloc_tos(), &rec);
581         TALLOC_FREE(subreq);
582         if (ret != 0) {
583                 goto next;
584         }
585
586         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &pass_blob,
587                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_connection_passB);
588         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
589                 status = ndr_map_error2ntstatus(ndr_err);
590                 DBG_WARNING("ndr_pull_struct_blob - %s\n", nt_errstr(status));
591                 goto next;
592         }
593
594         DBG_DEBUG("MSG_SMBXSRV_CLIENT_CLOSE\n");
595         if (DEBUGLVL(DBGLVL_DEBUG)) {
596                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
597         }
598
599         if (pass_blob.version != SMBXSRV_VERSION_0) {
600                 DBG_ERR("ignore invalid version %u\n", pass_blob.version);
601                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
602                 goto next;
603         }
604
605         pass_info0 = pass_blob.info.info0;
606         if (pass_info0 == NULL) {
607                 DBG_ERR("ignore NULL info %u\n", pass_blob.version);
608                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
609                 goto next;
610         }
611
612         if (!GUID_equal(&client->global->client_guid, &pass_info0->client_guid))
613         {
614                 DBG_WARNING("client's client_guid [%s] != passed guid [%s]\n",
615                         GUID_string(talloc_tos(), &client->global->client_guid),
616                         GUID_string(talloc_tos(), &pass_info0->client_guid));
617                 if (DEBUGLVL(DBGLVL_WARNING)) {
618                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
619                 }
620                 goto next;
621         }
622
623         if (client->global->initial_connect_time !=
624             pass_info0->initial_connect_time)
625         {
626                 DBG_WARNING("client's initial connect time [%s] (%llu) != "
627                         "passed initial connect time [%s] (%llu)\n",
628                         nt_time_string(talloc_tos(),
629                                        client->global->initial_connect_time),
630                         (unsigned long long)client->global->initial_connect_time,
631                         nt_time_string(talloc_tos(),
632                                        pass_info0->initial_connect_time),
633                         (unsigned long long)pass_info0->initial_connect_time);
634                 if (DEBUGLVL(DBGLVL_WARNING)) {
635                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
636                 }
637                 goto next;
638         }
639
640         SMB_ASSERT(rec->num_fds == 1);
641         sock_fd = rec->fds[0];
642
643         DBG_ERR("got connection sockfd[%d]\n", sock_fd);
644         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
645         status = smbd_add_connection(client, sock_fd, &xconn);
646         if (!NT_STATUS_IS_OK(status)) {
647                 close(sock_fd);
648                 sock_fd = -1;
649                 DBG_ERR("smbd_add_connection => %s\n", nt_errstr(status));
650                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
651                 goto next;
652         }
653
654         /*
655          * Set seq_low to mid received in negprot
656          */
657         seq_low = BVAL(pass_info0->negotiate_request.data,
658                        SMB2_HDR_MESSAGE_ID);
659
660         xconn->smb2.client.guid_verified = true;
661         smbd_smb2_process_negprot(xconn, seq_low,
662                                   pass_info0->negotiate_request.data,
663                                   pass_info0->negotiate_request.length);
664
665 next:
666         TALLOC_FREE(rec);
667
668         subreq = messaging_filtered_read_send(client, client->ev_ctx, client->msg_ctx,
669                                               smbXsrv_client_connection_pass_filter,
670                                               client);
671         if (subreq == NULL) {
672                 const char *r;
673                 r = "messaging_read_send(MSG_SMBXSRV_CONNECTION_PASS failed";
674                 exit_server_cleanly(r);
675                 return;
676         }
677         tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
678 }
679
680 NTSTATUS smbXsrv_client_update(struct smbXsrv_client *client)
681 {
682         struct smbXsrv_client_table *table = client->table;
683         NTSTATUS status;
684         uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE];
685         TDB_DATA key;
686
687         if (client->global->db_rec != NULL) {
688                 DBG_ERR("guid [%s]: Called with db_rec != NULL'\n",
689                         GUID_string(talloc_tos(),
690                         &client->global->client_guid));
691                 return NT_STATUS_INTERNAL_ERROR;
692         }
693
694         key = smbXsrv_client_global_id_to_key(&client->global->client_guid,
695                                               key_buf);
696
697         client->global->db_rec = dbwrap_fetch_locked(table->global.db_ctx,
698                                                      client->global, key);
699         if (client->global->db_rec == NULL) {
700                 DBG_ERR("guid [%s]: Failed to lock key '%s'\n",
701                         GUID_string(talloc_tos(), &client->global->client_guid),
702                         hex_encode_talloc(talloc_tos(), key.dptr, key.dsize));
703                 return NT_STATUS_INTERNAL_DB_ERROR;
704         }
705
706         status = smbXsrv_client_global_store(client->global);
707         if (!NT_STATUS_IS_OK(status)) {
708                 DBG_ERR("client_guid[%s] store failed - %s\n",
709                         GUID_string(talloc_tos(), &client->global->client_guid),
710                         nt_errstr(status));
711                 return status;
712         }
713
714         if (DEBUGLVL(DBGLVL_DEBUG)) {
715                 struct smbXsrv_clientB client_blob;
716
717                 ZERO_STRUCT(client_blob);
718                 client_blob.version = SMBXSRV_VERSION_0;
719                 client_blob.info.info0 = client;
720
721                 DBG_DEBUG("client_guid[%s] stored\n",
722                         GUID_string(talloc_tos(), &client->global->client_guid));
723                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
724         }
725
726         return NT_STATUS_OK;
727 }
728
729 NTSTATUS smbXsrv_client_remove(struct smbXsrv_client *client)
730 {
731         struct smbXsrv_client_table *table = client->table;
732         NTSTATUS status;
733         uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE];
734         TDB_DATA key;
735
736         if (client->global->db_rec != NULL) {
737                 DBG_ERR("client_guid[%s]: Called with db_rec != NULL'\n",
738                         GUID_string(talloc_tos(), &client->global->client_guid));
739                 return NT_STATUS_INTERNAL_ERROR;
740         }
741
742         if (!client->global->stored) {
743                 return NT_STATUS_OK;
744         }
745
746         key = smbXsrv_client_global_id_to_key(&client->global->client_guid,
747                                               key_buf);
748
749         client->global->db_rec = dbwrap_fetch_locked(table->global.db_ctx,
750                                                      client->global, key);
751         if (client->global->db_rec == NULL) {
752                 DBG_ERR("client_guid[%s]: Failed to lock key '%s'\n",
753                         GUID_string(talloc_tos(), &client->global->client_guid),
754                         hex_encode_talloc(talloc_tos(), key.dptr, key.dsize));
755                 return NT_STATUS_INTERNAL_DB_ERROR;
756         }
757
758         status = smbXsrv_client_global_remove(client->global);
759         if (!NT_STATUS_IS_OK(status)) {
760                 DBG_ERR("client_guid[%s] store failed - %s\n",
761                         GUID_string(talloc_tos(), &client->global->client_guid),
762                         nt_errstr(status));
763                 return status;
764         }
765
766         if (DEBUGLVL(DBGLVL_DEBUG)) {
767                 struct smbXsrv_clientB client_blob;
768
769                 ZERO_STRUCT(client_blob);
770                 client_blob.version = SMBXSRV_VERSION_0;
771                 client_blob.info.info0 = client;
772
773                 DBG_DEBUG("client_guid[%s] stored\n",
774                         GUID_string(talloc_tos(), &client->global->client_guid));
775                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
776         }
777
778         return NT_STATUS_OK;
779 }