Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Stefan Metzmacher 2011-2012
5 : Copyright (C) Michael Adam 2012
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "smbXsrv_session.h"
23 : #include "system/filesys.h"
24 : #include <tevent.h>
25 : #include "lib/util/server_id.h"
26 : #include "smbd/smbd.h"
27 : #include "smbd/globals.h"
28 : #include "dbwrap/dbwrap.h"
29 : #include "dbwrap/dbwrap_rbt.h"
30 : #include "dbwrap/dbwrap_open.h"
31 : #include "dbwrap/dbwrap_watch.h"
32 : #include "session.h"
33 : #include "auth.h"
34 : #include "auth/gensec/gensec.h"
35 : #include "../lib/tsocket/tsocket.h"
36 : #include "../libcli/security/security.h"
37 : #include "messages.h"
38 : #include "lib/util/util_tdb.h"
39 : #include "librpc/gen_ndr/ndr_smbXsrv.h"
40 : #include "serverid.h"
41 : #include "lib/util/tevent_ntstatus.h"
42 : #include "lib/global_contexts.h"
43 : #include "source3/include/util_tdb.h"
44 :
45 : struct smbXsrv_session_table {
46 : struct {
47 : struct db_context *db_ctx;
48 : uint32_t lowest_id;
49 : uint32_t highest_id;
50 : uint32_t max_sessions;
51 : uint32_t num_sessions;
52 : } local;
53 : struct {
54 : struct db_context *db_ctx;
55 : } global;
56 : };
57 :
58 : static struct db_context *smbXsrv_session_global_db_ctx = NULL;
59 :
60 30724 : NTSTATUS smbXsrv_session_global_init(struct messaging_context *msg_ctx)
61 : {
62 30724 : char *global_path = NULL;
63 30724 : struct db_context *backend = NULL;
64 30724 : struct db_context *db_ctx = NULL;
65 :
66 30724 : if (smbXsrv_session_global_db_ctx != NULL) {
67 30702 : return NT_STATUS_OK;
68 : }
69 :
70 : /*
71 : * This contains secret information like session keys!
72 : */
73 22 : global_path = lock_path(talloc_tos(), "smbXsrv_session_global.tdb");
74 22 : if (global_path == NULL) {
75 0 : return NT_STATUS_NO_MEMORY;
76 : }
77 :
78 22 : backend = db_open(NULL, global_path,
79 : SMBD_VOLATILE_TDB_HASH_SIZE,
80 : SMBD_VOLATILE_TDB_FLAGS,
81 : O_RDWR | O_CREAT, 0600,
82 : DBWRAP_LOCK_ORDER_1,
83 : DBWRAP_FLAG_NONE);
84 22 : TALLOC_FREE(global_path);
85 22 : if (backend == NULL) {
86 0 : NTSTATUS status;
87 :
88 0 : status = map_nt_error_from_unix_common(errno);
89 :
90 0 : return status;
91 : }
92 :
93 22 : db_ctx = db_open_watched(NULL, &backend, global_messaging_context());
94 22 : if (db_ctx == NULL) {
95 0 : TALLOC_FREE(backend);
96 0 : return NT_STATUS_NO_MEMORY;
97 : }
98 :
99 22 : smbXsrv_session_global_db_ctx = db_ctx;
100 :
101 22 : return NT_STATUS_OK;
102 : }
103 :
104 : /*
105 : * NOTE:
106 : * We need to store the keys in big endian so that dbwrap_rbt's memcmp
107 : * has the same result as integer comparison between the uint32_t
108 : * values.
109 : *
110 : * TODO: implement string based key
111 : */
112 :
113 : #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
114 :
115 190900 : static TDB_DATA smbXsrv_session_global_id_to_key(uint32_t id,
116 : uint8_t *key_buf)
117 : {
118 4300 : TDB_DATA key;
119 :
120 190900 : RSIVAL(key_buf, 0, id);
121 :
122 190900 : key = make_tdb_data(key_buf, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE);
123 :
124 190900 : return key;
125 : }
126 :
127 : #if 0
128 : static NTSTATUS smbXsrv_session_global_key_to_id(TDB_DATA key, uint32_t *id)
129 : {
130 : if (id == NULL) {
131 : return NT_STATUS_INVALID_PARAMETER;
132 : }
133 :
134 : if (key.dsize != SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE) {
135 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
136 : }
137 :
138 : *id = RIVAL(key.dptr, 0);
139 :
140 : return NT_STATUS_OK;
141 : }
142 : #endif
143 :
144 : #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
145 :
146 3992431 : static TDB_DATA smbXsrv_session_local_id_to_key(uint32_t id,
147 : uint8_t *key_buf)
148 : {
149 38893 : TDB_DATA key;
150 :
151 3992431 : RSIVAL(key_buf, 0, id);
152 :
153 3992431 : key = make_tdb_data(key_buf, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE);
154 :
155 3992431 : return key;
156 : }
157 :
158 0 : static NTSTATUS smbXsrv_session_local_key_to_id(TDB_DATA key, uint32_t *id)
159 : {
160 0 : if (id == NULL) {
161 0 : return NT_STATUS_INVALID_PARAMETER;
162 : }
163 :
164 0 : if (key.dsize != SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE) {
165 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
166 : }
167 :
168 0 : *id = RIVAL(key.dptr, 0);
169 :
170 0 : return NT_STATUS_OK;
171 : }
172 :
173 190900 : static struct db_record *smbXsrv_session_global_fetch_locked(
174 : struct db_context *db,
175 : uint32_t id,
176 : TALLOC_CTX *mem_ctx)
177 : {
178 4300 : TDB_DATA key;
179 4300 : uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE];
180 190900 : struct db_record *rec = NULL;
181 :
182 190900 : key = smbXsrv_session_global_id_to_key(id, key_buf);
183 :
184 190900 : rec = dbwrap_fetch_locked(db, mem_ctx, key);
185 :
186 190900 : if (rec == NULL) {
187 0 : DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id,
188 : tdb_data_dbg(key));
189 : }
190 :
191 190900 : return rec;
192 : }
193 :
194 33511 : static struct db_record *smbXsrv_session_local_fetch_locked(
195 : struct db_context *db,
196 : uint32_t id,
197 : TALLOC_CTX *mem_ctx)
198 : {
199 781 : TDB_DATA key;
200 781 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
201 33511 : struct db_record *rec = NULL;
202 :
203 33511 : key = smbXsrv_session_local_id_to_key(id, key_buf);
204 :
205 33511 : rec = dbwrap_fetch_locked(db, mem_ctx, key);
206 :
207 33511 : if (rec == NULL) {
208 0 : DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id,
209 : tdb_data_dbg(key));
210 : }
211 :
212 33511 : return rec;
213 : }
214 :
215 : static void smbXsrv_session_close_loop(struct tevent_req *subreq);
216 :
217 30682 : static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn,
218 : uint32_t lowest_id,
219 : uint32_t highest_id,
220 : uint32_t max_sessions)
221 : {
222 30682 : struct smbXsrv_client *client = conn->client;
223 834 : struct smbXsrv_session_table *table;
224 834 : NTSTATUS status;
225 834 : struct tevent_req *subreq;
226 834 : uint64_t max_range;
227 :
228 30682 : if (lowest_id > highest_id) {
229 0 : return NT_STATUS_INTERNAL_ERROR;
230 : }
231 :
232 30682 : max_range = highest_id;
233 30682 : max_range -= lowest_id;
234 30682 : max_range += 1;
235 :
236 30682 : if (max_sessions > max_range) {
237 0 : return NT_STATUS_INTERNAL_ERROR;
238 : }
239 :
240 30682 : table = talloc_zero(client, struct smbXsrv_session_table);
241 30682 : if (table == NULL) {
242 0 : return NT_STATUS_NO_MEMORY;
243 : }
244 :
245 30682 : table->local.db_ctx = db_open_rbt(table);
246 30682 : if (table->local.db_ctx == NULL) {
247 0 : TALLOC_FREE(table);
248 0 : return NT_STATUS_NO_MEMORY;
249 : }
250 30682 : table->local.lowest_id = lowest_id;
251 30682 : table->local.highest_id = highest_id;
252 30682 : table->local.max_sessions = max_sessions;
253 :
254 30682 : status = smbXsrv_session_global_init(client->msg_ctx);
255 30682 : if (!NT_STATUS_IS_OK(status)) {
256 0 : TALLOC_FREE(table);
257 0 : return status;
258 : }
259 :
260 30682 : table->global.db_ctx = smbXsrv_session_global_db_ctx;
261 :
262 30682 : subreq = messaging_read_send(table,
263 : client->raw_ev_ctx,
264 : client->msg_ctx,
265 : MSG_SMBXSRV_SESSION_CLOSE);
266 30682 : if (subreq == NULL) {
267 0 : TALLOC_FREE(table);
268 0 : return NT_STATUS_NO_MEMORY;
269 : }
270 30682 : tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
271 :
272 30682 : client->session_table = table;
273 30682 : return NT_STATUS_OK;
274 : }
275 :
276 : static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq);
277 :
278 54 : static void smbXsrv_session_close_loop(struct tevent_req *subreq)
279 : {
280 4 : struct smbXsrv_client *client =
281 54 : tevent_req_callback_data(subreq,
282 : struct smbXsrv_client);
283 54 : struct smbXsrv_session_table *table = client->session_table;
284 4 : int ret;
285 54 : struct messaging_rec *rec = NULL;
286 4 : struct smbXsrv_session_closeB close_blob;
287 4 : enum ndr_err_code ndr_err;
288 54 : struct smbXsrv_session_close0 *close_info0 = NULL;
289 54 : struct smbXsrv_session *session = NULL;
290 4 : NTSTATUS status;
291 54 : struct timeval tv = timeval_current();
292 54 : NTTIME now = timeval_to_nttime(&tv);
293 :
294 54 : ret = messaging_read_recv(subreq, talloc_tos(), &rec);
295 54 : TALLOC_FREE(subreq);
296 54 : if (ret != 0) {
297 0 : goto next;
298 : }
299 :
300 54 : ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &close_blob,
301 : (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_closeB);
302 54 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
303 0 : status = ndr_map_error2ntstatus(ndr_err);
304 0 : DBG_WARNING("ndr_pull_struct_blob - %s\n", nt_errstr(status));
305 0 : goto next;
306 : }
307 :
308 54 : DBG_DEBUG("MSG_SMBXSRV_SESSION_CLOSE\n");
309 54 : if (DEBUGLVL(DBGLVL_DEBUG)) {
310 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
311 : }
312 :
313 54 : if (close_blob.version != SMBXSRV_VERSION_0) {
314 0 : DBG_ERR("ignore invalid version %u\n", close_blob.version);
315 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
316 0 : goto next;
317 : }
318 :
319 54 : close_info0 = close_blob.info.info0;
320 54 : if (close_info0 == NULL) {
321 0 : DBG_ERR("ignore NULL info %u\n", close_blob.version);
322 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
323 0 : goto next;
324 : }
325 :
326 54 : status = smb2srv_session_lookup_client(client,
327 : close_info0->old_session_wire_id,
328 : now, &session);
329 54 : if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
330 0 : DBG_INFO("old_session_wire_id %" PRIu64 " not found\n",
331 : close_info0->old_session_wire_id);
332 0 : if (DEBUGLVL(DBGLVL_INFO)) {
333 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
334 : }
335 0 : goto next;
336 : }
337 54 : if (!NT_STATUS_IS_OK(status) &&
338 0 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
339 0 : !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
340 0 : DBG_WARNING("old_session_wire_id %" PRIu64 " - %s\n",
341 : close_info0->old_session_wire_id,
342 : nt_errstr(status));
343 0 : if (DEBUGLVL(DBGLVL_WARNING)) {
344 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
345 : }
346 0 : goto next;
347 : }
348 :
349 54 : if (session->global->session_global_id != close_info0->old_session_global_id) {
350 0 : DBG_WARNING("old_session_wire_id %" PRIu64 " - "
351 : "global %" PRIu32 " != %" PRIu32 "\n",
352 : close_info0->old_session_wire_id,
353 : session->global->session_global_id,
354 : close_info0->old_session_global_id);
355 0 : if (DEBUGLVL(DBGLVL_WARNING)) {
356 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
357 : }
358 0 : goto next;
359 : }
360 :
361 54 : if (session->global->creation_time != close_info0->old_creation_time) {
362 0 : DBG_WARNING("old_session_wire_id %" PRIu64 " - "
363 : "creation %s (%" PRIu64 ") != %s (%" PRIu64 ")\n",
364 : close_info0->old_session_wire_id,
365 : nt_time_string(rec,
366 : session->global->creation_time),
367 : session->global->creation_time,
368 : nt_time_string(rec,
369 : close_info0->old_creation_time),
370 : close_info0->old_creation_time);
371 0 : if (DEBUGLVL(DBGLVL_WARNING)) {
372 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
373 : }
374 0 : goto next;
375 : }
376 :
377 54 : subreq = smb2srv_session_shutdown_send(session, client->raw_ev_ctx,
378 : session, NULL);
379 54 : if (subreq == NULL) {
380 0 : status = NT_STATUS_NO_MEMORY;
381 0 : DBG_ERR("smb2srv_session_shutdown_send(%" PRIu64
382 : ") failed: %s\n",
383 : session->global->session_wire_id,
384 : nt_errstr(status));
385 0 : if (DEBUGLVL(DBGLVL_WARNING)) {
386 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
387 : }
388 0 : goto next;
389 : }
390 54 : tevent_req_set_callback(subreq,
391 : smbXsrv_session_close_shutdown_done,
392 : session);
393 :
394 54 : next:
395 54 : TALLOC_FREE(rec);
396 :
397 54 : subreq = messaging_read_send(table,
398 : client->raw_ev_ctx,
399 : client->msg_ctx,
400 : MSG_SMBXSRV_SESSION_CLOSE);
401 54 : if (subreq == NULL) {
402 0 : const char *r;
403 0 : r = "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
404 0 : exit_server_cleanly(r);
405 : return;
406 : }
407 54 : tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
408 : }
409 :
410 54 : static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq)
411 : {
412 4 : struct smbXsrv_session *session =
413 54 : tevent_req_callback_data(subreq,
414 : struct smbXsrv_session);
415 4 : NTSTATUS status;
416 :
417 54 : status = smb2srv_session_shutdown_recv(subreq);
418 54 : TALLOC_FREE(subreq);
419 54 : if (!NT_STATUS_IS_OK(status)) {
420 0 : DBG_ERR("smb2srv_session_shutdown_recv(%" PRIu64
421 : ") failed: %s\n",
422 : session->global->session_wire_id,
423 : nt_errstr(status));
424 : }
425 :
426 54 : status = smbXsrv_session_logoff(session);
427 54 : if (!NT_STATUS_IS_OK(status)) {
428 0 : DBG_ERR("smbXsrv_session_logoff(%" PRIu64 ") failed: %s\n",
429 : session->global->session_wire_id,
430 : nt_errstr(status));
431 : }
432 :
433 54 : TALLOC_FREE(session);
434 54 : }
435 :
436 : struct smb1srv_session_local_allocate_state {
437 : const uint32_t lowest_id;
438 : const uint32_t highest_id;
439 : uint32_t last_id;
440 : uint32_t useable_id;
441 : NTSTATUS status;
442 : };
443 :
444 0 : static int smb1srv_session_local_allocate_traverse(struct db_record *rec,
445 : void *private_data)
446 : {
447 0 : struct smb1srv_session_local_allocate_state *state =
448 : (struct smb1srv_session_local_allocate_state *)private_data;
449 0 : TDB_DATA key = dbwrap_record_get_key(rec);
450 0 : uint32_t id = 0;
451 0 : NTSTATUS status;
452 :
453 0 : status = smbXsrv_session_local_key_to_id(key, &id);
454 0 : if (!NT_STATUS_IS_OK(status)) {
455 0 : state->status = status;
456 0 : return -1;
457 : }
458 :
459 0 : if (id <= state->last_id) {
460 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
461 0 : return -1;
462 : }
463 0 : state->last_id = id;
464 :
465 0 : if (id > state->useable_id) {
466 0 : state->status = NT_STATUS_OK;
467 0 : return -1;
468 : }
469 :
470 0 : if (state->useable_id == state->highest_id) {
471 0 : state->status = NT_STATUS_INSUFFICIENT_RESOURCES;
472 0 : return -1;
473 : }
474 :
475 0 : state->useable_id +=1;
476 0 : return 0;
477 : }
478 :
479 7239 : static NTSTATUS smb1srv_session_local_allocate_id(struct db_context *db,
480 : uint32_t lowest_id,
481 : uint32_t highest_id,
482 : TALLOC_CTX *mem_ctx,
483 : struct db_record **_rec,
484 : uint32_t *_id)
485 : {
486 7239 : struct smb1srv_session_local_allocate_state state = {
487 : .lowest_id = lowest_id,
488 : .highest_id = highest_id,
489 : .last_id = 0,
490 : .useable_id = lowest_id,
491 : .status = NT_STATUS_INTERNAL_ERROR,
492 : };
493 133 : uint32_t i;
494 133 : uint32_t range;
495 133 : NTSTATUS status;
496 7239 : int count = 0;
497 :
498 7239 : *_rec = NULL;
499 7239 : *_id = 0;
500 :
501 7239 : if (lowest_id > highest_id) {
502 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
503 : }
504 :
505 : /*
506 : * first we try randomly
507 : */
508 7239 : range = (highest_id - lowest_id) + 1;
509 :
510 7239 : for (i = 0; i < (range / 2); i++) {
511 133 : uint32_t id;
512 133 : TDB_DATA val;
513 7239 : struct db_record *rec = NULL;
514 :
515 7239 : id = generate_random() % range;
516 7239 : id += lowest_id;
517 :
518 7239 : if (id < lowest_id) {
519 0 : id = lowest_id;
520 : }
521 7239 : if (id > highest_id) {
522 0 : id = highest_id;
523 : }
524 :
525 7239 : rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
526 7239 : if (rec == NULL) {
527 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
528 : }
529 :
530 7239 : val = dbwrap_record_get_value(rec);
531 7239 : if (val.dsize != 0) {
532 0 : TALLOC_FREE(rec);
533 0 : continue;
534 : }
535 :
536 7239 : *_rec = rec;
537 7239 : *_id = id;
538 7239 : return NT_STATUS_OK;
539 : }
540 :
541 : /*
542 : * if the range is almost full,
543 : * we traverse the whole table
544 : * (this relies on sorted behavior of dbwrap_rbt)
545 : */
546 0 : status = dbwrap_traverse_read(db, smb1srv_session_local_allocate_traverse,
547 : &state, &count);
548 0 : if (NT_STATUS_IS_OK(status)) {
549 0 : if (NT_STATUS_IS_OK(state.status)) {
550 0 : return NT_STATUS_INTERNAL_ERROR;
551 : }
552 :
553 0 : if (!NT_STATUS_EQUAL(state.status, NT_STATUS_INTERNAL_ERROR)) {
554 0 : return state.status;
555 : }
556 :
557 0 : if (state.useable_id <= state.highest_id) {
558 0 : state.status = NT_STATUS_OK;
559 : } else {
560 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
561 : }
562 0 : } else if (!NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_CORRUPTION)) {
563 : /*
564 : * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
565 : *
566 : * If we get anything else it is an error, because it
567 : * means we did not manage to find a free slot in
568 : * the db.
569 : */
570 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
571 : }
572 :
573 0 : if (NT_STATUS_IS_OK(state.status)) {
574 0 : uint32_t id;
575 0 : TDB_DATA val;
576 0 : struct db_record *rec = NULL;
577 :
578 0 : id = state.useable_id;
579 :
580 0 : rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
581 0 : if (rec == NULL) {
582 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
583 : }
584 :
585 0 : val = dbwrap_record_get_value(rec);
586 0 : if (val.dsize != 0) {
587 0 : TALLOC_FREE(rec);
588 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
589 : }
590 :
591 0 : *_rec = rec;
592 0 : *_id = id;
593 0 : return NT_STATUS_OK;
594 : }
595 :
596 0 : return state.status;
597 : }
598 :
599 : struct smbXsrv_session_local_fetch_state {
600 : struct smbXsrv_session *session;
601 : NTSTATUS status;
602 : };
603 :
604 3957846 : static void smbXsrv_session_local_fetch_parser(TDB_DATA key, TDB_DATA data,
605 : void *private_data)
606 : {
607 3957846 : struct smbXsrv_session_local_fetch_state *state =
608 : (struct smbXsrv_session_local_fetch_state *)private_data;
609 37946 : void *ptr;
610 :
611 3957846 : if (data.dsize != sizeof(ptr)) {
612 0 : state->status = NT_STATUS_INTERNAL_DB_ERROR;
613 0 : return;
614 : }
615 :
616 3957846 : memcpy(&ptr, data.dptr, data.dsize);
617 3957846 : state->session = talloc_get_type_abort(ptr, struct smbXsrv_session);
618 3957846 : state->status = NT_STATUS_OK;
619 : }
620 :
621 2163748 : static NTSTATUS smbXsrv_session_local_lookup(struct smbXsrv_session_table *table,
622 : /* conn: optional */
623 : struct smbXsrv_connection *conn,
624 : uint32_t session_local_id,
625 : NTTIME now,
626 : struct smbXsrv_session **_session)
627 : {
628 2163748 : struct smbXsrv_session_local_fetch_state state = {
629 : .session = NULL,
630 : .status = NT_STATUS_INTERNAL_ERROR,
631 : };
632 21491 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
633 21491 : TDB_DATA key;
634 21491 : NTSTATUS status;
635 :
636 2163748 : *_session = NULL;
637 :
638 2163748 : if (session_local_id == 0) {
639 81249 : return NT_STATUS_USER_SESSION_DELETED;
640 : }
641 :
642 2082499 : if (table == NULL) {
643 : /* this might happen before the end of negprot */
644 0 : return NT_STATUS_USER_SESSION_DELETED;
645 : }
646 :
647 2082499 : if (table->local.db_ctx == NULL) {
648 0 : return NT_STATUS_INTERNAL_ERROR;
649 : }
650 :
651 2082499 : key = smbXsrv_session_local_id_to_key(session_local_id, key_buf);
652 :
653 2082499 : status = dbwrap_parse_record(table->local.db_ctx, key,
654 : smbXsrv_session_local_fetch_parser,
655 : &state);
656 2082499 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
657 1057 : return NT_STATUS_USER_SESSION_DELETED;
658 2081442 : } else if (!NT_STATUS_IS_OK(status)) {
659 0 : return status;
660 : }
661 2081442 : if (!NT_STATUS_IS_OK(state.status)) {
662 0 : return state.status;
663 : }
664 :
665 2081442 : if (NT_STATUS_EQUAL(state.session->status, NT_STATUS_USER_SESSION_DELETED)) {
666 0 : return NT_STATUS_USER_SESSION_DELETED;
667 : }
668 :
669 : /*
670 : * If a connection is specified check if the session is
671 : * valid on the channel.
672 : */
673 2081442 : if (conn != NULL) {
674 2061855 : struct smbXsrv_channel_global0 *c = NULL;
675 :
676 2061855 : status = smbXsrv_session_find_channel(state.session, conn, &c);
677 2061855 : if (!NT_STATUS_IS_OK(status)) {
678 140 : return status;
679 : }
680 : }
681 :
682 2081302 : state.session->idle_time = now;
683 :
684 2081302 : if (!NT_STATUS_IS_OK(state.session->status)) {
685 30293 : *_session = state.session;
686 30293 : return state.session->status;
687 : }
688 :
689 2051009 : if (now > state.session->global->expiration_time) {
690 49 : state.session->status = NT_STATUS_NETWORK_SESSION_EXPIRED;
691 : }
692 :
693 2051009 : *_session = state.session;
694 2051009 : return state.session->status;
695 : }
696 :
697 31113 : static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0 *global)
698 : {
699 31113 : return 0;
700 : }
701 :
702 : static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
703 : bool *is_free,
704 : bool *was_free,
705 : TALLOC_CTX *mem_ctx,
706 : struct smbXsrv_session_global0 **_g,
707 : uint32_t *pseqnum);
708 :
709 31127 : static NTSTATUS smbXsrv_session_global_allocate(struct db_context *db,
710 : TALLOC_CTX *mem_ctx,
711 : struct smbXsrv_session_global0 **_global)
712 : {
713 760 : uint32_t i;
714 31127 : struct smbXsrv_session_global0 *global = NULL;
715 31127 : uint32_t last_free = 0;
716 31127 : const uint32_t min_tries = 3;
717 :
718 31127 : *_global = NULL;
719 :
720 31127 : global = talloc_zero(mem_ctx, struct smbXsrv_session_global0);
721 31127 : if (global == NULL) {
722 0 : return NT_STATUS_NO_MEMORY;
723 : }
724 31127 : talloc_set_destructor(global, smbXsrv_session_global_destructor);
725 :
726 : /*
727 : * Here we just randomly try the whole 32-bit space
728 : *
729 : * We use just 32-bit, because we want to reuse the
730 : * ID for SRVSVC.
731 : */
732 31887 : for (i = 0; i < UINT32_MAX; i++) {
733 31127 : bool is_free = false;
734 31127 : bool was_free = false;
735 760 : uint32_t id;
736 :
737 31127 : if (i >= min_tries && last_free != 0) {
738 0 : id = last_free;
739 : } else {
740 31127 : id = generate_random();
741 : }
742 31127 : if (id == 0) {
743 0 : id++;
744 : }
745 31127 : if (id == UINT32_MAX) {
746 0 : id--;
747 : }
748 :
749 31127 : global->db_rec = smbXsrv_session_global_fetch_locked(db, id,
750 : mem_ctx);
751 31127 : if (global->db_rec == NULL) {
752 0 : talloc_free(global);
753 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
754 : }
755 :
756 31127 : smbXsrv_session_global_verify_record(global->db_rec,
757 : &is_free,
758 : &was_free,
759 : NULL, NULL, NULL);
760 :
761 31127 : if (!is_free) {
762 0 : TALLOC_FREE(global->db_rec);
763 0 : continue;
764 : }
765 :
766 31127 : if (!was_free && i < min_tries) {
767 : /*
768 : * The session_id is free now,
769 : * but was not free before.
770 : *
771 : * This happens if a smbd crashed
772 : * and did not cleanup the record.
773 : *
774 : * If this is one of our first tries,
775 : * then we try to find a real free one.
776 : */
777 0 : if (last_free == 0) {
778 0 : last_free = id;
779 : }
780 0 : TALLOC_FREE(global->db_rec);
781 0 : continue;
782 : }
783 :
784 31127 : global->session_global_id = id;
785 :
786 31127 : *_global = global;
787 31127 : return NT_STATUS_OK;
788 : }
789 :
790 : /* should not be reached */
791 0 : talloc_free(global);
792 0 : return NT_STATUS_INTERNAL_ERROR;
793 : }
794 :
795 32452 : static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
796 : bool *is_free,
797 : bool *was_free,
798 : TALLOC_CTX *mem_ctx,
799 : struct smbXsrv_session_global0 **_g,
800 : uint32_t *pseqnum)
801 : {
802 973 : TDB_DATA key;
803 973 : TDB_DATA val;
804 973 : DATA_BLOB blob;
805 973 : struct smbXsrv_session_globalB global_blob;
806 973 : enum ndr_err_code ndr_err;
807 32452 : struct smbXsrv_session_global0 *global = NULL;
808 973 : bool exists;
809 32452 : TALLOC_CTX *frame = talloc_stackframe();
810 :
811 32452 : *is_free = false;
812 :
813 32452 : if (was_free) {
814 31127 : *was_free = false;
815 : }
816 32452 : if (_g) {
817 1325 : *_g = NULL;
818 : }
819 32452 : if (pseqnum) {
820 158 : *pseqnum = 0;
821 : }
822 :
823 32452 : key = dbwrap_record_get_key(db_rec);
824 :
825 32452 : val = dbwrap_record_get_value(db_rec);
826 32452 : if (val.dsize == 0) {
827 31239 : TALLOC_FREE(frame);
828 31239 : *is_free = true;
829 31239 : if (was_free) {
830 31127 : *was_free = true;
831 : }
832 31239 : return;
833 : }
834 :
835 1213 : blob = data_blob_const(val.dptr, val.dsize);
836 :
837 1213 : ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
838 : (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
839 1213 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
840 0 : NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
841 0 : DBG_WARNING("key '%s' ndr_pull_struct_blob - %s\n",
842 : tdb_data_dbg(key),
843 : nt_errstr(status));
844 0 : TALLOC_FREE(frame);
845 0 : *is_free = true;
846 0 : if (was_free) {
847 0 : *was_free = true;
848 : }
849 0 : return;
850 : }
851 :
852 1213 : DBG_DEBUG("smbXsrv_session_global_verify_record\n");
853 1213 : if (DEBUGLVL(DBGLVL_DEBUG)) {
854 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
855 : }
856 :
857 1213 : if (global_blob.version != SMBXSRV_VERSION_0) {
858 0 : DBG_ERR("key '%s' use unsupported version %u\n",
859 : tdb_data_dbg(key),
860 : global_blob.version);
861 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
862 0 : TALLOC_FREE(frame);
863 0 : *is_free = true;
864 0 : if (was_free) {
865 0 : *was_free = true;
866 : }
867 0 : return;
868 : }
869 :
870 1213 : global = global_blob.info.info0;
871 :
872 : #define __BLOB_KEEP_SECRET(__blob) do { \
873 : if ((__blob).length != 0) { \
874 : talloc_keep_secret((__blob).data); \
875 : } \
876 : } while(0)
877 : {
878 209 : uint32_t i;
879 1213 : __BLOB_KEEP_SECRET(global->application_key_blob);
880 1213 : __BLOB_KEEP_SECRET(global->signing_key_blob);
881 1213 : __BLOB_KEEP_SECRET(global->encryption_key_blob);
882 1213 : __BLOB_KEEP_SECRET(global->decryption_key_blob);
883 2434 : for (i = 0; i < global->num_channels; i++) {
884 1221 : __BLOB_KEEP_SECRET(global->channels[i].signing_key_blob);
885 : }
886 : }
887 : #undef __BLOB_KEEP_SECRET
888 :
889 1213 : exists = serverid_exists(&global->channels[0].server_id);
890 1213 : if (!exists) {
891 0 : struct server_id_buf idbuf;
892 0 : DBG_NOTICE("key '%s' server_id %s does not exist.\n",
893 : tdb_data_dbg(key),
894 : server_id_str_buf(global->channels[0].server_id,
895 : &idbuf));
896 0 : if (DEBUGLVL(DBGLVL_NOTICE)) {
897 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
898 : }
899 0 : TALLOC_FREE(frame);
900 0 : dbwrap_record_delete(db_rec);
901 0 : *is_free = true;
902 0 : return;
903 : }
904 :
905 1213 : if (_g) {
906 1213 : *_g = talloc_move(mem_ctx, &global);
907 : }
908 1213 : if (pseqnum) {
909 56 : *pseqnum = global_blob.seqnum;
910 : }
911 1213 : TALLOC_FREE(frame);
912 : }
913 :
914 158462 : static NTSTATUS smbXsrv_session_global_store(struct smbXsrv_session_global0 *global)
915 : {
916 3327 : struct smbXsrv_session_globalB global_blob;
917 158462 : DATA_BLOB blob = data_blob_null;
918 3327 : TDB_DATA key;
919 3327 : TDB_DATA val;
920 3327 : NTSTATUS status;
921 3327 : enum ndr_err_code ndr_err;
922 :
923 : /*
924 : * TODO: if we use other versions than '0'
925 : * we would add glue code here, that would be able to
926 : * store the information in the old format.
927 : */
928 :
929 158462 : if (global->db_rec == NULL) {
930 0 : return NT_STATUS_INTERNAL_ERROR;
931 : }
932 :
933 158462 : key = dbwrap_record_get_key(global->db_rec);
934 158462 : val = dbwrap_record_get_value(global->db_rec);
935 :
936 158462 : ZERO_STRUCT(global_blob);
937 158462 : global_blob.version = smbXsrv_version_global_current();
938 158462 : if (val.dsize >= 8) {
939 127335 : global_blob.seqnum = IVAL(val.dptr, 4);
940 : }
941 158462 : global_blob.seqnum += 1;
942 158462 : global_blob.info.info0 = global;
943 :
944 158462 : ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
945 : (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_globalB);
946 158462 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
947 0 : status = ndr_map_error2ntstatus(ndr_err);
948 0 : DBG_WARNING("key '%s' ndr_push - %s\n",
949 : tdb_data_dbg(key),
950 : nt_errstr(status));
951 0 : TALLOC_FREE(global->db_rec);
952 0 : return status;
953 : }
954 :
955 158462 : val = make_tdb_data(blob.data, blob.length);
956 158462 : status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
957 158462 : if (!NT_STATUS_IS_OK(status)) {
958 0 : DBG_WARNING("key '%s' store - %s\n",
959 : tdb_data_dbg(key),
960 : nt_errstr(status));
961 0 : TALLOC_FREE(global->db_rec);
962 0 : return status;
963 : }
964 :
965 158462 : if (DEBUGLVL(DBGLVL_DEBUG)) {
966 0 : DBG_DEBUG("key '%s' stored\n", tdb_data_dbg(key));
967 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
968 : }
969 :
970 158462 : TALLOC_FREE(global->db_rec);
971 :
972 158462 : return NT_STATUS_OK;
973 : }
974 :
975 : struct smb2srv_session_close_previous_state {
976 : struct tevent_context *ev;
977 : struct smbXsrv_connection *connection;
978 : struct dom_sid *current_sid;
979 : uint64_t previous_session_id;
980 : uint64_t current_session_id;
981 : struct db_record *db_rec;
982 : uint64_t watch_instance;
983 : uint32_t last_seqnum;
984 : };
985 :
986 204 : static void smb2srv_session_close_previous_cleanup(struct tevent_req *req,
987 : enum tevent_req_state req_state)
988 : {
989 8 : struct smb2srv_session_close_previous_state *state =
990 204 : tevent_req_data(req,
991 : struct smb2srv_session_close_previous_state);
992 :
993 204 : if (state->db_rec != NULL) {
994 102 : dbwrap_watched_watch_remove_instance(state->db_rec,
995 : state->watch_instance);
996 102 : state->watch_instance = 0;
997 102 : TALLOC_FREE(state->db_rec);
998 : }
999 204 : }
1000 :
1001 : static void smb2srv_session_close_previous_check(struct tevent_req *req);
1002 : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq);
1003 :
1004 102 : struct tevent_req *smb2srv_session_close_previous_send(TALLOC_CTX *mem_ctx,
1005 : struct tevent_context *ev,
1006 : struct smbXsrv_connection *conn,
1007 : struct auth_session_info *session_info,
1008 : uint64_t previous_session_id,
1009 : uint64_t current_session_id)
1010 : {
1011 4 : struct tevent_req *req;
1012 4 : struct smb2srv_session_close_previous_state *state;
1013 102 : uint32_t global_id = previous_session_id & UINT32_MAX;
1014 102 : uint64_t global_zeros = previous_session_id & 0xFFFFFFFF00000000LLU;
1015 102 : struct smbXsrv_session_table *table = conn->client->session_table;
1016 102 : struct security_token *current_token = NULL;
1017 :
1018 102 : req = tevent_req_create(mem_ctx, &state,
1019 : struct smb2srv_session_close_previous_state);
1020 102 : if (req == NULL) {
1021 0 : return NULL;
1022 : }
1023 102 : state->ev = ev;
1024 102 : state->connection = conn;
1025 102 : state->previous_session_id = previous_session_id;
1026 102 : state->current_session_id = current_session_id;
1027 :
1028 102 : tevent_req_set_cleanup_fn(req, smb2srv_session_close_previous_cleanup);
1029 :
1030 102 : if (global_zeros != 0) {
1031 0 : tevent_req_done(req);
1032 0 : return tevent_req_post(req, ev);
1033 : }
1034 :
1035 102 : if (session_info == NULL) {
1036 0 : tevent_req_done(req);
1037 0 : return tevent_req_post(req, ev);
1038 : }
1039 102 : current_token = session_info->security_token;
1040 :
1041 102 : if (current_token->num_sids > PRIMARY_USER_SID_INDEX) {
1042 102 : state->current_sid = ¤t_token->sids[PRIMARY_USER_SID_INDEX];
1043 : }
1044 :
1045 102 : if (state->current_sid == NULL) {
1046 0 : tevent_req_done(req);
1047 0 : return tevent_req_post(req, ev);
1048 : }
1049 :
1050 102 : if (!security_token_has_nt_authenticated_users(current_token)) {
1051 : /* TODO */
1052 0 : tevent_req_done(req);
1053 0 : return tevent_req_post(req, ev);
1054 : }
1055 :
1056 102 : state->db_rec = smbXsrv_session_global_fetch_locked(
1057 : table->global.db_ctx,
1058 : global_id,
1059 : state /* TALLOC_CTX */);
1060 102 : if (state->db_rec == NULL) {
1061 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1062 0 : return tevent_req_post(req, ev);
1063 : }
1064 :
1065 102 : smb2srv_session_close_previous_check(req);
1066 102 : if (!tevent_req_is_in_progress(req)) {
1067 46 : return tevent_req_post(req, ev);
1068 : }
1069 :
1070 52 : return req;
1071 : }
1072 :
1073 158 : static void smb2srv_session_close_previous_check(struct tevent_req *req)
1074 : {
1075 8 : struct smb2srv_session_close_previous_state *state =
1076 158 : tevent_req_data(req,
1077 : struct smb2srv_session_close_previous_state);
1078 158 : struct smbXsrv_connection *conn = state->connection;
1079 8 : DATA_BLOB blob;
1080 158 : struct security_token *previous_token = NULL;
1081 158 : struct smbXsrv_session_global0 *global = NULL;
1082 8 : enum ndr_err_code ndr_err;
1083 8 : struct smbXsrv_session_close0 close_info0;
1084 8 : struct smbXsrv_session_closeB close_blob;
1085 158 : struct tevent_req *subreq = NULL;
1086 8 : NTSTATUS status;
1087 158 : bool is_free = false;
1088 158 : uint32_t seqnum = 0;
1089 :
1090 158 : smbXsrv_session_global_verify_record(state->db_rec,
1091 : &is_free,
1092 : NULL,
1093 : state,
1094 : &global,
1095 : &seqnum);
1096 :
1097 158 : if (is_free) {
1098 102 : tevent_req_done(req);
1099 102 : return;
1100 : }
1101 :
1102 56 : if (global->auth_session_info == NULL) {
1103 0 : tevent_req_done(req);
1104 0 : return;
1105 : }
1106 :
1107 56 : previous_token = global->auth_session_info->security_token;
1108 :
1109 56 : if (!security_token_is_sid(previous_token, state->current_sid)) {
1110 0 : tevent_req_done(req);
1111 0 : return;
1112 : }
1113 :
1114 : /*
1115 : * If the record changed, but we are not happy with the change yet,
1116 : * we better remove ourself from the waiter list
1117 : * (most likely the first position)
1118 : * and re-add us at the end of the list.
1119 : *
1120 : * This gives other waiters a change
1121 : * to make progress.
1122 : *
1123 : * Otherwise we'll keep our waiter instance alive,
1124 : * keep waiting (most likely at first position).
1125 : * It means the order of watchers stays fair.
1126 : */
1127 56 : if (state->last_seqnum != seqnum) {
1128 56 : state->last_seqnum = seqnum;
1129 56 : dbwrap_watched_watch_remove_instance(state->db_rec,
1130 : state->watch_instance);
1131 56 : state->watch_instance =
1132 56 : dbwrap_watched_watch_add_instance(state->db_rec);
1133 : }
1134 :
1135 60 : subreq = dbwrap_watched_watch_send(state, state->ev, state->db_rec,
1136 : state->watch_instance,
1137 56 : (struct server_id){0});
1138 56 : if (tevent_req_nomem(subreq, req)) {
1139 0 : return;
1140 : }
1141 56 : tevent_req_set_callback(subreq,
1142 : smb2srv_session_close_previous_modified,
1143 : req);
1144 :
1145 56 : close_info0.old_session_global_id = global->session_global_id;
1146 56 : close_info0.old_session_wire_id = global->session_wire_id;
1147 56 : close_info0.old_creation_time = global->creation_time;
1148 56 : close_info0.new_session_wire_id = state->current_session_id;
1149 :
1150 56 : ZERO_STRUCT(close_blob);
1151 56 : close_blob.version = smbXsrv_version_global_current();
1152 56 : close_blob.info.info0 = &close_info0;
1153 :
1154 56 : ndr_err = ndr_push_struct_blob(&blob, state, &close_blob,
1155 : (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_closeB);
1156 56 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1157 0 : status = ndr_map_error2ntstatus(ndr_err);
1158 0 : DBG_WARNING("old_session[%" PRIu64 "] "
1159 : "new_session[%" PRIu64 "] ndr_push - %s\n",
1160 : close_info0.old_session_wire_id,
1161 : close_info0.new_session_wire_id,
1162 : nt_errstr(status));
1163 0 : tevent_req_nterror(req, status);
1164 0 : return;
1165 : }
1166 :
1167 56 : status = messaging_send(conn->client->msg_ctx,
1168 56 : global->channels[0].server_id,
1169 : MSG_SMBXSRV_SESSION_CLOSE, &blob);
1170 56 : TALLOC_FREE(global);
1171 56 : if (tevent_req_nterror(req, status)) {
1172 0 : return;
1173 : }
1174 :
1175 56 : TALLOC_FREE(state->db_rec);
1176 52 : return;
1177 : }
1178 :
1179 56 : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq)
1180 : {
1181 4 : struct tevent_req *req =
1182 56 : tevent_req_callback_data(subreq,
1183 : struct tevent_req);
1184 4 : struct smb2srv_session_close_previous_state *state =
1185 56 : tevent_req_data(req,
1186 : struct smb2srv_session_close_previous_state);
1187 4 : uint32_t global_id;
1188 4 : NTSTATUS status;
1189 56 : uint64_t instance = 0;
1190 :
1191 56 : status = dbwrap_watched_watch_recv(subreq, &instance, NULL, NULL);
1192 56 : TALLOC_FREE(subreq);
1193 56 : if (tevent_req_nterror(req, status)) {
1194 0 : return;
1195 : }
1196 :
1197 56 : state->watch_instance = instance;
1198 :
1199 56 : global_id = state->previous_session_id & UINT32_MAX;
1200 :
1201 112 : state->db_rec = smbXsrv_session_global_fetch_locked(
1202 56 : state->connection->client->session_table->global.db_ctx,
1203 : global_id, state /* TALLOC_CTX */);
1204 56 : if (state->db_rec == NULL) {
1205 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1206 0 : return;
1207 : }
1208 :
1209 56 : smb2srv_session_close_previous_check(req);
1210 : }
1211 :
1212 102 : NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
1213 : {
1214 4 : NTSTATUS status;
1215 :
1216 102 : if (tevent_req_is_nterror(req, &status)) {
1217 0 : tevent_req_received(req);
1218 0 : return status;
1219 : }
1220 :
1221 102 : tevent_req_received(req);
1222 102 : return NT_STATUS_OK;
1223 : }
1224 :
1225 59842 : static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session)
1226 : {
1227 1499 : NTSTATUS status;
1228 59842 : struct smbXsrv_connection *xconn = NULL;
1229 :
1230 59842 : if (session->client != NULL) {
1231 30844 : xconn = session->client->connections;
1232 : }
1233 :
1234 90738 : for (; xconn != NULL; xconn = xconn->next) {
1235 750 : struct smbd_smb2_request *preq;
1236 :
1237 30952 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1238 56 : if (preq->session != session) {
1239 0 : continue;
1240 : }
1241 :
1242 56 : preq->session = NULL;
1243 : /*
1244 : * If we no longer have a session we can't
1245 : * sign or encrypt replies.
1246 : */
1247 56 : preq->do_signing = false;
1248 56 : preq->do_encryption = false;
1249 56 : preq->preauth = NULL;
1250 : }
1251 : }
1252 :
1253 59842 : status = smbXsrv_session_logoff(session);
1254 59842 : return status;
1255 : }
1256 :
1257 31113 : static int smbXsrv_session_destructor(struct smbXsrv_session *session)
1258 : {
1259 760 : NTSTATUS status;
1260 :
1261 31113 : DBG_DEBUG("destructing session(%" PRIu64 ")\n",
1262 : session->global->session_wire_id);
1263 :
1264 31113 : status = smbXsrv_session_clear_and_logoff(session);
1265 31113 : if (!NT_STATUS_IS_OK(status)) {
1266 0 : DBG_ERR("smbXsrv_session_logoff() failed: %s\n",
1267 : nt_errstr(status));
1268 : }
1269 :
1270 31113 : TALLOC_FREE(session->global);
1271 :
1272 31113 : return 0;
1273 : }
1274 :
1275 31127 : NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
1276 : NTTIME now,
1277 : struct smbXsrv_session **_session)
1278 : {
1279 31127 : struct smbXsrv_session_table *table = conn->client->session_table;
1280 31127 : struct db_record *local_rec = NULL;
1281 31127 : struct smbXsrv_session *session = NULL;
1282 31127 : void *ptr = NULL;
1283 760 : TDB_DATA val;
1284 31127 : struct smbXsrv_session_global0 *global = NULL;
1285 31127 : struct smbXsrv_channel_global0 *channel = NULL;
1286 760 : NTSTATUS status;
1287 :
1288 31127 : if (table->local.num_sessions >= table->local.max_sessions) {
1289 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1290 : }
1291 :
1292 31127 : session = talloc_zero(table, struct smbXsrv_session);
1293 31127 : if (session == NULL) {
1294 0 : return NT_STATUS_NO_MEMORY;
1295 : }
1296 31127 : session->table = table;
1297 31127 : session->idle_time = now;
1298 31127 : session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
1299 31127 : session->client = conn->client;
1300 31127 : session->homes_snum = -1;
1301 :
1302 31127 : status = smbXsrv_session_global_allocate(table->global.db_ctx,
1303 : session,
1304 : &global);
1305 31127 : if (!NT_STATUS_IS_OK(status)) {
1306 0 : TALLOC_FREE(session);
1307 0 : return status;
1308 : }
1309 31127 : session->global = global;
1310 :
1311 31127 : if (conn->protocol >= PROTOCOL_SMB2_02) {
1312 23888 : uint64_t id = global->session_global_id;
1313 :
1314 23888 : global->connection_dialect = conn->smb2.server.dialect;
1315 23888 : global->client_guid = conn->smb2.client.guid;
1316 :
1317 23888 : global->session_wire_id = id;
1318 :
1319 23888 : status = smb2srv_tcon_table_init(session);
1320 23888 : if (!NT_STATUS_IS_OK(status)) {
1321 0 : TALLOC_FREE(session);
1322 0 : return status;
1323 : }
1324 :
1325 23888 : session->local_id = global->session_global_id;
1326 :
1327 23888 : local_rec = smbXsrv_session_local_fetch_locked(
1328 : table->local.db_ctx,
1329 : session->local_id,
1330 : session /* TALLOC_CTX */);
1331 23888 : if (local_rec == NULL) {
1332 0 : TALLOC_FREE(session);
1333 0 : return NT_STATUS_NO_MEMORY;
1334 : }
1335 :
1336 23888 : val = dbwrap_record_get_value(local_rec);
1337 23888 : if (val.dsize != 0) {
1338 0 : TALLOC_FREE(session);
1339 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1340 : }
1341 : } else {
1342 :
1343 7239 : status = smb1srv_session_local_allocate_id(table->local.db_ctx,
1344 : table->local.lowest_id,
1345 : table->local.highest_id,
1346 : session,
1347 : &local_rec,
1348 : &session->local_id);
1349 7239 : if (!NT_STATUS_IS_OK(status)) {
1350 0 : TALLOC_FREE(session);
1351 0 : return status;
1352 : }
1353 :
1354 7239 : global->session_wire_id = session->local_id;
1355 : }
1356 :
1357 31127 : global->creation_time = now;
1358 31127 : global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1359 :
1360 31127 : status = smbXsrv_session_add_channel(session, conn, now, &channel);
1361 31127 : if (!NT_STATUS_IS_OK(status)) {
1362 0 : TALLOC_FREE(session);
1363 0 : return status;
1364 : }
1365 :
1366 31127 : ptr = session;
1367 31127 : val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
1368 31127 : status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
1369 31127 : TALLOC_FREE(local_rec);
1370 31127 : if (!NT_STATUS_IS_OK(status)) {
1371 0 : TALLOC_FREE(session);
1372 0 : return status;
1373 : }
1374 31127 : table->local.num_sessions += 1;
1375 :
1376 31127 : talloc_set_destructor(session, smbXsrv_session_destructor);
1377 :
1378 31127 : status = smbXsrv_session_global_store(global);
1379 31127 : if (!NT_STATUS_IS_OK(status)) {
1380 0 : DBG_ERR("global_id (0x%08x) store failed - %s\n",
1381 : session->global->session_global_id,
1382 : nt_errstr(status));
1383 0 : TALLOC_FREE(session);
1384 0 : return status;
1385 : }
1386 :
1387 31127 : if (DEBUGLVL(DBGLVL_DEBUG)) {
1388 0 : struct smbXsrv_sessionB session_blob = {
1389 : .version = SMBXSRV_VERSION_0,
1390 : .info.info0 = session,
1391 : };
1392 :
1393 0 : DBG_DEBUG("global_id (0x%08x) stored\n",
1394 : session->global->session_global_id);
1395 0 : NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1396 : }
1397 :
1398 31127 : *_session = session;
1399 31127 : return NT_STATUS_OK;
1400 : }
1401 :
1402 32037 : NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
1403 : struct smbXsrv_connection *conn,
1404 : NTTIME now,
1405 : struct smbXsrv_channel_global0 **_c)
1406 : {
1407 32037 : struct smbXsrv_session_global0 *global = session->global;
1408 32037 : struct smbXsrv_channel_global0 *c = NULL;
1409 :
1410 32037 : if (global->num_channels > 31) {
1411 : /*
1412 : * Windows allow up to 32 channels
1413 : */
1414 4 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1415 : }
1416 :
1417 32033 : c = talloc_realloc(global,
1418 : global->channels,
1419 : struct smbXsrv_channel_global0,
1420 : global->num_channels + 1);
1421 32033 : if (c == NULL) {
1422 0 : return NT_STATUS_NO_MEMORY;
1423 : }
1424 32033 : global->channels = c;
1425 :
1426 32033 : c = &global->channels[global->num_channels];
1427 32033 : ZERO_STRUCTP(c);
1428 :
1429 32033 : c->server_id = messaging_server_id(conn->client->msg_ctx);
1430 32033 : c->channel_id = conn->channel_id;
1431 32033 : c->creation_time = now;
1432 64066 : c->local_address = tsocket_address_string(conn->local_address,
1433 32033 : global->channels);
1434 32033 : if (c->local_address == NULL) {
1435 0 : return NT_STATUS_NO_MEMORY;
1436 : }
1437 64066 : c->remote_address = tsocket_address_string(conn->remote_address,
1438 32033 : global->channels);
1439 32033 : if (c->remote_address == NULL) {
1440 0 : return NT_STATUS_NO_MEMORY;
1441 : }
1442 32033 : c->remote_name = talloc_strdup(global->channels,
1443 : conn->remote_hostname);
1444 32033 : if (c->remote_name == NULL) {
1445 0 : return NT_STATUS_NO_MEMORY;
1446 : }
1447 32033 : c->connection = conn;
1448 :
1449 32033 : global->num_channels += 1;
1450 :
1451 32033 : *_c = c;
1452 32033 : return NT_STATUS_OK;
1453 : }
1454 :
1455 127335 : NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session)
1456 : {
1457 127335 : struct smbXsrv_session_table *table = session->table;
1458 2567 : NTSTATUS status;
1459 :
1460 127335 : if (session->global->db_rec != NULL) {
1461 0 : DBG_ERR("smbXsrv_session_update(0x%08x): "
1462 : "Called with db_rec != NULL'\n",
1463 : session->global->session_global_id);
1464 0 : return NT_STATUS_INTERNAL_ERROR;
1465 : }
1466 :
1467 127335 : if (table == NULL) {
1468 0 : DBG_ERR("smbXsrv_session_update(0x%08x): "
1469 : "Called with table == NULL'\n",
1470 : session->global->session_global_id);
1471 0 : return NT_STATUS_INTERNAL_ERROR;
1472 : }
1473 :
1474 252103 : session->global->db_rec = smbXsrv_session_global_fetch_locked(
1475 : table->global.db_ctx,
1476 124768 : session->global->session_global_id,
1477 124768 : session->global /* TALLOC_CTX */);
1478 127335 : if (session->global->db_rec == NULL) {
1479 0 : return NT_STATUS_INTERNAL_DB_ERROR;
1480 : }
1481 :
1482 127335 : status = smbXsrv_session_global_store(session->global);
1483 127335 : if (!NT_STATUS_IS_OK(status)) {
1484 0 : DBG_ERR("global_id (0x%08x) store failed - %s\n",
1485 : session->global->session_global_id,
1486 : nt_errstr(status));
1487 0 : return status;
1488 : }
1489 :
1490 127335 : if (DEBUGLVL(DBGLVL_DEBUG)) {
1491 0 : struct smbXsrv_sessionB session_blob = {
1492 : .version = SMBXSRV_VERSION_0,
1493 : .info.info0 = session,
1494 : };
1495 :
1496 0 : DBG_DEBUG("global_id (0x%08x) stored\n",
1497 : session->global->session_global_id);
1498 0 : NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1499 : }
1500 :
1501 127335 : return NT_STATUS_OK;
1502 : }
1503 :
1504 3546236 : NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
1505 : const struct smbXsrv_connection *conn,
1506 : struct smbXsrv_channel_global0 **_c)
1507 : {
1508 41405 : uint32_t i;
1509 :
1510 3625610 : for (i=0; i < session->global->num_channels; i++) {
1511 3619534 : struct smbXsrv_channel_global0 *c = &session->global->channels[i];
1512 :
1513 3619534 : if (c->channel_id != conn->channel_id) {
1514 79374 : continue;
1515 : }
1516 :
1517 3540160 : if (c->connection != conn) {
1518 0 : continue;
1519 : }
1520 :
1521 3540160 : *_c = c;
1522 3540160 : return NT_STATUS_OK;
1523 : }
1524 :
1525 6076 : return NT_STATUS_USER_SESSION_DELETED;
1526 : }
1527 :
1528 90347 : NTSTATUS smbXsrv_session_find_auth(const struct smbXsrv_session *session,
1529 : const struct smbXsrv_connection *conn,
1530 : NTTIME now,
1531 : struct smbXsrv_session_auth0 **_a)
1532 : {
1533 1980 : struct smbXsrv_session_auth0 *a;
1534 :
1535 90347 : for (a = session->pending_auth; a != NULL; a = a->next) {
1536 24047 : if (a->channel_id != conn->channel_id) {
1537 0 : continue;
1538 : }
1539 :
1540 24047 : if (a->connection == conn) {
1541 24047 : if (now != 0) {
1542 24029 : a->idle_time = now;
1543 : }
1544 24047 : *_a = a;
1545 24047 : return NT_STATUS_OK;
1546 : }
1547 : }
1548 :
1549 66300 : return NT_STATUS_USER_SESSION_DELETED;
1550 : }
1551 :
1552 32152 : static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0 *a)
1553 : {
1554 32152 : if (a->session == NULL) {
1555 14 : return 0;
1556 : }
1557 :
1558 32134 : DLIST_REMOVE(a->session->pending_auth, a);
1559 32134 : a->session = NULL;
1560 32134 : return 0;
1561 : }
1562 :
1563 32146 : NTSTATUS smbXsrv_session_create_auth(struct smbXsrv_session *session,
1564 : struct smbXsrv_connection *conn,
1565 : NTTIME now,
1566 : uint8_t in_flags,
1567 : uint8_t in_security_mode,
1568 : struct smbXsrv_session_auth0 **_a)
1569 : {
1570 811 : struct smbXsrv_session_auth0 *a;
1571 811 : NTSTATUS status;
1572 :
1573 32146 : status = smbXsrv_session_find_auth(session, conn, 0, &a);
1574 32146 : if (NT_STATUS_IS_OK(status)) {
1575 0 : return NT_STATUS_INTERNAL_ERROR;
1576 : }
1577 :
1578 32146 : a = talloc_zero(session, struct smbXsrv_session_auth0);
1579 32146 : if (a == NULL) {
1580 0 : return NT_STATUS_NO_MEMORY;
1581 : }
1582 32146 : a->session = session;
1583 32146 : a->connection = conn;
1584 32146 : a->in_flags = in_flags;
1585 32146 : a->in_security_mode = in_security_mode;
1586 32146 : a->creation_time = now;
1587 32146 : a->idle_time = now;
1588 32146 : a->channel_id = conn->channel_id;
1589 :
1590 32146 : if (conn->protocol >= PROTOCOL_SMB3_11) {
1591 22395 : a->preauth = talloc(a, struct smbXsrv_preauth);
1592 22395 : if (a->preauth == NULL) {
1593 0 : TALLOC_FREE(session);
1594 0 : return NT_STATUS_NO_MEMORY;
1595 : }
1596 22395 : *a->preauth = conn->smb2.preauth;
1597 : }
1598 :
1599 32146 : talloc_set_destructor(a, smbXsrv_session_auth0_destructor);
1600 32146 : DLIST_ADD_END(session->pending_auth, a);
1601 :
1602 32146 : *_a = a;
1603 32146 : return NT_STATUS_OK;
1604 : }
1605 :
1606 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq);
1607 :
1608 2026 : NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session,
1609 : struct smbXsrv_connection *xconn)
1610 : {
1611 2026 : struct smbXsrv_session_auth0 *a = NULL;
1612 2026 : struct smbXsrv_channel_global0 *c = NULL;
1613 210 : NTSTATUS status;
1614 2026 : bool need_update = false;
1615 :
1616 2026 : status = smbXsrv_session_find_auth(session, xconn, 0, &a);
1617 2026 : if (!NT_STATUS_IS_OK(status)) {
1618 2008 : a = NULL;
1619 : }
1620 2026 : status = smbXsrv_session_find_channel(session, xconn, &c);
1621 2026 : if (!NT_STATUS_IS_OK(status)) {
1622 1086 : c = NULL;
1623 : }
1624 :
1625 2026 : if (a != NULL) {
1626 18 : smbXsrv_session_auth0_destructor(a);
1627 18 : a->connection = NULL;
1628 18 : need_update = true;
1629 : }
1630 :
1631 2026 : if (c != NULL) {
1632 940 : struct smbXsrv_session_global0 *global = session->global;
1633 24 : ptrdiff_t n;
1634 :
1635 940 : n = (c - global->channels);
1636 940 : if (n >= global->num_channels || n < 0) {
1637 0 : return NT_STATUS_INTERNAL_ERROR;
1638 : }
1639 940 : ARRAY_DEL_ELEMENT(global->channels, n, global->num_channels);
1640 940 : global->num_channels--;
1641 940 : if (global->num_channels == 0) {
1642 44 : struct smbXsrv_client *client = session->client;
1643 44 : struct tevent_queue *xconn_wait_queue =
1644 : xconn->transport.shutdown_wait_queue;
1645 44 : struct tevent_req *subreq = NULL;
1646 :
1647 : /*
1648 : * Let the connection wait until the session is
1649 : * destroyed.
1650 : *
1651 : * We don't set a callback, as we just want to block the
1652 : * wait queue and the talloc_free() of the session will
1653 : * remove the item from the wait queue in order
1654 : * to remove allow the connection to disappear.
1655 : */
1656 44 : if (xconn_wait_queue != NULL) {
1657 44 : subreq = tevent_queue_wait_send(session,
1658 : client->raw_ev_ctx,
1659 : xconn_wait_queue);
1660 44 : if (subreq == NULL) {
1661 0 : status = NT_STATUS_NO_MEMORY;
1662 0 : DBG_ERR("tevent_queue_wait_send() "
1663 : "session(%" PRIu64
1664 : ") failed: %s\n",
1665 : session->global
1666 : ->session_wire_id,
1667 : nt_errstr(status));
1668 0 : return status;
1669 : }
1670 : }
1671 :
1672 : /*
1673 : * This is guaranteed to set
1674 : * session->status = NT_STATUS_USER_SESSION_DELETED
1675 : * even if NULL is returned.
1676 : */
1677 44 : subreq = smb2srv_session_shutdown_send(session,
1678 : client->raw_ev_ctx,
1679 : session,
1680 : NULL);
1681 44 : if (subreq == NULL) {
1682 0 : status = NT_STATUS_NO_MEMORY;
1683 0 : DBG_ERR("smb2srv_session_shutdown_send("
1684 : "%" PRIu64 " failed: %s\n",
1685 : session->global->session_wire_id,
1686 : nt_errstr(status));
1687 0 : return status;
1688 : }
1689 44 : tevent_req_set_callback(subreq,
1690 : smbXsrv_session_remove_channel_done,
1691 : session);
1692 : }
1693 916 : need_update = true;
1694 : }
1695 :
1696 2002 : if (!need_update) {
1697 1086 : return NT_STATUS_OK;
1698 : }
1699 :
1700 940 : return smbXsrv_session_update(session);
1701 : }
1702 :
1703 44 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq)
1704 : {
1705 4 : struct smbXsrv_session *session =
1706 44 : tevent_req_callback_data(subreq,
1707 : struct smbXsrv_session);
1708 4 : NTSTATUS status;
1709 :
1710 44 : status = smb2srv_session_shutdown_recv(subreq);
1711 44 : TALLOC_FREE(subreq);
1712 44 : if (!NT_STATUS_IS_OK(status)) {
1713 0 : DBG_ERR("smb2srv_session_shutdown_recv(%" PRIu64
1714 : ") failed: %s\n",
1715 : session->global->session_wire_id,
1716 : nt_errstr(status));
1717 : }
1718 :
1719 44 : status = smbXsrv_session_logoff(session);
1720 44 : if (!NT_STATUS_IS_OK(status)) {
1721 0 : DBG_ERR("smbXsrv_session_logoff(%" PRIu64 ") failed: %s\n",
1722 : session->global->session_wire_id,
1723 : nt_errstr(status));
1724 : }
1725 :
1726 44 : TALLOC_FREE(session);
1727 44 : }
1728 :
1729 : struct smb2srv_session_shutdown_state {
1730 : struct tevent_queue *wait_queue;
1731 : };
1732 :
1733 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
1734 :
1735 879 : struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
1736 : struct tevent_context *ev,
1737 : struct smbXsrv_session *session,
1738 : struct smbd_smb2_request *current_req)
1739 : {
1740 21 : struct tevent_req *req;
1741 21 : struct smb2srv_session_shutdown_state *state;
1742 21 : struct tevent_req *subreq;
1743 879 : struct smbXsrv_connection *xconn = NULL;
1744 879 : size_t len = 0;
1745 :
1746 : /*
1747 : * Make sure that no new request will be able to use this session.
1748 : */
1749 879 : session->status = NT_STATUS_USER_SESSION_DELETED;
1750 :
1751 879 : req = tevent_req_create(mem_ctx, &state,
1752 : struct smb2srv_session_shutdown_state);
1753 879 : if (req == NULL) {
1754 0 : return NULL;
1755 : }
1756 :
1757 879 : state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
1758 879 : if (tevent_req_nomem(state->wait_queue, req)) {
1759 0 : return tevent_req_post(req, ev);
1760 : }
1761 :
1762 1848 : for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
1763 33 : struct smbd_smb2_request *preq;
1764 :
1765 1788 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1766 819 : if (preq == current_req) {
1767 : /* Can't cancel current request. */
1768 781 : continue;
1769 : }
1770 38 : if (preq->session != session) {
1771 : /* Request on different session. */
1772 26 : continue;
1773 : }
1774 :
1775 12 : if (preq->subreq != NULL) {
1776 12 : tevent_req_cancel(preq->subreq);
1777 : }
1778 :
1779 : /*
1780 : * Now wait until the request is finished.
1781 : *
1782 : * We don't set a callback, as we just want to block the
1783 : * wait queue and the talloc_free() of the request will
1784 : * remove the item from the wait queue.
1785 : */
1786 12 : subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
1787 12 : if (tevent_req_nomem(subreq, req)) {
1788 0 : return tevent_req_post(req, ev);
1789 : }
1790 : }
1791 : }
1792 :
1793 879 : len = tevent_queue_length(state->wait_queue);
1794 879 : if (len == 0) {
1795 867 : tevent_req_done(req);
1796 867 : return tevent_req_post(req, ev);
1797 : }
1798 :
1799 : /*
1800 : * Now we add our own waiter to the end of the queue,
1801 : * this way we get notified when all pending requests are finished
1802 : * and send to the socket.
1803 : */
1804 12 : subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
1805 12 : if (tevent_req_nomem(subreq, req)) {
1806 0 : return tevent_req_post(req, ev);
1807 : }
1808 12 : tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
1809 :
1810 12 : return req;
1811 : }
1812 :
1813 12 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
1814 : {
1815 0 : struct tevent_req *req =
1816 12 : tevent_req_callback_data(subreq,
1817 : struct tevent_req);
1818 :
1819 12 : tevent_queue_wait_recv(subreq);
1820 12 : TALLOC_FREE(subreq);
1821 :
1822 12 : tevent_req_done(req);
1823 12 : }
1824 :
1825 879 : NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
1826 : {
1827 879 : return tevent_req_simple_recv_ntstatus(req);
1828 : }
1829 :
1830 60111 : NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
1831 : {
1832 1513 : struct smbXsrv_session_table *table;
1833 60111 : struct db_record *local_rec = NULL;
1834 60111 : struct db_record *global_rec = NULL;
1835 60111 : struct smbd_server_connection *sconn = NULL;
1836 1513 : NTSTATUS status;
1837 60111 : NTSTATUS error = NT_STATUS_OK;
1838 :
1839 60111 : if (session->table == NULL) {
1840 28998 : return NT_STATUS_OK;
1841 : }
1842 :
1843 31113 : table = session->table;
1844 31113 : session->table = NULL;
1845 :
1846 31113 : sconn = session->client->sconn;
1847 31113 : session->client = NULL;
1848 31113 : session->status = NT_STATUS_USER_SESSION_DELETED;
1849 :
1850 : /*
1851 : * For SMB2 this is a bit redundant as files are also close
1852 : * below via smb2srv_tcon_disconnect_all() -> ... ->
1853 : * smbXsrv_tcon_disconnect() -> close_cnum() ->
1854 : * file_close_conn().
1855 : */
1856 31113 : file_close_user(sconn, session->global->session_wire_id);
1857 :
1858 31113 : if (session->tcon_table != NULL) {
1859 : /*
1860 : * Note: We only have a tcon_table for SMB2.
1861 : */
1862 23886 : status = smb2srv_tcon_disconnect_all(session);
1863 23886 : if (!NT_STATUS_IS_OK(status)) {
1864 52 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1865 : "smb2srv_tcon_disconnect_all() failed: %s\n",
1866 : session->global->session_global_id,
1867 : nt_errstr(status));
1868 52 : error = status;
1869 : }
1870 : }
1871 :
1872 31113 : invalidate_vuid(sconn, session->global->session_wire_id);
1873 :
1874 31113 : global_rec = session->global->db_rec;
1875 31113 : session->global->db_rec = NULL;
1876 31113 : if (global_rec == NULL) {
1877 31113 : global_rec = smbXsrv_session_global_fetch_locked(
1878 : table->global.db_ctx,
1879 30353 : session->global->session_global_id,
1880 30353 : session->global /* TALLOC_CTX */);
1881 31113 : if (global_rec == NULL) {
1882 0 : error = NT_STATUS_INTERNAL_ERROR;
1883 : }
1884 : }
1885 :
1886 31113 : if (global_rec != NULL) {
1887 31113 : status = dbwrap_record_delete(global_rec);
1888 31113 : if (!NT_STATUS_IS_OK(status)) {
1889 0 : TDB_DATA key = dbwrap_record_get_key(global_rec);
1890 :
1891 0 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1892 : "failed to delete global key '%s': %s\n",
1893 : session->global->session_global_id,
1894 : tdb_data_dbg(key),
1895 : nt_errstr(status));
1896 0 : error = status;
1897 : }
1898 : }
1899 31113 : TALLOC_FREE(global_rec);
1900 :
1901 31113 : local_rec = session->db_rec;
1902 31113 : if (local_rec == NULL) {
1903 2384 : local_rec = smbXsrv_session_local_fetch_locked(
1904 : table->local.db_ctx,
1905 : session->local_id,
1906 : session /* TALLOC_CTX */);
1907 2384 : if (local_rec == NULL) {
1908 0 : error = NT_STATUS_INTERNAL_ERROR;
1909 : }
1910 : }
1911 :
1912 31113 : if (local_rec != NULL) {
1913 31113 : status = dbwrap_record_delete(local_rec);
1914 31113 : if (!NT_STATUS_IS_OK(status)) {
1915 0 : TDB_DATA key = dbwrap_record_get_key(local_rec);
1916 :
1917 0 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1918 : "failed to delete local key '%s': %s\n",
1919 : session->global->session_global_id,
1920 : tdb_data_dbg(key),
1921 : nt_errstr(status));
1922 0 : error = status;
1923 : }
1924 31113 : table->local.num_sessions -= 1;
1925 : }
1926 31113 : if (session->db_rec == NULL) {
1927 2384 : TALLOC_FREE(local_rec);
1928 : }
1929 31113 : session->db_rec = NULL;
1930 :
1931 31113 : return error;
1932 : }
1933 :
1934 : struct smbXsrv_session_logoff_all_state {
1935 : NTSTATUS first_status;
1936 : int errors;
1937 : };
1938 :
1939 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1940 : void *private_data);
1941 :
1942 31375 : NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_client *client)
1943 : {
1944 31375 : struct smbXsrv_session_table *table = client->session_table;
1945 842 : struct smbXsrv_session_logoff_all_state state;
1946 842 : NTSTATUS status;
1947 31375 : int count = 0;
1948 :
1949 31375 : if (table == NULL) {
1950 707 : DBG_DEBUG("empty session_table, nothing to do.\n");
1951 707 : return NT_STATUS_OK;
1952 : }
1953 :
1954 30668 : ZERO_STRUCT(state);
1955 :
1956 30668 : status = dbwrap_traverse(table->local.db_ctx,
1957 : smbXsrv_session_logoff_all_callback,
1958 : &state, &count);
1959 30668 : if (!NT_STATUS_IS_OK(status)) {
1960 0 : DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
1961 0 : return status;
1962 : }
1963 :
1964 30668 : if (!NT_STATUS_IS_OK(state.first_status)) {
1965 50 : DBG_ERR("count[%d] errors[%d] first[%s]\n",
1966 : count,
1967 : state.errors,
1968 : nt_errstr(state.first_status));
1969 50 : return state.first_status;
1970 : }
1971 :
1972 30618 : return NT_STATUS_OK;
1973 : }
1974 :
1975 28729 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1976 : void *private_data)
1977 : {
1978 28729 : struct smbXsrv_session_logoff_all_state *state =
1979 : (struct smbXsrv_session_logoff_all_state *)private_data;
1980 739 : TDB_DATA val;
1981 28729 : void *ptr = NULL;
1982 28729 : struct smbXsrv_session *session = NULL;
1983 739 : NTSTATUS status;
1984 :
1985 28729 : val = dbwrap_record_get_value(local_rec);
1986 28729 : if (val.dsize != sizeof(ptr)) {
1987 0 : status = NT_STATUS_INTERNAL_ERROR;
1988 0 : if (NT_STATUS_IS_OK(state->first_status)) {
1989 0 : state->first_status = status;
1990 : }
1991 0 : state->errors++;
1992 0 : return 0;
1993 : }
1994 :
1995 28729 : memcpy(&ptr, val.dptr, val.dsize);
1996 28729 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
1997 :
1998 28729 : session->db_rec = local_rec;
1999 28729 : status = smbXsrv_session_clear_and_logoff(session);
2000 28729 : session->db_rec = NULL;
2001 28729 : if (!NT_STATUS_IS_OK(status)) {
2002 52 : if (NT_STATUS_IS_OK(state->first_status)) {
2003 50 : state->first_status = status;
2004 : }
2005 52 : state->errors++;
2006 52 : return 0;
2007 : }
2008 :
2009 27938 : return 0;
2010 : }
2011 :
2012 : struct smbXsrv_session_local_trav_state {
2013 : NTSTATUS status;
2014 : int (*caller_cb)(struct smbXsrv_session *session,
2015 : void *caller_data);
2016 : void *caller_data;
2017 : };
2018 :
2019 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
2020 : void *private_data);
2021 :
2022 0 : NTSTATUS smbXsrv_session_local_traverse(
2023 : struct smbXsrv_client *client,
2024 : int (*caller_cb)(struct smbXsrv_session *session,
2025 : void *caller_data),
2026 : void *caller_data)
2027 : {
2028 0 : struct smbXsrv_session_table *table = client->session_table;
2029 0 : struct smbXsrv_session_local_trav_state state;
2030 0 : NTSTATUS status;
2031 0 : int count = 0;
2032 :
2033 0 : state = (struct smbXsrv_session_local_trav_state) {
2034 : .status = NT_STATUS_OK,
2035 : .caller_cb = caller_cb,
2036 : .caller_data = caller_data,
2037 : };
2038 :
2039 0 : if (table == NULL) {
2040 0 : DBG_DEBUG("empty session_table, nothing to do.\n");
2041 0 : return NT_STATUS_OK;
2042 : }
2043 :
2044 0 : status = dbwrap_traverse(table->local.db_ctx,
2045 : smbXsrv_session_local_traverse_cb,
2046 : &state,
2047 : &count);
2048 0 : if (!NT_STATUS_IS_OK(status)) {
2049 0 : DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
2050 0 : return status;
2051 : }
2052 0 : if (!NT_STATUS_IS_OK(state.status)) {
2053 0 : DBG_ERR("count[%d] status[%s]\n",
2054 : count, nt_errstr(state.status));
2055 0 : return state.status;
2056 : }
2057 :
2058 0 : return NT_STATUS_OK;
2059 : }
2060 :
2061 0 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
2062 : void *private_data)
2063 : {
2064 0 : struct smbXsrv_session_local_trav_state *state =
2065 : (struct smbXsrv_session_local_trav_state *)private_data;
2066 0 : TDB_DATA val;
2067 0 : void *ptr = NULL;
2068 0 : struct smbXsrv_session *session = NULL;
2069 0 : int ret;
2070 :
2071 0 : val = dbwrap_record_get_value(local_rec);
2072 0 : if (val.dsize != sizeof(ptr)) {
2073 0 : state->status = NT_STATUS_INTERNAL_ERROR;
2074 0 : return -1;
2075 : }
2076 :
2077 0 : memcpy(&ptr, val.dptr, val.dsize);
2078 0 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2079 :
2080 0 : session->db_rec = local_rec;
2081 0 : ret = state->caller_cb(session, state->caller_data);
2082 0 : session->db_rec = NULL;
2083 :
2084 0 : return ret;
2085 : }
2086 :
2087 : struct smbXsrv_session_disconnect_xconn_state {
2088 : struct smbXsrv_connection *xconn;
2089 : NTSTATUS first_status;
2090 : int errors;
2091 : };
2092 :
2093 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
2094 : void *private_data);
2095 :
2096 1106 : NTSTATUS smbXsrv_session_disconnect_xconn(struct smbXsrv_connection *xconn)
2097 : {
2098 1106 : struct smbXsrv_client *client = xconn->client;
2099 1106 : struct smbXsrv_session_table *table = client->session_table;
2100 52 : struct smbXsrv_session_disconnect_xconn_state state;
2101 52 : NTSTATUS status;
2102 1106 : int count = 0;
2103 :
2104 1106 : if (table == NULL) {
2105 0 : DBG_ERR("empty session_table, nothing to do.\n");
2106 0 : return NT_STATUS_OK;
2107 : }
2108 :
2109 1106 : ZERO_STRUCT(state);
2110 1106 : state.xconn = xconn;
2111 :
2112 1106 : status = dbwrap_traverse(table->local.db_ctx,
2113 : smbXsrv_session_disconnect_xconn_callback,
2114 : &state, &count);
2115 1106 : if (!NT_STATUS_IS_OK(status)) {
2116 0 : DBG_ERR("dbwrap_traverse() failed: %s\n",
2117 : nt_errstr(status));
2118 0 : return status;
2119 : }
2120 :
2121 1106 : if (!NT_STATUS_IS_OK(state.first_status)) {
2122 0 : DBG_ERR("count[%d] errors[%d] first[%s]\n",
2123 : count, state.errors,
2124 : nt_errstr(state.first_status));
2125 0 : return state.first_status;
2126 : }
2127 :
2128 1106 : return NT_STATUS_OK;
2129 : }
2130 :
2131 1184 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
2132 : void *private_data)
2133 : {
2134 1184 : struct smbXsrv_session_disconnect_xconn_state *state =
2135 : (struct smbXsrv_session_disconnect_xconn_state *)private_data;
2136 62 : TDB_DATA val;
2137 1184 : void *ptr = NULL;
2138 1184 : struct smbXsrv_session *session = NULL;
2139 62 : NTSTATUS status;
2140 :
2141 1184 : val = dbwrap_record_get_value(local_rec);
2142 1184 : if (val.dsize != sizeof(ptr)) {
2143 0 : status = NT_STATUS_INTERNAL_ERROR;
2144 0 : if (NT_STATUS_IS_OK(state->first_status)) {
2145 0 : state->first_status = status;
2146 : }
2147 0 : state->errors++;
2148 0 : return 0;
2149 : }
2150 :
2151 1184 : memcpy(&ptr, val.dptr, val.dsize);
2152 1184 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2153 :
2154 1184 : session->db_rec = local_rec;
2155 1184 : status = smbXsrv_session_remove_channel(session, state->xconn);
2156 1184 : session->db_rec = NULL;
2157 1184 : if (!NT_STATUS_IS_OK(status)) {
2158 0 : if (NT_STATUS_IS_OK(state->first_status)) {
2159 0 : state->first_status = status;
2160 : }
2161 0 : state->errors++;
2162 : }
2163 :
2164 1122 : return 0;
2165 : }
2166 :
2167 5775 : NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn)
2168 : {
2169 : /*
2170 : * Allow a range from 1..65534 with 65534 values.
2171 : */
2172 5775 : return smbXsrv_session_table_init(conn, 1, UINT16_MAX - 1,
2173 : UINT16_MAX - 1);
2174 : }
2175 :
2176 675530 : NTSTATUS smb1srv_session_lookup(struct smbXsrv_connection *conn,
2177 : uint16_t vuid, NTTIME now,
2178 : struct smbXsrv_session **session)
2179 : {
2180 675530 : struct smbXsrv_session_table *table = conn->client->session_table;
2181 675530 : uint32_t local_id = vuid;
2182 :
2183 675530 : return smbXsrv_session_local_lookup(table, conn, local_id, now,
2184 : session);
2185 : }
2186 :
2187 1844995 : NTSTATUS smbXsrv_session_info_lookup(struct smbXsrv_client *client,
2188 : uint64_t session_wire_id,
2189 : struct auth_session_info **si)
2190 : {
2191 1844995 : struct smbXsrv_session_table *table = client->session_table;
2192 17911 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2193 1844995 : struct smbXsrv_session_local_fetch_state state = {
2194 : .session = NULL,
2195 : .status = NT_STATUS_INTERNAL_ERROR,
2196 : };
2197 17911 : TDB_DATA key;
2198 17911 : NTSTATUS status;
2199 :
2200 1844995 : if (session_wire_id == 0) {
2201 0 : return NT_STATUS_USER_SESSION_DELETED;
2202 : }
2203 :
2204 1844995 : if (table == NULL) {
2205 : /* this might happen before the end of negprot */
2206 0 : return NT_STATUS_USER_SESSION_DELETED;
2207 : }
2208 :
2209 1844995 : if (table->local.db_ctx == NULL) {
2210 0 : return NT_STATUS_INTERNAL_ERROR;
2211 : }
2212 :
2213 1844995 : key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2214 :
2215 1844995 : status = dbwrap_parse_record(table->local.db_ctx, key,
2216 : smbXsrv_session_local_fetch_parser,
2217 : &state);
2218 1844995 : if (!NT_STATUS_IS_OK(status)) {
2219 17 : return status;
2220 : }
2221 1844978 : if (!NT_STATUS_IS_OK(state.status)) {
2222 0 : return state.status;
2223 : }
2224 1844978 : if (state.session->global->auth_session_info == NULL) {
2225 0 : return NT_STATUS_USER_SESSION_DELETED;
2226 : }
2227 :
2228 1844978 : *si = state.session->global->auth_session_info;
2229 1844978 : return NT_STATUS_OK;
2230 : }
2231 :
2232 : /*
2233 : * In memory of get_valid_user_struct()
2234 : *
2235 : * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
2236 : * but it doesn't implement the state checks of
2237 : * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
2238 : * session wire-id of incoming SMB requests, it MUST only be used in later
2239 : * internal processing where the session wire-id has already been validated.
2240 : */
2241 31426 : NTSTATUS get_valid_smbXsrv_session(struct smbXsrv_client *client,
2242 : uint64_t session_wire_id,
2243 : struct smbXsrv_session **session)
2244 : {
2245 31426 : struct smbXsrv_session_table *table = client->session_table;
2246 760 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2247 31426 : struct smbXsrv_session_local_fetch_state state = {
2248 : .session = NULL,
2249 : .status = NT_STATUS_INTERNAL_ERROR,
2250 : };
2251 760 : TDB_DATA key;
2252 760 : NTSTATUS status;
2253 :
2254 31426 : if (session_wire_id == 0) {
2255 0 : return NT_STATUS_USER_SESSION_DELETED;
2256 : }
2257 :
2258 31426 : if (table == NULL) {
2259 : /* this might happen before the end of negprot */
2260 0 : return NT_STATUS_USER_SESSION_DELETED;
2261 : }
2262 :
2263 31426 : if (table->local.db_ctx == NULL) {
2264 0 : return NT_STATUS_INTERNAL_ERROR;
2265 : }
2266 :
2267 31426 : key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2268 :
2269 31426 : status = dbwrap_parse_record(table->local.db_ctx, key,
2270 : smbXsrv_session_local_fetch_parser,
2271 : &state);
2272 31426 : if (!NT_STATUS_IS_OK(status)) {
2273 0 : return status;
2274 : }
2275 31426 : if (!NT_STATUS_IS_OK(state.status)) {
2276 0 : return state.status;
2277 : }
2278 31426 : if (state.session->global->auth_session_info == NULL) {
2279 2085 : return NT_STATUS_USER_SESSION_DELETED;
2280 : }
2281 :
2282 29341 : *session = state.session;
2283 29341 : return NT_STATUS_OK;
2284 : }
2285 :
2286 25055 : NTSTATUS smb2srv_session_lookup_global(struct smbXsrv_client *client,
2287 : uint64_t session_wire_id,
2288 : TALLOC_CTX *mem_ctx,
2289 : struct smbXsrv_session **_session)
2290 : {
2291 25055 : TALLOC_CTX *frame = talloc_stackframe();
2292 25055 : struct smbXsrv_session_table *table = client->session_table;
2293 25055 : uint32_t global_id = session_wire_id & UINT32_MAX;
2294 25055 : uint64_t global_zeros = session_wire_id & 0xFFFFFFFF00000000LLU;
2295 25055 : struct smbXsrv_session *session = NULL;
2296 25055 : struct db_record *global_rec = NULL;
2297 25055 : bool is_free = false;
2298 832 : NTSTATUS status;
2299 :
2300 25055 : if (global_id == 0) {
2301 23888 : TALLOC_FREE(frame);
2302 23888 : return NT_STATUS_USER_SESSION_DELETED;
2303 : }
2304 1167 : if (global_zeros != 0) {
2305 0 : TALLOC_FREE(frame);
2306 0 : return NT_STATUS_USER_SESSION_DELETED;
2307 : }
2308 :
2309 1167 : if (table == NULL) {
2310 : /* this might happen before the end of negprot */
2311 0 : TALLOC_FREE(frame);
2312 0 : return NT_STATUS_USER_SESSION_DELETED;
2313 : }
2314 :
2315 1167 : if (table->global.db_ctx == NULL) {
2316 0 : TALLOC_FREE(frame);
2317 0 : return NT_STATUS_INTERNAL_ERROR;
2318 : }
2319 :
2320 1167 : session = talloc_zero(mem_ctx, struct smbXsrv_session);
2321 1167 : if (session == NULL) {
2322 0 : TALLOC_FREE(frame);
2323 0 : return NT_STATUS_NO_MEMORY;
2324 : }
2325 1167 : talloc_steal(frame, session);
2326 :
2327 1167 : session->client = client;
2328 1167 : session->status = NT_STATUS_BAD_LOGON_SESSION_STATE;
2329 1167 : session->local_id = global_id;
2330 :
2331 : /*
2332 : * This means smb2_get_new_nonce() will return
2333 : * NT_STATUS_ENCRYPTION_FAILED.
2334 : *
2335 : * But we initialize some random parts just in case...
2336 : */
2337 1167 : session->nonce_high_max = session->nonce_high = 0;
2338 1167 : generate_nonce_buffer((uint8_t *)&session->nonce_high_random,
2339 : sizeof(session->nonce_high_random));
2340 1167 : generate_nonce_buffer((uint8_t *)&session->nonce_low,
2341 : sizeof(session->nonce_low));
2342 :
2343 1167 : global_rec = smbXsrv_session_global_fetch_locked(table->global.db_ctx,
2344 : global_id,
2345 : frame);
2346 1167 : if (global_rec == NULL) {
2347 0 : TALLOC_FREE(frame);
2348 0 : return NT_STATUS_INTERNAL_DB_ERROR;
2349 : }
2350 :
2351 1167 : smbXsrv_session_global_verify_record(global_rec,
2352 : &is_free,
2353 : NULL,
2354 : session,
2355 1167 : &session->global,
2356 : NULL);
2357 1167 : if (is_free) {
2358 10 : TALLOC_FREE(frame);
2359 10 : return NT_STATUS_USER_SESSION_DELETED;
2360 : }
2361 :
2362 : /*
2363 : * We don't have channels on this session
2364 : * and only the main signing key
2365 : */
2366 1157 : session->global->num_channels = 0;
2367 1362 : status = smb2_signing_key_sign_create(session->global,
2368 1157 : session->global->signing_algo,
2369 : NULL, /* no master key */
2370 : NULL, /* derivations */
2371 952 : &session->global->signing_key);
2372 1157 : if (!NT_STATUS_IS_OK(status)) {
2373 0 : TALLOC_FREE(frame);
2374 0 : return NT_STATUS_NO_MEMORY;
2375 : }
2376 1157 : session->global->signing_key->blob = session->global->signing_key_blob;
2377 1157 : session->global->signing_flags = 0;
2378 :
2379 1362 : status = smb2_signing_key_cipher_create(session->global,
2380 1157 : session->global->encryption_cipher,
2381 : NULL, /* no master key */
2382 : NULL, /* derivations */
2383 952 : &session->global->decryption_key);
2384 1157 : if (!NT_STATUS_IS_OK(status)) {
2385 0 : TALLOC_FREE(frame);
2386 0 : return NT_STATUS_NO_MEMORY;
2387 : }
2388 1157 : session->global->decryption_key->blob = session->global->decryption_key_blob;
2389 1157 : session->global->encryption_flags = 0;
2390 :
2391 1157 : *_session = talloc_move(mem_ctx, &session);
2392 1157 : TALLOC_FREE(frame);
2393 1157 : return NT_STATUS_OK;
2394 : }
2395 :
2396 24907 : NTSTATUS smb2srv_session_table_init(struct smbXsrv_connection *conn)
2397 : {
2398 : /*
2399 : * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
2400 : */
2401 24907 : return smbXsrv_session_table_init(conn, 1, UINT32_MAX - 1,
2402 : UINT16_MAX - 1);
2403 : }
2404 :
2405 1488242 : static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
2406 : /* conn: optional */
2407 : struct smbXsrv_connection *conn,
2408 : uint64_t session_id, NTTIME now,
2409 : struct smbXsrv_session **session)
2410 : {
2411 1488242 : uint32_t local_id = session_id & UINT32_MAX;
2412 1488242 : uint64_t local_zeros = session_id & 0xFFFFFFFF00000000LLU;
2413 :
2414 1488242 : if (local_zeros != 0) {
2415 24 : return NT_STATUS_USER_SESSION_DELETED;
2416 : }
2417 :
2418 1488218 : return smbXsrv_session_local_lookup(table, conn, local_id, now,
2419 : session);
2420 : }
2421 :
2422 1443927 : NTSTATUS smb2srv_session_lookup_conn(struct smbXsrv_connection *conn,
2423 : uint64_t session_id, NTTIME now,
2424 : struct smbXsrv_session **session)
2425 : {
2426 1443927 : struct smbXsrv_session_table *table = conn->client->session_table;
2427 1443927 : return smb2srv_session_lookup_raw(table, conn, session_id, now,
2428 : session);
2429 : }
2430 :
2431 44315 : NTSTATUS smb2srv_session_lookup_client(struct smbXsrv_client *client,
2432 : uint64_t session_id, NTTIME now,
2433 : struct smbXsrv_session **session)
2434 : {
2435 44315 : struct smbXsrv_session_table *table = client->session_table;
2436 44315 : return smb2srv_session_lookup_raw(table, NULL, session_id, now,
2437 : session);
2438 : }
2439 :
2440 : struct smbXsrv_session_global_traverse_state {
2441 : int (*fn)(struct smbXsrv_session_global0 *, void *);
2442 : void *private_data;
2443 : };
2444 :
2445 46 : static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
2446 : {
2447 46 : int ret = -1;
2448 46 : struct smbXsrv_session_global_traverse_state *state =
2449 : (struct smbXsrv_session_global_traverse_state*)data;
2450 46 : TDB_DATA key = dbwrap_record_get_key(rec);
2451 46 : TDB_DATA val = dbwrap_record_get_value(rec);
2452 46 : DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
2453 0 : struct smbXsrv_session_globalB global_blob;
2454 0 : enum ndr_err_code ndr_err;
2455 46 : TALLOC_CTX *frame = talloc_stackframe();
2456 :
2457 46 : ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
2458 : (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
2459 46 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2460 0 : DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2461 : "key '%s' ndr_pull_struct_blob - %s\n",
2462 : tdb_data_dbg(key),
2463 : ndr_errstr(ndr_err));
2464 0 : goto done;
2465 : }
2466 :
2467 46 : if (global_blob.version != SMBXSRV_VERSION_0) {
2468 0 : DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2469 : "key '%s' unsupported version - %d\n",
2470 : tdb_data_dbg(key),
2471 : (int)global_blob.version);
2472 0 : goto done;
2473 : }
2474 :
2475 46 : if (global_blob.info.info0 == NULL) {
2476 0 : DBG_WARNING("Invalid record in smbXsrv_tcon_global.tdb:"
2477 : "key '%s' info0 NULL pointer\n",
2478 : tdb_data_dbg(key));
2479 0 : goto done;
2480 : }
2481 :
2482 46 : global_blob.info.info0->db_rec = rec;
2483 46 : ret = state->fn(global_blob.info.info0, state->private_data);
2484 46 : done:
2485 46 : TALLOC_FREE(frame);
2486 46 : return ret;
2487 : }
2488 :
2489 42 : NTSTATUS smbXsrv_session_global_traverse(
2490 : int (*fn)(struct smbXsrv_session_global0 *, void *),
2491 : void *private_data)
2492 : {
2493 :
2494 0 : NTSTATUS status;
2495 42 : int count = 0;
2496 42 : struct smbXsrv_session_global_traverse_state state = {
2497 : .fn = fn,
2498 : .private_data = private_data,
2499 : };
2500 :
2501 42 : become_root();
2502 42 : status = smbXsrv_session_global_init(NULL);
2503 42 : if (!NT_STATUS_IS_OK(status)) {
2504 0 : unbecome_root();
2505 0 : DBG_ERR("Failed to initialize session_global: %s\n",
2506 : nt_errstr(status));
2507 0 : return status;
2508 : }
2509 :
2510 42 : status = dbwrap_traverse_read(smbXsrv_session_global_db_ctx,
2511 : smbXsrv_session_global_traverse_fn,
2512 : &state,
2513 : &count);
2514 42 : unbecome_root();
2515 :
2516 42 : return status;
2517 : }
|