ca04ae75ec77da172221b108e6c7387ea6bcb91b
[kai/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 struct db_record *smbXsrv_client_global_fetch_locked(
122                         struct db_context *db,
123                         const struct GUID *client_guid,
124                         TALLOC_CTX *mem_ctx)
125 {
126         TDB_DATA key;
127         uint8_t key_buf[SMBXSRV_CLIENT_GLOBAL_TDB_KEY_SIZE];
128         struct db_record *rec = NULL;
129
130         key = smbXsrv_client_global_id_to_key(client_guid, key_buf);
131
132         rec = dbwrap_fetch_locked(db, mem_ctx, key);
133
134         if (rec == NULL) {
135                 DBG_DEBUG("Failed to lock guid [%s], key '%s'\n",
136                           GUID_string(talloc_tos(), client_guid),
137                           hex_encode_talloc(talloc_tos(), key.dptr, key.dsize));
138         }
139
140         return rec;
141 }
142
143 static NTSTATUS smbXsrv_client_table_create(TALLOC_CTX *mem_ctx,
144                                             struct messaging_context *msg_ctx,
145                                             uint32_t max_clients,
146                                             struct smbXsrv_client_table **_table)
147 {
148         struct smbXsrv_client_table *table;
149         NTSTATUS status;
150
151         if (max_clients > 1) {
152                 return NT_STATUS_INTERNAL_ERROR;
153         }
154
155         table = talloc_zero(mem_ctx, struct smbXsrv_client_table);
156         if (table == NULL) {
157                 return NT_STATUS_NO_MEMORY;
158         }
159
160         table->local.max_clients = max_clients;
161
162         status = smbXsrv_client_global_init();
163         if (!NT_STATUS_IS_OK(status)) {
164                 TALLOC_FREE(table);
165                 return status;
166         }
167
168         table->global.db_ctx = smbXsrv_client_global_db_ctx;
169
170         *_table = table;
171         return NT_STATUS_OK;
172 }
173
174 static int smbXsrv_client_global_destructor(struct smbXsrv_client_global0 *global)
175 {
176         return 0;
177 }
178
179 static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
180                                         bool *is_free,
181                                         bool *was_free,
182                                         TALLOC_CTX *mem_ctx,
183                                         struct smbXsrv_client_global0 **_g)
184 {
185         TDB_DATA key;
186         TDB_DATA val;
187         DATA_BLOB blob;
188         struct smbXsrv_client_globalB global_blob;
189         enum ndr_err_code ndr_err;
190         struct smbXsrv_client_global0 *global = NULL;
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
203         key = dbwrap_record_get_key(db_rec);
204
205         val = dbwrap_record_get_value(db_rec);
206         if (val.dsize == 0) {
207                 TALLOC_FREE(frame);
208                 *is_free = true;
209                 if (was_free) {
210                         *was_free = true;
211                 }
212                 return;
213         }
214
215         blob = data_blob_const(val.dptr, val.dsize);
216
217         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
218                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_client_globalB);
219         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
220                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
221                 DBG_WARNING("smbXsrv_client_global_verify_record: "
222                             "key '%s' ndr_pull_struct_blob - %s\n",
223                             hex_encode_talloc(frame, key.dptr, key.dsize),
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' use unsupported version %u\n",
236                         hex_encode_talloc(frame, key.dptr, key.dsize),
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         exists = serverid_exists(&global->server_id);
246         if (!exists) {
247                 struct server_id_buf tmp;
248
249                 DBG_NOTICE("key '%s' server_id %s does not exist.\n",
250                            hex_encode_talloc(frame, key.dptr, key.dsize),
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         if (_g) {
262                 *_g = talloc_move(mem_ctx, &global);
263         }
264         TALLOC_FREE(frame);
265 }
266
267 NTSTATUS smb2srv_client_lookup_global(struct smbXsrv_client *client,
268                                       struct GUID client_guid,
269                                       TALLOC_CTX *mem_ctx,
270                                       struct smbXsrv_client_global0 **_global)
271 {
272         struct smbXsrv_client_table *table = client->table;
273         struct smbXsrv_client_global0 *global = NULL;
274         bool is_free = false;
275         struct db_record *db_rec;
276
277         db_rec = smbXsrv_client_global_fetch_locked(table->global.db_ctx,
278                                                     &client_guid,
279                                                     talloc_tos());
280         if (db_rec == NULL) {
281                 return NT_STATUS_INTERNAL_DB_ERROR;
282         }
283
284         smbXsrv_client_global_verify_record(db_rec,
285                                             &is_free,
286                                             NULL,
287                                             mem_ctx,
288                                             &global);
289         TALLOC_FREE(db_rec);
290
291         if (is_free) {
292                 return NT_STATUS_OBJECTID_NOT_FOUND;
293         }
294
295         *_global = global;
296         return NT_STATUS_OK;
297 }
298
299 NTSTATUS smb2srv_client_connection_pass(struct smbd_smb2_request *smb2req,
300                                         struct smbXsrv_client_global0 *global)
301 {
302         DATA_BLOB blob;
303         enum ndr_err_code ndr_err;
304         NTSTATUS status;
305         struct smbXsrv_connection_pass0 pass_info0;
306         struct smbXsrv_connection_passB pass_blob;
307         ssize_t reqlen;
308         struct iovec iov;
309
310         pass_info0.initial_connect_time = global->initial_connect_time;
311         pass_info0.client_guid = global->client_guid;
312
313         reqlen = iov_buflen(smb2req->in.vector, smb2req->in.vector_count);
314         if (reqlen == -1) {
315                 return NT_STATUS_INVALID_BUFFER_SIZE;
316         }
317
318         pass_info0.negotiate_request.length = reqlen;
319         pass_info0.negotiate_request.data = talloc_array(talloc_tos(), uint8_t,
320                                                          reqlen);
321         if (pass_info0.negotiate_request.data == NULL) {
322                 return NT_STATUS_NO_MEMORY;
323         }
324         iov_buf(smb2req->in.vector, smb2req->in.vector_count,
325                 pass_info0.negotiate_request.data,
326                 pass_info0.negotiate_request.length);
327
328         ZERO_STRUCT(pass_blob);
329         pass_blob.version = smbXsrv_version_global_current();
330         pass_blob.info.info0 = &pass_info0;
331
332         if (DEBUGLVL(DBGLVL_DEBUG)) {
333                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
334         }
335
336         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &pass_blob,
337                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_connection_passB);
338         data_blob_free(&pass_info0.negotiate_request);
339         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
340                 status = ndr_map_error2ntstatus(ndr_err);
341                 return status;
342         }
343
344         iov.iov_base = blob.data;
345         iov.iov_len = blob.length;
346
347         status = messaging_send_iov(smb2req->xconn->msg_ctx,
348                                     global->server_id,
349                                     MSG_SMBXSRV_CONNECTION_PASS,
350                                     &iov, 1,
351                                     &smb2req->xconn->transport.sock, 1);
352         data_blob_free(&blob);
353         if (!NT_STATUS_IS_OK(status)) {
354                 return status;
355         }
356
357         return NT_STATUS_OK;
358 }
359
360 static NTSTATUS smbXsrv_client_global_store(struct smbXsrv_client_global0 *global)
361 {
362         struct smbXsrv_client_globalB global_blob;
363         DATA_BLOB blob = data_blob_null;
364         TDB_DATA key;
365         TDB_DATA val;
366         NTSTATUS status;
367         enum ndr_err_code ndr_err;
368         bool saved_stored = global->stored;
369
370         /*
371          * TODO: if we use other versions than '0'
372          * we would add glue code here, that would be able to
373          * store the information in the old format.
374          */
375
376         if (global->db_rec == NULL) {
377                 return NT_STATUS_INTERNAL_ERROR;
378         }
379
380         key = dbwrap_record_get_key(global->db_rec);
381         val = dbwrap_record_get_value(global->db_rec);
382
383         ZERO_STRUCT(global_blob);
384         global_blob.version = smbXsrv_version_global_current();
385         if (val.dsize >= 8) {
386                 global_blob.seqnum = IVAL(val.dptr, 4);
387         }
388         global_blob.seqnum += 1;
389         global_blob.info.info0 = global;
390
391         global->stored = true;
392         ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
393                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_client_globalB);
394         global->stored = saved_stored;
395         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
396                 status = ndr_map_error2ntstatus(ndr_err);
397                 DBG_WARNING("key '%s' ndr_push - %s\n",
398                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
399                         nt_errstr(status));
400                 TALLOC_FREE(global->db_rec);
401                 return status;
402         }
403
404         val = make_tdb_data(blob.data, blob.length);
405         status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
406         if (!NT_STATUS_IS_OK(status)) {
407                 DBG_WARNING("key '%s' store - %s\n",
408                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
409                         nt_errstr(status));
410                 TALLOC_FREE(global->db_rec);
411                 return status;
412         }
413
414         global->stored = true;
415
416         if (DEBUGLVL(DBGLVL_DEBUG)) {
417                 DBG_DEBUG("key '%s' stored\n",
418                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize));
419                 NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
420         }
421
422         TALLOC_FREE(global->db_rec);
423
424         return NT_STATUS_OK;
425 }
426
427 static NTSTATUS smbXsrv_client_global_remove(struct smbXsrv_client_global0 *global)
428 {
429         TDB_DATA key;
430         NTSTATUS status;
431
432         /*
433          * TODO: if we use other versions than '0'
434          * we would add glue code here, that would be able to
435          * store the information in the old format.
436          */
437
438         if (global->db_rec == NULL) {
439                 return NT_STATUS_INTERNAL_ERROR;
440         }
441
442         key = dbwrap_record_get_key(global->db_rec);
443
444         status = dbwrap_record_delete(global->db_rec);
445         if (!NT_STATUS_IS_OK(status)) {
446                 DBG_WARNING("key '%s' delete - %s\n",
447                         hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
448                         nt_errstr(status));
449                 TALLOC_FREE(global->db_rec);
450                 return status;
451         }
452         global->stored = false;
453         DBG_DEBUG("key '%s' delete\n",
454                   hex_encode_talloc(global->db_rec, key.dptr, key.dsize));
455
456         TALLOC_FREE(global->db_rec);
457
458         return NT_STATUS_OK;
459 }
460
461 static int smbXsrv_client_destructor(struct smbXsrv_client *client)
462 {
463         NTSTATUS status;
464
465         status = smbXsrv_client_remove(client);
466         if (!NT_STATUS_IS_OK(status)) {
467                 DBG_ERR("smbXsrv_client_remove() failed: %s\n",
468                         nt_errstr(status));
469         }
470
471         TALLOC_FREE(client->global);
472
473         return 0;
474 }
475
476 static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data);
477 static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq);
478
479 NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx,
480                                struct tevent_context *ev_ctx,
481                                struct messaging_context *msg_ctx,
482                                NTTIME now,
483                                struct smbXsrv_client **_client)
484 {
485         struct smbXsrv_client_table *table;
486         struct smbXsrv_client *client = NULL;
487         struct smbXsrv_client_global0 *global = NULL;
488         NTSTATUS status;
489         struct tevent_req *subreq = NULL;
490
491         status = smbXsrv_client_table_create(mem_ctx,
492                                              msg_ctx,
493                                              1, /* max_clients */
494                                              &table);
495         if (!NT_STATUS_IS_OK(status)) {
496                 return status;
497         }
498
499         if (table->local.num_clients >= table->local.max_clients) {
500                 TALLOC_FREE(table);
501                 return NT_STATUS_INSUFFICIENT_RESOURCES;
502         }
503
504         client = talloc_zero(mem_ctx, struct smbXsrv_client);
505         if (client == NULL) {
506                 TALLOC_FREE(table);
507                 return NT_STATUS_NO_MEMORY;
508         }
509         client->ev_ctx = ev_ctx;
510         client->msg_ctx = msg_ctx;
511
512         client->server_multi_channel_enabled = lp_server_multi_channel_support();
513
514         client->table = talloc_move(client, &table);
515         table = client->table;
516
517         global = talloc_zero(client, struct smbXsrv_client_global0);
518         if (global == NULL) {
519                 TALLOC_FREE(client);
520                 return NT_STATUS_NO_MEMORY;
521         }
522         talloc_set_destructor(global, smbXsrv_client_global_destructor);
523         client->global = global;
524
525         global->initial_connect_time = now;
526
527         global->server_id = messaging_server_id(client->msg_ctx);
528
529         table->local.num_clients += 1;
530
531         talloc_set_destructor(client, smbXsrv_client_destructor);
532
533         if (DEBUGLVL(DBGLVL_DEBUG)) {
534                 struct smbXsrv_clientB client_blob;
535
536                 ZERO_STRUCT(client_blob);
537                 client_blob.version = SMBXSRV_VERSION_0;
538                 client_blob.info.info0 = client;
539
540                 DBG_DEBUG("client_guid[%s] stored\n",
541                           GUID_string(talloc_tos(), &global->client_guid));
542                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
543         }
544
545         subreq = messaging_filtered_read_send(client, client->ev_ctx, client->msg_ctx,
546                                               smbXsrv_client_connection_pass_filter,
547                                               client);
548         if (subreq == NULL) {
549                 TALLOC_FREE(client);
550                 return NT_STATUS_NO_MEMORY;
551         }
552         tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
553
554         *_client = client;
555         return NT_STATUS_OK;
556 }
557
558 static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data)
559 {
560         if (rec->msg_type != MSG_SMBXSRV_CONNECTION_PASS) {
561                 return false;
562         }
563
564         if (rec->num_fds != 1) {
565                 return false;
566         }
567
568         if (rec->buf.length < SMB2_HDR_BODY) {
569                 return false;
570         }
571
572         /* TODO: verify client_guid...? */
573
574         return true;
575 }
576
577 static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq)
578 {
579         struct smbXsrv_client *client =
580                 tevent_req_callback_data(subreq,
581                 struct smbXsrv_client);
582         struct smbXsrv_connection *xconn = NULL;
583         int ret;
584         struct messaging_rec *rec = NULL;
585         struct smbXsrv_connection_passB pass_blob;
586         enum ndr_err_code ndr_err;
587         struct smbXsrv_connection_pass0 *pass_info0 = NULL;
588         NTSTATUS status;
589         int sock_fd = -1;
590         uint64_t seq_low;
591
592         ret = messaging_filtered_read_recv(subreq, talloc_tos(), &rec);
593         TALLOC_FREE(subreq);
594         if (ret != 0) {
595                 goto next;
596         }
597
598         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &pass_blob,
599                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_connection_passB);
600         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
601                 status = ndr_map_error2ntstatus(ndr_err);
602                 DBG_WARNING("ndr_pull_struct_blob - %s\n", nt_errstr(status));
603                 goto next;
604         }
605
606         DBG_DEBUG("MSG_SMBXSRV_CLIENT_CLOSE\n");
607         if (DEBUGLVL(DBGLVL_DEBUG)) {
608                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
609         }
610
611         if (pass_blob.version != SMBXSRV_VERSION_0) {
612                 DBG_ERR("ignore invalid version %u\n", pass_blob.version);
613                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
614                 goto next;
615         }
616
617         pass_info0 = pass_blob.info.info0;
618         if (pass_info0 == NULL) {
619                 DBG_ERR("ignore NULL info %u\n", pass_blob.version);
620                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
621                 goto next;
622         }
623
624         if (!GUID_equal(&client->global->client_guid, &pass_info0->client_guid))
625         {
626                 DBG_WARNING("client's client_guid [%s] != passed guid [%s]\n",
627                         GUID_string(talloc_tos(), &client->global->client_guid),
628                         GUID_string(talloc_tos(), &pass_info0->client_guid));
629                 if (DEBUGLVL(DBGLVL_WARNING)) {
630                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
631                 }
632                 goto next;
633         }
634
635         if (client->global->initial_connect_time !=
636             pass_info0->initial_connect_time)
637         {
638                 DBG_WARNING("client's initial connect time [%s] (%llu) != "
639                         "passed initial connect time [%s] (%llu)\n",
640                         nt_time_string(talloc_tos(),
641                                        client->global->initial_connect_time),
642                         (unsigned long long)client->global->initial_connect_time,
643                         nt_time_string(talloc_tos(),
644                                        pass_info0->initial_connect_time),
645                         (unsigned long long)pass_info0->initial_connect_time);
646                 if (DEBUGLVL(DBGLVL_WARNING)) {
647                         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
648                 }
649                 goto next;
650         }
651
652         SMB_ASSERT(rec->num_fds == 1);
653         sock_fd = rec->fds[0];
654
655         DBG_ERR("got connection sockfd[%d]\n", sock_fd);
656         NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
657         status = smbd_add_connection(client, sock_fd, &xconn);
658         if (!NT_STATUS_IS_OK(status)) {
659                 close(sock_fd);
660                 sock_fd = -1;
661                 DBG_ERR("smbd_add_connection => %s\n", nt_errstr(status));
662                 NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob);
663                 goto next;
664         }
665
666         /*
667          * Set seq_low to mid received in negprot
668          */
669         seq_low = BVAL(pass_info0->negotiate_request.data,
670                        SMB2_HDR_MESSAGE_ID);
671
672         xconn->smb2.client.guid_verified = true;
673         smbd_smb2_process_negprot(xconn, seq_low,
674                                   pass_info0->negotiate_request.data,
675                                   pass_info0->negotiate_request.length);
676
677 next:
678         TALLOC_FREE(rec);
679
680         subreq = messaging_filtered_read_send(client, client->ev_ctx, client->msg_ctx,
681                                               smbXsrv_client_connection_pass_filter,
682                                               client);
683         if (subreq == NULL) {
684                 const char *r;
685                 r = "messaging_read_send(MSG_SMBXSRV_CONNECTION_PASS failed";
686                 exit_server_cleanly(r);
687                 return;
688         }
689         tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
690 }
691
692 NTSTATUS smbXsrv_client_update(struct smbXsrv_client *client)
693 {
694         struct smbXsrv_client_table *table = client->table;
695         NTSTATUS status;
696
697         if (client->global->db_rec != NULL) {
698                 DBG_ERR("guid [%s]: Called with db_rec != NULL'\n",
699                         GUID_string(talloc_tos(),
700                         &client->global->client_guid));
701                 return NT_STATUS_INTERNAL_ERROR;
702         }
703
704         client->global->db_rec = smbXsrv_client_global_fetch_locked(
705                                         table->global.db_ctx,
706                                         &client->global->client_guid,
707                                         client->global /* TALLOC_CTX */);
708         if (client->global->db_rec == NULL) {
709                 return NT_STATUS_INTERNAL_DB_ERROR;
710         }
711
712         status = smbXsrv_client_global_store(client->global);
713         if (!NT_STATUS_IS_OK(status)) {
714                 DBG_ERR("client_guid[%s] store failed - %s\n",
715                         GUID_string(talloc_tos(), &client->global->client_guid),
716                         nt_errstr(status));
717                 return status;
718         }
719
720         if (DEBUGLVL(DBGLVL_DEBUG)) {
721                 struct smbXsrv_clientB client_blob;
722
723                 ZERO_STRUCT(client_blob);
724                 client_blob.version = SMBXSRV_VERSION_0;
725                 client_blob.info.info0 = client;
726
727                 DBG_DEBUG("client_guid[%s] stored\n",
728                         GUID_string(talloc_tos(), &client->global->client_guid));
729                 NDR_PRINT_DEBUG(smbXsrv_clientB, &client_blob);
730         }
731
732         return NT_STATUS_OK;
733 }
734
735 NTSTATUS smbXsrv_client_remove(struct smbXsrv_client *client)
736 {
737         struct smbXsrv_client_table *table = client->table;
738         NTSTATUS status;
739
740         if (client->global->db_rec != NULL) {
741                 DBG_ERR("client_guid[%s]: Called with db_rec != NULL'\n",
742                         GUID_string(talloc_tos(), &client->global->client_guid));
743                 return NT_STATUS_INTERNAL_ERROR;
744         }
745
746         if (!client->global->stored) {
747                 return NT_STATUS_OK;
748         }
749
750         client->global->db_rec = smbXsrv_client_global_fetch_locked(
751                                         table->global.db_ctx,
752                                         &client->global->client_guid,
753                                         client->global /* TALLOC_CTX */);
754         if (client->global->db_rec == NULL) {
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 }