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