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 31259 : NTSTATUS smbXsrv_session_global_init(struct messaging_context *msg_ctx)
61 : {
62 31259 : char *global_path = NULL;
63 31259 : struct db_context *backend = NULL;
64 31259 : struct db_context *db_ctx = NULL;
65 :
66 31259 : if (smbXsrv_session_global_db_ctx != NULL) {
67 31237 : 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 200013 : static TDB_DATA smbXsrv_session_global_id_to_key(uint32_t id,
116 : uint8_t *key_buf)
117 : {
118 4450 : TDB_DATA key;
119 :
120 200013 : RSIVAL(key_buf, 0, id);
121 :
122 200013 : key = make_tdb_data(key_buf, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE);
123 :
124 200013 : 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 4009065 : static TDB_DATA smbXsrv_session_local_id_to_key(uint32_t id,
147 : uint8_t *key_buf)
148 : {
149 37446 : TDB_DATA key;
150 :
151 4009065 : RSIVAL(key_buf, 0, id);
152 :
153 4009065 : key = make_tdb_data(key_buf, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE);
154 :
155 4009065 : 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 200013 : 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 4450 : TDB_DATA key;
179 4450 : uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE];
180 200013 : struct db_record *rec = NULL;
181 :
182 200013 : key = smbXsrv_session_global_id_to_key(id, key_buf);
183 :
184 200013 : rec = dbwrap_fetch_locked(db, mem_ctx, key);
185 :
186 200013 : 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 200013 : return rec;
192 : }
193 :
194 35984 : 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 805 : TDB_DATA key;
200 805 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
201 35984 : struct db_record *rec = NULL;
202 :
203 35984 : key = smbXsrv_session_local_id_to_key(id, key_buf);
204 :
205 35984 : rec = dbwrap_fetch_locked(db, mem_ctx, key);
206 :
207 35984 : 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 35984 : return rec;
213 : }
214 :
215 : static void smbXsrv_session_close_loop(struct tevent_req *subreq);
216 :
217 31217 : 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 31217 : struct smbXsrv_client *client = conn->client;
223 854 : struct smbXsrv_session_table *table;
224 854 : NTSTATUS status;
225 854 : struct tevent_req *subreq;
226 854 : uint64_t max_range;
227 :
228 31217 : if (lowest_id > highest_id) {
229 0 : return NT_STATUS_INTERNAL_ERROR;
230 : }
231 :
232 31217 : max_range = highest_id;
233 31217 : max_range -= lowest_id;
234 31217 : max_range += 1;
235 :
236 31217 : if (max_sessions > max_range) {
237 0 : return NT_STATUS_INTERNAL_ERROR;
238 : }
239 :
240 31217 : table = talloc_zero(client, struct smbXsrv_session_table);
241 31217 : if (table == NULL) {
242 0 : return NT_STATUS_NO_MEMORY;
243 : }
244 :
245 31217 : table->local.db_ctx = db_open_rbt(table);
246 31217 : if (table->local.db_ctx == NULL) {
247 0 : TALLOC_FREE(table);
248 0 : return NT_STATUS_NO_MEMORY;
249 : }
250 31217 : table->local.lowest_id = lowest_id;
251 31217 : table->local.highest_id = highest_id;
252 31217 : table->local.max_sessions = max_sessions;
253 :
254 31217 : status = smbXsrv_session_global_init(client->msg_ctx);
255 31217 : if (!NT_STATUS_IS_OK(status)) {
256 0 : TALLOC_FREE(table);
257 0 : return status;
258 : }
259 :
260 31217 : table->global.db_ctx = smbXsrv_session_global_db_ctx;
261 :
262 31217 : subreq = messaging_read_send(table,
263 : client->raw_ev_ctx,
264 : client->msg_ctx,
265 : MSG_SMBXSRV_SESSION_CLOSE);
266 31217 : if (subreq == NULL) {
267 0 : TALLOC_FREE(table);
268 0 : return NT_STATUS_NO_MEMORY;
269 : }
270 31217 : tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
271 :
272 31217 : client->session_table = table;
273 31217 : 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 7076 : 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 7076 : 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 7076 : int count = 0;
497 :
498 7076 : *_rec = NULL;
499 7076 : *_id = 0;
500 :
501 7076 : if (lowest_id > highest_id) {
502 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
503 : }
504 :
505 : /*
506 : * first we try randomly
507 : */
508 7076 : range = (highest_id - lowest_id) + 1;
509 :
510 7076 : for (i = 0; i < (range / 2); i++) {
511 133 : uint32_t id;
512 133 : TDB_DATA val;
513 7076 : struct db_record *rec = NULL;
514 :
515 7076 : id = generate_random() % range;
516 7076 : id += lowest_id;
517 :
518 7076 : if (id < lowest_id) {
519 0 : id = lowest_id;
520 : }
521 7076 : if (id > highest_id) {
522 0 : id = highest_id;
523 : }
524 :
525 7076 : rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
526 7076 : if (rec == NULL) {
527 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
528 : }
529 :
530 7076 : val = dbwrap_record_get_value(rec);
531 7076 : if (val.dsize != 0) {
532 0 : TALLOC_FREE(rec);
533 0 : continue;
534 : }
535 :
536 7076 : *_rec = rec;
537 7076 : *_id = id;
538 7076 : 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 3972007 : static void smbXsrv_session_local_fetch_parser(TDB_DATA key, TDB_DATA data,
605 : void *private_data)
606 : {
607 3972007 : struct smbXsrv_session_local_fetch_state *state =
608 : (struct smbXsrv_session_local_fetch_state *)private_data;
609 36475 : void *ptr;
610 :
611 3972007 : if (data.dsize != sizeof(ptr)) {
612 0 : state->status = NT_STATUS_INTERNAL_DB_ERROR;
613 0 : return;
614 : }
615 :
616 3972007 : memcpy(&ptr, data.dptr, data.dsize);
617 3972007 : state->session = talloc_get_type_abort(ptr, struct smbXsrv_session);
618 3972007 : state->status = NT_STATUS_OK;
619 : }
620 :
621 2173238 : 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 2173238 : struct smbXsrv_session_local_fetch_state state = {
629 : .session = NULL,
630 : .status = NT_STATUS_INTERNAL_ERROR,
631 : };
632 20809 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
633 20809 : TDB_DATA key;
634 20809 : NTSTATUS status;
635 :
636 2173238 : *_session = NULL;
637 :
638 2173238 : if (session_local_id == 0) {
639 83719 : return NT_STATUS_USER_SESSION_DELETED;
640 : }
641 :
642 2089519 : if (table == NULL) {
643 : /* this might happen before the end of negprot */
644 0 : return NT_STATUS_USER_SESSION_DELETED;
645 : }
646 :
647 2089519 : if (table->local.db_ctx == NULL) {
648 0 : return NT_STATUS_INTERNAL_ERROR;
649 : }
650 :
651 2089519 : key = smbXsrv_session_local_id_to_key(session_local_id, key_buf);
652 :
653 2089519 : status = dbwrap_parse_record(table->local.db_ctx, key,
654 : smbXsrv_session_local_fetch_parser,
655 : &state);
656 2089519 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
657 1057 : return NT_STATUS_USER_SESSION_DELETED;
658 2088462 : } else if (!NT_STATUS_IS_OK(status)) {
659 0 : return status;
660 : }
661 2088462 : if (!NT_STATUS_IS_OK(state.status)) {
662 0 : return state.status;
663 : }
664 :
665 2088462 : 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 2088462 : if (conn != NULL) {
674 2067137 : struct smbXsrv_channel_global0 *c = NULL;
675 :
676 2067137 : status = smbXsrv_session_find_channel(state.session, conn, &c);
677 2067137 : if (!NT_STATUS_IS_OK(status)) {
678 140 : return status;
679 : }
680 : }
681 :
682 2088322 : state.session->idle_time = now;
683 :
684 2088322 : if (!NT_STATUS_IS_OK(state.session->status)) {
685 31705 : *_session = state.session;
686 31705 : return state.session->status;
687 : }
688 :
689 2056617 : if (now > state.session->global->expiration_time) {
690 49 : state.session->status = NT_STATUS_NETWORK_SESSION_EXPIRED;
691 : }
692 :
693 2056617 : *_session = state.session;
694 2056617 : return state.session->status;
695 : }
696 :
697 32628 : static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0 *global)
698 : {
699 32628 : 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 32642 : static NTSTATUS smbXsrv_session_global_allocate(struct db_context *db,
710 : TALLOC_CTX *mem_ctx,
711 : struct smbXsrv_session_global0 **_global)
712 : {
713 784 : uint32_t i;
714 32642 : struct smbXsrv_session_global0 *global = NULL;
715 32642 : uint32_t last_free = 0;
716 32642 : const uint32_t min_tries = 3;
717 :
718 32642 : *_global = NULL;
719 :
720 32642 : global = talloc_zero(mem_ctx, struct smbXsrv_session_global0);
721 32642 : if (global == NULL) {
722 0 : return NT_STATUS_NO_MEMORY;
723 : }
724 32642 : 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 33426 : for (i = 0; i < UINT32_MAX; i++) {
733 32642 : bool is_free = false;
734 32642 : bool was_free = false;
735 784 : uint32_t id;
736 :
737 32642 : if (i >= min_tries && last_free != 0) {
738 0 : id = last_free;
739 : } else {
740 32642 : id = generate_random();
741 : }
742 32642 : if (id == 0) {
743 0 : id++;
744 : }
745 32642 : if (id == UINT32_MAX) {
746 0 : id--;
747 : }
748 :
749 32642 : global->db_rec = smbXsrv_session_global_fetch_locked(db, id,
750 : mem_ctx);
751 32642 : if (global->db_rec == NULL) {
752 0 : talloc_free(global);
753 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
754 : }
755 :
756 32642 : smbXsrv_session_global_verify_record(global->db_rec,
757 : &is_free,
758 : &was_free,
759 : NULL, NULL, NULL);
760 :
761 32642 : if (!is_free) {
762 0 : TALLOC_FREE(global->db_rec);
763 0 : continue;
764 : }
765 :
766 32642 : 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 32642 : global->session_global_id = id;
785 :
786 32642 : *_global = global;
787 32642 : 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 33967 : 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 997 : TDB_DATA key;
803 997 : TDB_DATA val;
804 997 : DATA_BLOB blob;
805 997 : struct smbXsrv_session_globalB global_blob;
806 997 : enum ndr_err_code ndr_err;
807 33967 : struct smbXsrv_session_global0 *global = NULL;
808 997 : bool exists;
809 33967 : TALLOC_CTX *frame = talloc_stackframe();
810 :
811 33967 : *is_free = false;
812 :
813 33967 : if (was_free) {
814 32642 : *was_free = false;
815 : }
816 33967 : if (_g) {
817 1325 : *_g = NULL;
818 : }
819 33967 : if (pseqnum) {
820 158 : *pseqnum = 0;
821 : }
822 :
823 33967 : key = dbwrap_record_get_key(db_rec);
824 :
825 33967 : val = dbwrap_record_get_value(db_rec);
826 33967 : if (val.dsize == 0) {
827 32754 : TALLOC_FREE(frame);
828 32754 : *is_free = true;
829 32754 : if (was_free) {
830 32642 : *was_free = true;
831 : }
832 32754 : 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 166060 : static NTSTATUS smbXsrv_session_global_store(struct smbXsrv_session_global0 *global)
915 : {
916 3453 : struct smbXsrv_session_globalB global_blob;
917 166060 : DATA_BLOB blob = data_blob_null;
918 3453 : TDB_DATA key;
919 3453 : TDB_DATA val;
920 3453 : NTSTATUS status;
921 3453 : 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 166060 : key = dbwrap_record_get_key(global->db_rec);
930 166060 : val = dbwrap_record_get_value(global->db_rec);
931 :
932 169513 : global_blob = (struct smbXsrv_session_globalB){
933 166060 : .version = smbXsrv_version_global_current(),
934 : .info.info0 = global,
935 : };
936 :
937 166060 : if (val.dsize >= 8) {
938 133418 : global_blob.seqnum = IVAL(val.dptr, 4);
939 : }
940 166060 : global_blob.seqnum += 1;
941 :
942 166060 : ndr_err = ndr_push_struct_blob(
943 : &blob,
944 : talloc_tos(),
945 : &global_blob,
946 : (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_globalB);
947 166060 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
948 0 : status = ndr_map_error2ntstatus(ndr_err);
949 0 : DBG_WARNING("key '%s' ndr_push - %s\n",
950 : tdb_data_dbg(key),
951 : nt_errstr(status));
952 0 : TALLOC_FREE(global->db_rec);
953 0 : return status;
954 : }
955 :
956 166060 : val = make_tdb_data(blob.data, blob.length);
957 166060 : status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
958 166060 : TALLOC_FREE(blob.data);
959 166060 : if (!NT_STATUS_IS_OK(status)) {
960 0 : DBG_WARNING("key '%s' store - %s\n",
961 : tdb_data_dbg(key),
962 : nt_errstr(status));
963 0 : TALLOC_FREE(global->db_rec);
964 0 : return status;
965 : }
966 :
967 166060 : if (DEBUGLVL(DBGLVL_DEBUG)) {
968 0 : DBG_DEBUG("key '%s' stored\n", tdb_data_dbg(key));
969 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
970 : }
971 :
972 166060 : TALLOC_FREE(global->db_rec);
973 :
974 166060 : return NT_STATUS_OK;
975 : }
976 :
977 : struct smb2srv_session_close_previous_state {
978 : struct tevent_context *ev;
979 : struct smbXsrv_connection *connection;
980 : struct dom_sid *current_sid;
981 : uint64_t previous_session_id;
982 : uint64_t current_session_id;
983 : struct db_record *db_rec;
984 : uint64_t watch_instance;
985 : uint32_t last_seqnum;
986 : };
987 :
988 204 : static void smb2srv_session_close_previous_cleanup(struct tevent_req *req,
989 : enum tevent_req_state req_state)
990 : {
991 8 : struct smb2srv_session_close_previous_state *state =
992 204 : tevent_req_data(req,
993 : struct smb2srv_session_close_previous_state);
994 :
995 204 : if (state->db_rec != NULL) {
996 102 : dbwrap_watched_watch_remove_instance(state->db_rec,
997 : state->watch_instance);
998 102 : state->watch_instance = 0;
999 102 : TALLOC_FREE(state->db_rec);
1000 : }
1001 204 : }
1002 :
1003 : static void smb2srv_session_close_previous_check(struct tevent_req *req);
1004 : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq);
1005 :
1006 102 : struct tevent_req *smb2srv_session_close_previous_send(TALLOC_CTX *mem_ctx,
1007 : struct tevent_context *ev,
1008 : struct smbXsrv_connection *conn,
1009 : struct auth_session_info *session_info,
1010 : uint64_t previous_session_id,
1011 : uint64_t current_session_id)
1012 : {
1013 102 : struct tevent_req *req = NULL;
1014 102 : struct smb2srv_session_close_previous_state *state = NULL;
1015 102 : uint32_t global_id = previous_session_id & UINT32_MAX;
1016 102 : uint64_t global_zeros = previous_session_id & 0xFFFFFFFF00000000LLU;
1017 102 : struct smbXsrv_session_table *table = conn->client->session_table;
1018 102 : struct security_token *current_token = NULL;
1019 :
1020 102 : req = tevent_req_create(mem_ctx, &state,
1021 : struct smb2srv_session_close_previous_state);
1022 102 : if (req == NULL) {
1023 0 : return NULL;
1024 : }
1025 102 : state->ev = ev;
1026 102 : state->connection = conn;
1027 102 : state->previous_session_id = previous_session_id;
1028 102 : state->current_session_id = current_session_id;
1029 :
1030 102 : tevent_req_set_cleanup_fn(req, smb2srv_session_close_previous_cleanup);
1031 :
1032 102 : if (global_zeros != 0) {
1033 0 : tevent_req_done(req);
1034 0 : return tevent_req_post(req, ev);
1035 : }
1036 :
1037 102 : if (session_info == NULL) {
1038 0 : tevent_req_done(req);
1039 0 : return tevent_req_post(req, ev);
1040 : }
1041 102 : current_token = session_info->security_token;
1042 :
1043 102 : if (current_token->num_sids <= PRIMARY_USER_SID_INDEX) {
1044 0 : tevent_req_done(req);
1045 0 : return tevent_req_post(req, ev);
1046 : }
1047 102 : state->current_sid = ¤t_token->sids[PRIMARY_USER_SID_INDEX];
1048 :
1049 102 : if (!security_token_has_nt_authenticated_users(current_token)) {
1050 : /* TODO */
1051 0 : tevent_req_done(req);
1052 0 : return tevent_req_post(req, ev);
1053 : }
1054 :
1055 102 : state->db_rec = smbXsrv_session_global_fetch_locked(
1056 : table->global.db_ctx,
1057 : global_id,
1058 : state /* TALLOC_CTX */);
1059 102 : if (state->db_rec == NULL) {
1060 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1061 0 : return tevent_req_post(req, ev);
1062 : }
1063 :
1064 102 : smb2srv_session_close_previous_check(req);
1065 102 : if (!tevent_req_is_in_progress(req)) {
1066 46 : return tevent_req_post(req, ev);
1067 : }
1068 :
1069 52 : return req;
1070 : }
1071 :
1072 158 : static void smb2srv_session_close_previous_check(struct tevent_req *req)
1073 : {
1074 8 : struct smb2srv_session_close_previous_state *state =
1075 158 : tevent_req_data(req,
1076 : struct smb2srv_session_close_previous_state);
1077 158 : struct smbXsrv_connection *conn = state->connection;
1078 8 : DATA_BLOB blob;
1079 158 : struct security_token *previous_token = NULL;
1080 158 : struct smbXsrv_session_global0 *global = NULL;
1081 8 : enum ndr_err_code ndr_err;
1082 8 : struct smbXsrv_session_close0 close_info0;
1083 8 : struct smbXsrv_session_closeB close_blob;
1084 158 : struct tevent_req *subreq = NULL;
1085 8 : NTSTATUS status;
1086 158 : bool is_free = false;
1087 158 : uint32_t seqnum = 0;
1088 :
1089 158 : smbXsrv_session_global_verify_record(state->db_rec,
1090 : &is_free,
1091 : NULL,
1092 : state,
1093 : &global,
1094 : &seqnum);
1095 :
1096 158 : if (is_free) {
1097 102 : tevent_req_done(req);
1098 102 : return;
1099 : }
1100 :
1101 56 : if (global->auth_session_info == NULL) {
1102 0 : tevent_req_done(req);
1103 0 : return;
1104 : }
1105 :
1106 56 : previous_token = global->auth_session_info->security_token;
1107 :
1108 56 : if (!security_token_is_sid(previous_token, state->current_sid)) {
1109 0 : tevent_req_done(req);
1110 0 : return;
1111 : }
1112 :
1113 : /*
1114 : * If the record changed, but we are not happy with the change yet,
1115 : * we better remove ourself from the waiter list
1116 : * (most likely the first position)
1117 : * and re-add us at the end of the list.
1118 : *
1119 : * This gives other waiters a change
1120 : * to make progress.
1121 : *
1122 : * Otherwise we'll keep our waiter instance alive,
1123 : * keep waiting (most likely at first position).
1124 : * It means the order of watchers stays fair.
1125 : */
1126 56 : if (state->last_seqnum != seqnum) {
1127 56 : state->last_seqnum = seqnum;
1128 56 : dbwrap_watched_watch_remove_instance(state->db_rec,
1129 : state->watch_instance);
1130 56 : state->watch_instance =
1131 56 : dbwrap_watched_watch_add_instance(state->db_rec);
1132 : }
1133 :
1134 60 : subreq = dbwrap_watched_watch_send(state, state->ev, state->db_rec,
1135 : state->watch_instance,
1136 56 : (struct server_id){0});
1137 56 : if (tevent_req_nomem(subreq, req)) {
1138 0 : return;
1139 : }
1140 56 : tevent_req_set_callback(subreq,
1141 : smb2srv_session_close_previous_modified,
1142 : req);
1143 :
1144 56 : close_info0 = (struct smbXsrv_session_close0){
1145 56 : .old_session_global_id = global->session_global_id,
1146 56 : .old_session_wire_id = global->session_wire_id,
1147 56 : .old_creation_time = global->creation_time,
1148 56 : .new_session_wire_id = state->current_session_id,
1149 : };
1150 :
1151 60 : close_blob = (struct smbXsrv_session_closeB){
1152 56 : .version = smbXsrv_version_global_current(),
1153 : .info.info0 = &close_info0,
1154 : };
1155 :
1156 56 : ndr_err = ndr_push_struct_blob(&blob, state, &close_blob,
1157 : (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_closeB);
1158 56 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1159 0 : status = ndr_map_error2ntstatus(ndr_err);
1160 0 : DBG_WARNING("old_session[%" PRIu64 "] "
1161 : "new_session[%" PRIu64 "] ndr_push - %s\n",
1162 : close_info0.old_session_wire_id,
1163 : close_info0.new_session_wire_id,
1164 : nt_errstr(status));
1165 0 : tevent_req_nterror(req, status);
1166 0 : return;
1167 : }
1168 :
1169 56 : status = messaging_send(conn->client->msg_ctx,
1170 56 : global->channels[0].server_id,
1171 : MSG_SMBXSRV_SESSION_CLOSE, &blob);
1172 56 : TALLOC_FREE(global);
1173 56 : if (tevent_req_nterror(req, status)) {
1174 0 : return;
1175 : }
1176 :
1177 56 : TALLOC_FREE(state->db_rec);
1178 52 : return;
1179 : }
1180 :
1181 56 : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq)
1182 : {
1183 4 : struct tevent_req *req =
1184 56 : tevent_req_callback_data(subreq,
1185 : struct tevent_req);
1186 4 : struct smb2srv_session_close_previous_state *state =
1187 56 : tevent_req_data(req,
1188 : struct smb2srv_session_close_previous_state);
1189 4 : uint32_t global_id;
1190 4 : NTSTATUS status;
1191 56 : uint64_t instance = 0;
1192 :
1193 56 : status = dbwrap_watched_watch_recv(subreq, &instance, NULL, NULL);
1194 56 : TALLOC_FREE(subreq);
1195 56 : if (tevent_req_nterror(req, status)) {
1196 0 : return;
1197 : }
1198 :
1199 56 : state->watch_instance = instance;
1200 :
1201 56 : global_id = state->previous_session_id & UINT32_MAX;
1202 :
1203 112 : state->db_rec = smbXsrv_session_global_fetch_locked(
1204 56 : state->connection->client->session_table->global.db_ctx,
1205 : global_id, state /* TALLOC_CTX */);
1206 56 : if (state->db_rec == NULL) {
1207 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1208 0 : return;
1209 : }
1210 :
1211 56 : smb2srv_session_close_previous_check(req);
1212 : }
1213 :
1214 102 : NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
1215 : {
1216 4 : NTSTATUS status;
1217 :
1218 102 : if (tevent_req_is_nterror(req, &status)) {
1219 0 : tevent_req_received(req);
1220 0 : return status;
1221 : }
1222 :
1223 102 : tevent_req_received(req);
1224 102 : return NT_STATUS_OK;
1225 : }
1226 :
1227 61914 : static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session)
1228 : {
1229 1547 : NTSTATUS status;
1230 61914 : struct smbXsrv_connection *xconn = NULL;
1231 :
1232 61914 : if (session->client != NULL) {
1233 32359 : xconn = session->client->connections;
1234 : }
1235 :
1236 94325 : for (; xconn != NULL; xconn = xconn->next) {
1237 774 : struct smbd_smb2_request *preq;
1238 :
1239 32467 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1240 56 : if (preq->session != session) {
1241 0 : continue;
1242 : }
1243 :
1244 56 : preq->session = NULL;
1245 : /*
1246 : * If we no longer have a session we can't
1247 : * sign or encrypt replies.
1248 : */
1249 56 : preq->do_signing = false;
1250 56 : preq->do_encryption = false;
1251 56 : preq->preauth = NULL;
1252 : }
1253 : }
1254 :
1255 61914 : status = smbXsrv_session_logoff(session);
1256 61914 : return status;
1257 : }
1258 :
1259 32628 : static int smbXsrv_session_destructor(struct smbXsrv_session *session)
1260 : {
1261 784 : NTSTATUS status;
1262 :
1263 32628 : DBG_DEBUG("destructing session(%" PRIu64 ")\n",
1264 : session->global->session_wire_id);
1265 :
1266 32628 : status = smbXsrv_session_clear_and_logoff(session);
1267 32628 : if (!NT_STATUS_IS_OK(status)) {
1268 0 : DBG_ERR("smbXsrv_session_logoff() failed: %s\n",
1269 : nt_errstr(status));
1270 : }
1271 :
1272 32628 : TALLOC_FREE(session->global);
1273 :
1274 32628 : return 0;
1275 : }
1276 :
1277 32642 : NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
1278 : NTTIME now,
1279 : struct smbXsrv_session **_session)
1280 : {
1281 32642 : struct smbXsrv_session_table *table = conn->client->session_table;
1282 32642 : struct db_record *local_rec = NULL;
1283 32642 : struct smbXsrv_session *session = NULL;
1284 32642 : void *ptr = NULL;
1285 784 : TDB_DATA val;
1286 32642 : struct smbXsrv_session_global0 *global = NULL;
1287 32642 : struct smbXsrv_channel_global0 *channel = NULL;
1288 784 : NTSTATUS status;
1289 :
1290 32642 : if (table->local.num_sessions >= table->local.max_sessions) {
1291 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1292 : }
1293 :
1294 32642 : session = talloc_zero(table, struct smbXsrv_session);
1295 32642 : if (session == NULL) {
1296 0 : return NT_STATUS_NO_MEMORY;
1297 : }
1298 32642 : session->table = table;
1299 32642 : session->idle_time = now;
1300 32642 : session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
1301 32642 : session->client = conn->client;
1302 32642 : session->homes_snum = -1;
1303 :
1304 32642 : status = smbXsrv_session_global_allocate(table->global.db_ctx,
1305 : session,
1306 : &global);
1307 32642 : if (!NT_STATUS_IS_OK(status)) {
1308 0 : TALLOC_FREE(session);
1309 0 : return status;
1310 : }
1311 32642 : session->global = global;
1312 :
1313 32642 : if (conn->protocol >= PROTOCOL_SMB2_02) {
1314 25566 : uint64_t id = global->session_global_id;
1315 :
1316 25566 : global->connection_dialect = conn->smb2.server.dialect;
1317 25566 : global->client_guid = conn->smb2.client.guid;
1318 :
1319 25566 : global->session_wire_id = id;
1320 :
1321 25566 : status = smb2srv_tcon_table_init(session);
1322 25566 : if (!NT_STATUS_IS_OK(status)) {
1323 0 : TALLOC_FREE(session);
1324 0 : return status;
1325 : }
1326 :
1327 25566 : session->local_id = global->session_global_id;
1328 :
1329 25566 : local_rec = smbXsrv_session_local_fetch_locked(
1330 : table->local.db_ctx,
1331 : session->local_id,
1332 : session /* TALLOC_CTX */);
1333 25566 : if (local_rec == NULL) {
1334 0 : TALLOC_FREE(session);
1335 0 : return NT_STATUS_NO_MEMORY;
1336 : }
1337 :
1338 25566 : val = dbwrap_record_get_value(local_rec);
1339 25566 : if (val.dsize != 0) {
1340 0 : TALLOC_FREE(session);
1341 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1342 : }
1343 : } else {
1344 :
1345 7076 : status = smb1srv_session_local_allocate_id(table->local.db_ctx,
1346 : table->local.lowest_id,
1347 : table->local.highest_id,
1348 : session,
1349 : &local_rec,
1350 : &session->local_id);
1351 7076 : if (!NT_STATUS_IS_OK(status)) {
1352 0 : TALLOC_FREE(session);
1353 0 : return status;
1354 : }
1355 :
1356 7076 : global->session_wire_id = session->local_id;
1357 : }
1358 :
1359 32642 : global->creation_time = now;
1360 32642 : global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1361 :
1362 32642 : status = smbXsrv_session_add_channel(session, conn, now, &channel);
1363 32642 : if (!NT_STATUS_IS_OK(status)) {
1364 0 : TALLOC_FREE(session);
1365 0 : return status;
1366 : }
1367 :
1368 32642 : ptr = session;
1369 32642 : val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
1370 32642 : status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
1371 32642 : TALLOC_FREE(local_rec);
1372 32642 : if (!NT_STATUS_IS_OK(status)) {
1373 0 : TALLOC_FREE(session);
1374 0 : return status;
1375 : }
1376 32642 : table->local.num_sessions += 1;
1377 :
1378 32642 : talloc_set_destructor(session, smbXsrv_session_destructor);
1379 :
1380 32642 : status = smbXsrv_session_global_store(global);
1381 32642 : if (!NT_STATUS_IS_OK(status)) {
1382 0 : DBG_ERR("global_id (0x%08x) store failed - %s\n",
1383 : session->global->session_global_id,
1384 : nt_errstr(status));
1385 0 : TALLOC_FREE(session);
1386 0 : return status;
1387 : }
1388 :
1389 32642 : if (DEBUGLVL(DBGLVL_DEBUG)) {
1390 0 : struct smbXsrv_sessionB session_blob = {
1391 : .version = SMBXSRV_VERSION_0,
1392 : .info.info0 = session,
1393 : };
1394 :
1395 0 : DBG_DEBUG("global_id (0x%08x) stored\n",
1396 : session->global->session_global_id);
1397 0 : NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1398 : }
1399 :
1400 32642 : *_session = session;
1401 32642 : return NT_STATUS_OK;
1402 : }
1403 :
1404 33552 : NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
1405 : struct smbXsrv_connection *conn,
1406 : NTTIME now,
1407 : struct smbXsrv_channel_global0 **_c)
1408 : {
1409 33552 : struct smbXsrv_session_global0 *global = session->global;
1410 33552 : struct smbXsrv_channel_global0 *c = NULL;
1411 :
1412 33552 : if (global->num_channels > 31) {
1413 : /*
1414 : * Windows allow up to 32 channels
1415 : */
1416 4 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1417 : }
1418 :
1419 33548 : c = talloc_realloc(global,
1420 : global->channels,
1421 : struct smbXsrv_channel_global0,
1422 : global->num_channels + 1);
1423 33548 : if (c == NULL) {
1424 0 : return NT_STATUS_NO_MEMORY;
1425 : }
1426 33548 : global->channels = c;
1427 :
1428 33548 : c = &global->channels[global->num_channels];
1429 :
1430 34354 : *c = (struct smbXsrv_channel_global0){
1431 33548 : .server_id = messaging_server_id(conn->client->msg_ctx),
1432 33548 : .channel_id = conn->channel_id,
1433 : .creation_time = now,
1434 : .connection = conn,
1435 : };
1436 :
1437 67096 : c->local_address = tsocket_address_string(conn->local_address,
1438 33548 : global->channels);
1439 33548 : if (c->local_address == NULL) {
1440 0 : return NT_STATUS_NO_MEMORY;
1441 : }
1442 67096 : c->remote_address = tsocket_address_string(conn->remote_address,
1443 33548 : global->channels);
1444 33548 : if (c->remote_address == NULL) {
1445 0 : return NT_STATUS_NO_MEMORY;
1446 : }
1447 33548 : c->remote_name = talloc_strdup(global->channels,
1448 : conn->remote_hostname);
1449 33548 : if (c->remote_name == NULL) {
1450 0 : return NT_STATUS_NO_MEMORY;
1451 : }
1452 :
1453 33548 : global->num_channels += 1;
1454 :
1455 33548 : *_c = c;
1456 33548 : return NT_STATUS_OK;
1457 : }
1458 :
1459 133418 : NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session)
1460 : {
1461 133418 : struct smbXsrv_session_table *table = session->table;
1462 2669 : NTSTATUS status;
1463 :
1464 133418 : if (session->global->db_rec != NULL) {
1465 0 : DBG_ERR("smbXsrv_session_update(0x%08x): "
1466 : "Called with db_rec != NULL'\n",
1467 : session->global->session_global_id);
1468 0 : return NT_STATUS_INTERNAL_ERROR;
1469 : }
1470 :
1471 133418 : if (table == NULL) {
1472 0 : DBG_ERR("smbXsrv_session_update(0x%08x): "
1473 : "Called with table == NULL'\n",
1474 : session->global->session_global_id);
1475 0 : return NT_STATUS_INTERNAL_ERROR;
1476 : }
1477 :
1478 264167 : session->global->db_rec = smbXsrv_session_global_fetch_locked(
1479 : table->global.db_ctx,
1480 130749 : session->global->session_global_id,
1481 130749 : session->global /* TALLOC_CTX */);
1482 133418 : if (session->global->db_rec == NULL) {
1483 0 : return NT_STATUS_INTERNAL_DB_ERROR;
1484 : }
1485 :
1486 133418 : status = smbXsrv_session_global_store(session->global);
1487 133418 : if (!NT_STATUS_IS_OK(status)) {
1488 0 : DBG_ERR("global_id (0x%08x) store failed - %s\n",
1489 : session->global->session_global_id,
1490 : nt_errstr(status));
1491 0 : return status;
1492 : }
1493 :
1494 133418 : if (DEBUGLVL(DBGLVL_DEBUG)) {
1495 0 : struct smbXsrv_sessionB session_blob = {
1496 : .version = SMBXSRV_VERSION_0,
1497 : .info.info0 = session,
1498 : };
1499 :
1500 0 : DBG_DEBUG("global_id (0x%08x) stored\n",
1501 : session->global->session_global_id);
1502 0 : NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1503 : }
1504 :
1505 133418 : return NT_STATUS_OK;
1506 : }
1507 :
1508 3552779 : NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
1509 : const struct smbXsrv_connection *conn,
1510 : struct smbXsrv_channel_global0 **_c)
1511 : {
1512 39167 : uint32_t i;
1513 :
1514 3632153 : for (i=0; i < session->global->num_channels; i++) {
1515 3626077 : struct smbXsrv_channel_global0 *c = &session->global->channels[i];
1516 :
1517 3626077 : if (c->channel_id != conn->channel_id) {
1518 79374 : continue;
1519 : }
1520 :
1521 3546703 : if (c->connection != conn) {
1522 0 : continue;
1523 : }
1524 :
1525 3546703 : *_c = c;
1526 3546703 : return NT_STATUS_OK;
1527 : }
1528 :
1529 6076 : return NT_STATUS_USER_SESSION_DELETED;
1530 : }
1531 :
1532 94952 : NTSTATUS smbXsrv_session_find_auth(const struct smbXsrv_session *session,
1533 : const struct smbXsrv_connection *conn,
1534 : NTTIME now,
1535 : struct smbXsrv_session_auth0 **_a)
1536 : {
1537 2045 : struct smbXsrv_session_auth0 *a;
1538 :
1539 94952 : for (a = session->pending_auth; a != NULL; a = a->next) {
1540 25622 : if (a->channel_id != conn->channel_id) {
1541 0 : continue;
1542 : }
1543 :
1544 25622 : if (a->connection == conn) {
1545 25622 : if (now != 0) {
1546 25604 : a->idle_time = now;
1547 : }
1548 25622 : *_a = a;
1549 25622 : return NT_STATUS_OK;
1550 : }
1551 : }
1552 :
1553 69330 : return NT_STATUS_USER_SESSION_DELETED;
1554 : }
1555 :
1556 33667 : static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0 *a)
1557 : {
1558 33667 : if (a->session == NULL) {
1559 14 : return 0;
1560 : }
1561 :
1562 33649 : DLIST_REMOVE(a->session->pending_auth, a);
1563 33649 : a->session = NULL;
1564 33649 : return 0;
1565 : }
1566 :
1567 33661 : NTSTATUS smbXsrv_session_create_auth(struct smbXsrv_session *session,
1568 : struct smbXsrv_connection *conn,
1569 : NTTIME now,
1570 : uint8_t in_flags,
1571 : uint8_t in_security_mode,
1572 : struct smbXsrv_session_auth0 **_a)
1573 : {
1574 835 : struct smbXsrv_session_auth0 *a;
1575 835 : NTSTATUS status;
1576 :
1577 33661 : status = smbXsrv_session_find_auth(session, conn, 0, &a);
1578 33661 : if (NT_STATUS_IS_OK(status)) {
1579 0 : return NT_STATUS_INTERNAL_ERROR;
1580 : }
1581 :
1582 33661 : a = talloc(session, struct smbXsrv_session_auth0);
1583 33661 : if (a == NULL) {
1584 0 : return NT_STATUS_NO_MEMORY;
1585 : }
1586 :
1587 33661 : *a = (struct smbXsrv_session_auth0){
1588 : .session = session,
1589 : .connection = conn,
1590 : .in_flags = in_flags,
1591 : .in_security_mode = in_security_mode,
1592 : .creation_time = now,
1593 : .idle_time = now,
1594 33661 : .channel_id = conn->channel_id,
1595 : };
1596 :
1597 33661 : if (conn->protocol >= PROTOCOL_SMB3_11) {
1598 24265 : a->preauth = talloc(a, struct smbXsrv_preauth);
1599 24265 : if (a->preauth == NULL) {
1600 0 : TALLOC_FREE(session);
1601 0 : return NT_STATUS_NO_MEMORY;
1602 : }
1603 24265 : *a->preauth = conn->smb2.preauth;
1604 : }
1605 :
1606 33661 : talloc_set_destructor(a, smbXsrv_session_auth0_destructor);
1607 33661 : DLIST_ADD_END(session->pending_auth, a);
1608 :
1609 33661 : *_a = a;
1610 33661 : return NT_STATUS_OK;
1611 : }
1612 :
1613 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq);
1614 :
1615 2026 : NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session,
1616 : struct smbXsrv_connection *xconn)
1617 : {
1618 2026 : struct smbXsrv_session_auth0 *a = NULL;
1619 2026 : struct smbXsrv_channel_global0 *c = NULL;
1620 210 : NTSTATUS status;
1621 2026 : bool need_update = false;
1622 :
1623 2026 : status = smbXsrv_session_find_auth(session, xconn, 0, &a);
1624 2026 : if (!NT_STATUS_IS_OK(status)) {
1625 2008 : a = NULL;
1626 : }
1627 2026 : status = smbXsrv_session_find_channel(session, xconn, &c);
1628 2026 : if (!NT_STATUS_IS_OK(status)) {
1629 1086 : c = NULL;
1630 : }
1631 :
1632 2026 : if (a != NULL) {
1633 18 : smbXsrv_session_auth0_destructor(a);
1634 18 : a->connection = NULL;
1635 18 : need_update = true;
1636 : }
1637 :
1638 2026 : if (c != NULL) {
1639 940 : struct smbXsrv_session_global0 *global = session->global;
1640 24 : ptrdiff_t n;
1641 :
1642 940 : n = (c - global->channels);
1643 940 : if (n >= global->num_channels || n < 0) {
1644 0 : return NT_STATUS_INTERNAL_ERROR;
1645 : }
1646 940 : ARRAY_DEL_ELEMENT(global->channels, n, global->num_channels);
1647 940 : global->num_channels--;
1648 940 : if (global->num_channels == 0) {
1649 44 : struct smbXsrv_client *client = session->client;
1650 44 : struct tevent_queue *xconn_wait_queue =
1651 : xconn->transport.shutdown_wait_queue;
1652 44 : struct tevent_req *subreq = NULL;
1653 :
1654 : /*
1655 : * Let the connection wait until the session is
1656 : * destroyed.
1657 : *
1658 : * We don't set a callback, as we just want to block the
1659 : * wait queue and the talloc_free() of the session will
1660 : * remove the item from the wait queue in order
1661 : * to remove allow the connection to disappear.
1662 : */
1663 44 : if (xconn_wait_queue != NULL) {
1664 44 : subreq = tevent_queue_wait_send(session,
1665 : client->raw_ev_ctx,
1666 : xconn_wait_queue);
1667 44 : if (subreq == NULL) {
1668 0 : status = NT_STATUS_NO_MEMORY;
1669 0 : DBG_ERR("tevent_queue_wait_send() "
1670 : "session(%" PRIu64
1671 : ") failed: %s\n",
1672 : session->global
1673 : ->session_wire_id,
1674 : nt_errstr(status));
1675 0 : return status;
1676 : }
1677 : }
1678 :
1679 : /*
1680 : * This is guaranteed to set
1681 : * session->status = NT_STATUS_USER_SESSION_DELETED
1682 : * even if NULL is returned.
1683 : */
1684 44 : subreq = smb2srv_session_shutdown_send(session,
1685 : client->raw_ev_ctx,
1686 : session,
1687 : NULL);
1688 44 : if (subreq == NULL) {
1689 0 : status = NT_STATUS_NO_MEMORY;
1690 0 : DBG_ERR("smb2srv_session_shutdown_send("
1691 : "%" PRIu64 " failed: %s\n",
1692 : session->global->session_wire_id,
1693 : nt_errstr(status));
1694 0 : return status;
1695 : }
1696 44 : tevent_req_set_callback(subreq,
1697 : smbXsrv_session_remove_channel_done,
1698 : session);
1699 : }
1700 916 : need_update = true;
1701 : }
1702 :
1703 2002 : if (!need_update) {
1704 1086 : return NT_STATUS_OK;
1705 : }
1706 :
1707 940 : return smbXsrv_session_update(session);
1708 : }
1709 :
1710 44 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq)
1711 : {
1712 4 : struct smbXsrv_session *session =
1713 44 : tevent_req_callback_data(subreq,
1714 : struct smbXsrv_session);
1715 4 : NTSTATUS status;
1716 :
1717 44 : status = smb2srv_session_shutdown_recv(subreq);
1718 44 : TALLOC_FREE(subreq);
1719 44 : if (!NT_STATUS_IS_OK(status)) {
1720 0 : DBG_ERR("smb2srv_session_shutdown_recv(%" PRIu64
1721 : ") failed: %s\n",
1722 : session->global->session_wire_id,
1723 : nt_errstr(status));
1724 : }
1725 :
1726 44 : status = smbXsrv_session_logoff(session);
1727 44 : if (!NT_STATUS_IS_OK(status)) {
1728 0 : DBG_ERR("smbXsrv_session_logoff(%" PRIu64 ") failed: %s\n",
1729 : session->global->session_wire_id,
1730 : nt_errstr(status));
1731 : }
1732 :
1733 44 : TALLOC_FREE(session);
1734 44 : }
1735 :
1736 : struct smb2srv_session_shutdown_state {
1737 : struct tevent_queue *wait_queue;
1738 : };
1739 :
1740 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
1741 :
1742 2004 : struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
1743 : struct tevent_context *ev,
1744 : struct smbXsrv_session *session,
1745 : struct smbd_smb2_request *current_req)
1746 : {
1747 2004 : struct tevent_req *req = NULL;
1748 2004 : struct smb2srv_session_shutdown_state *state = NULL;
1749 2004 : struct tevent_req *subreq = NULL;
1750 2004 : struct smbXsrv_connection *xconn = NULL;
1751 2004 : size_t len = 0;
1752 :
1753 : /*
1754 : * Make sure that no new request will be able to use this session.
1755 : */
1756 2004 : session->status = NT_STATUS_USER_SESSION_DELETED;
1757 :
1758 2004 : req = tevent_req_create(mem_ctx, &state,
1759 : struct smb2srv_session_shutdown_state);
1760 2004 : if (req == NULL) {
1761 0 : return NULL;
1762 : }
1763 :
1764 2004 : state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
1765 2004 : if (tevent_req_nomem(state->wait_queue, req)) {
1766 0 : return tevent_req_post(req, ev);
1767 : }
1768 :
1769 4098 : for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
1770 33 : struct smbd_smb2_request *preq;
1771 :
1772 4038 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1773 1944 : if (preq == current_req) {
1774 : /* Can't cancel current request. */
1775 1906 : continue;
1776 : }
1777 38 : if (preq->session != session) {
1778 : /* Request on different session. */
1779 26 : continue;
1780 : }
1781 :
1782 12 : if (preq->subreq != NULL) {
1783 12 : tevent_req_cancel(preq->subreq);
1784 : }
1785 :
1786 : /*
1787 : * Now wait until the request is finished.
1788 : *
1789 : * We don't set a callback, as we just want to block the
1790 : * wait queue and the talloc_free() of the request will
1791 : * remove the item from the wait queue.
1792 : */
1793 12 : subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
1794 12 : if (tevent_req_nomem(subreq, req)) {
1795 0 : return tevent_req_post(req, ev);
1796 : }
1797 : }
1798 : }
1799 :
1800 2004 : len = tevent_queue_length(state->wait_queue);
1801 2004 : if (len == 0) {
1802 1992 : tevent_req_done(req);
1803 1992 : return tevent_req_post(req, ev);
1804 : }
1805 :
1806 : /*
1807 : * Now we add our own waiter to the end of the queue,
1808 : * this way we get notified when all pending requests are finished
1809 : * and send to the socket.
1810 : */
1811 12 : subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
1812 12 : if (tevent_req_nomem(subreq, req)) {
1813 0 : return tevent_req_post(req, ev);
1814 : }
1815 12 : tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
1816 :
1817 12 : return req;
1818 : }
1819 :
1820 12 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
1821 : {
1822 0 : struct tevent_req *req =
1823 12 : tevent_req_callback_data(subreq,
1824 : struct tevent_req);
1825 :
1826 12 : tevent_queue_wait_recv(subreq);
1827 12 : TALLOC_FREE(subreq);
1828 :
1829 12 : tevent_req_done(req);
1830 12 : }
1831 :
1832 2004 : NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
1833 : {
1834 2004 : return tevent_req_simple_recv_ntstatus(req);
1835 : }
1836 :
1837 62183 : NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
1838 : {
1839 1561 : struct smbXsrv_session_table *table;
1840 62183 : struct db_record *local_rec = NULL;
1841 62183 : struct db_record *global_rec = NULL;
1842 62183 : struct smbd_server_connection *sconn = NULL;
1843 1561 : NTSTATUS status;
1844 62183 : NTSTATUS error = NT_STATUS_OK;
1845 :
1846 62183 : if (session->table == NULL) {
1847 29555 : return NT_STATUS_OK;
1848 : }
1849 :
1850 32628 : table = session->table;
1851 32628 : session->table = NULL;
1852 :
1853 32628 : sconn = session->client->sconn;
1854 32628 : session->client = NULL;
1855 32628 : session->status = NT_STATUS_USER_SESSION_DELETED;
1856 :
1857 : /*
1858 : * For SMB2 this is a bit redundant as files are also close
1859 : * below via smb2srv_tcon_disconnect_all() -> ... ->
1860 : * smbXsrv_tcon_disconnect() -> close_cnum() ->
1861 : * file_close_conn().
1862 : */
1863 32628 : file_close_user(sconn, session->global->session_wire_id);
1864 :
1865 32628 : if (session->tcon_table != NULL) {
1866 : /*
1867 : * Note: We only have a tcon_table for SMB2.
1868 : */
1869 25564 : status = smb2srv_tcon_disconnect_all(session);
1870 25564 : if (!NT_STATUS_IS_OK(status)) {
1871 52 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1872 : "smb2srv_tcon_disconnect_all() failed: %s\n",
1873 : session->global->session_global_id,
1874 : nt_errstr(status));
1875 52 : error = status;
1876 : }
1877 : }
1878 :
1879 32628 : invalidate_vuid(sconn, session->global->session_wire_id);
1880 :
1881 32628 : global_rec = session->global->db_rec;
1882 32628 : session->global->db_rec = NULL;
1883 32628 : if (global_rec == NULL) {
1884 32628 : global_rec = smbXsrv_session_global_fetch_locked(
1885 : table->global.db_ctx,
1886 31844 : session->global->session_global_id,
1887 31844 : session->global /* TALLOC_CTX */);
1888 32628 : if (global_rec == NULL) {
1889 0 : error = NT_STATUS_INTERNAL_ERROR;
1890 : }
1891 : }
1892 :
1893 32628 : if (global_rec != NULL) {
1894 32628 : status = dbwrap_record_delete(global_rec);
1895 32628 : if (!NT_STATUS_IS_OK(status)) {
1896 0 : TDB_DATA key = dbwrap_record_get_key(global_rec);
1897 :
1898 0 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1899 : "failed to delete global key '%s': %s\n",
1900 : session->global->session_global_id,
1901 : tdb_data_dbg(key),
1902 : nt_errstr(status));
1903 0 : error = status;
1904 : }
1905 : }
1906 32628 : TALLOC_FREE(global_rec);
1907 :
1908 32628 : local_rec = session->db_rec;
1909 32628 : if (local_rec == NULL) {
1910 3342 : local_rec = smbXsrv_session_local_fetch_locked(
1911 : table->local.db_ctx,
1912 : session->local_id,
1913 : session /* TALLOC_CTX */);
1914 3342 : if (local_rec == NULL) {
1915 0 : error = NT_STATUS_INTERNAL_ERROR;
1916 : }
1917 : }
1918 :
1919 32628 : if (local_rec != NULL) {
1920 32628 : status = dbwrap_record_delete(local_rec);
1921 32628 : if (!NT_STATUS_IS_OK(status)) {
1922 0 : TDB_DATA key = dbwrap_record_get_key(local_rec);
1923 :
1924 0 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1925 : "failed to delete local key '%s': %s\n",
1926 : session->global->session_global_id,
1927 : tdb_data_dbg(key),
1928 : nt_errstr(status));
1929 0 : error = status;
1930 : }
1931 32628 : table->local.num_sessions -= 1;
1932 : }
1933 32628 : if (session->db_rec == NULL) {
1934 3342 : TALLOC_FREE(local_rec);
1935 : }
1936 32628 : session->db_rec = NULL;
1937 :
1938 32628 : return error;
1939 : }
1940 :
1941 : struct smbXsrv_session_logoff_all_state {
1942 : NTSTATUS first_status;
1943 : int errors;
1944 : };
1945 :
1946 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1947 : void *private_data);
1948 :
1949 31917 : NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_client *client)
1950 : {
1951 31917 : struct smbXsrv_session_table *table = client->session_table;
1952 31917 : struct smbXsrv_session_logoff_all_state state = {};
1953 862 : NTSTATUS status;
1954 31917 : int count = 0;
1955 :
1956 31917 : if (table == NULL) {
1957 714 : DBG_DEBUG("empty session_table, nothing to do.\n");
1958 714 : return NT_STATUS_OK;
1959 : }
1960 :
1961 31203 : status = dbwrap_traverse(table->local.db_ctx,
1962 : smbXsrv_session_logoff_all_callback,
1963 : &state, &count);
1964 31203 : if (!NT_STATUS_IS_OK(status)) {
1965 0 : DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
1966 0 : return status;
1967 : }
1968 :
1969 31203 : if (!NT_STATUS_IS_OK(state.first_status)) {
1970 50 : DBG_ERR("count[%d] errors[%d] first[%s]\n",
1971 : count,
1972 : state.errors,
1973 : nt_errstr(state.first_status));
1974 50 : return state.first_status;
1975 : }
1976 :
1977 31153 : return NT_STATUS_OK;
1978 : }
1979 :
1980 29286 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1981 : void *private_data)
1982 : {
1983 29286 : struct smbXsrv_session_logoff_all_state *state =
1984 : (struct smbXsrv_session_logoff_all_state *)private_data;
1985 763 : TDB_DATA val;
1986 29286 : void *ptr = NULL;
1987 29286 : struct smbXsrv_session *session = NULL;
1988 763 : NTSTATUS status;
1989 :
1990 29286 : val = dbwrap_record_get_value(local_rec);
1991 29286 : if (val.dsize != sizeof(ptr)) {
1992 0 : status = NT_STATUS_INTERNAL_ERROR;
1993 0 : if (NT_STATUS_IS_OK(state->first_status)) {
1994 0 : state->first_status = status;
1995 : }
1996 0 : state->errors++;
1997 0 : return 0;
1998 : }
1999 :
2000 29286 : memcpy(&ptr, val.dptr, val.dsize);
2001 29286 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2002 :
2003 29286 : session->db_rec = local_rec;
2004 29286 : status = smbXsrv_session_clear_and_logoff(session);
2005 29286 : session->db_rec = NULL;
2006 29286 : if (!NT_STATUS_IS_OK(status)) {
2007 52 : if (NT_STATUS_IS_OK(state->first_status)) {
2008 50 : state->first_status = status;
2009 : }
2010 52 : state->errors++;
2011 52 : return 0;
2012 : }
2013 :
2014 28471 : return 0;
2015 : }
2016 :
2017 : struct smbXsrv_session_local_trav_state {
2018 : NTSTATUS status;
2019 : int (*caller_cb)(struct smbXsrv_session *session,
2020 : void *caller_data);
2021 : void *caller_data;
2022 : };
2023 :
2024 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
2025 : void *private_data);
2026 :
2027 0 : NTSTATUS smbXsrv_session_local_traverse(
2028 : struct smbXsrv_client *client,
2029 : int (*caller_cb)(struct smbXsrv_session *session,
2030 : void *caller_data),
2031 : void *caller_data)
2032 : {
2033 0 : struct smbXsrv_session_table *table = client->session_table;
2034 0 : struct smbXsrv_session_local_trav_state state;
2035 0 : NTSTATUS status;
2036 0 : int count = 0;
2037 :
2038 0 : state = (struct smbXsrv_session_local_trav_state) {
2039 : .status = NT_STATUS_OK,
2040 : .caller_cb = caller_cb,
2041 : .caller_data = caller_data,
2042 : };
2043 :
2044 0 : if (table == NULL) {
2045 0 : DBG_DEBUG("empty session_table, nothing to do.\n");
2046 0 : return NT_STATUS_OK;
2047 : }
2048 :
2049 0 : status = dbwrap_traverse(table->local.db_ctx,
2050 : smbXsrv_session_local_traverse_cb,
2051 : &state,
2052 : &count);
2053 0 : if (!NT_STATUS_IS_OK(status)) {
2054 0 : DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
2055 0 : return status;
2056 : }
2057 0 : if (!NT_STATUS_IS_OK(state.status)) {
2058 0 : DBG_ERR("count[%d] status[%s]\n",
2059 : count, nt_errstr(state.status));
2060 0 : return state.status;
2061 : }
2062 :
2063 0 : return NT_STATUS_OK;
2064 : }
2065 :
2066 0 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
2067 : void *private_data)
2068 : {
2069 0 : struct smbXsrv_session_local_trav_state *state =
2070 : (struct smbXsrv_session_local_trav_state *)private_data;
2071 0 : TDB_DATA val;
2072 0 : void *ptr = NULL;
2073 0 : struct smbXsrv_session *session = NULL;
2074 0 : int ret;
2075 :
2076 0 : val = dbwrap_record_get_value(local_rec);
2077 0 : if (val.dsize != sizeof(ptr)) {
2078 0 : state->status = NT_STATUS_INTERNAL_ERROR;
2079 0 : return -1;
2080 : }
2081 :
2082 0 : memcpy(&ptr, val.dptr, val.dsize);
2083 0 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2084 :
2085 0 : session->db_rec = local_rec;
2086 0 : ret = state->caller_cb(session, state->caller_data);
2087 0 : session->db_rec = NULL;
2088 :
2089 0 : return ret;
2090 : }
2091 :
2092 : struct smbXsrv_session_disconnect_xconn_state {
2093 : struct smbXsrv_connection *xconn;
2094 : NTSTATUS first_status;
2095 : int errors;
2096 : };
2097 :
2098 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
2099 : void *private_data);
2100 :
2101 1106 : NTSTATUS smbXsrv_session_disconnect_xconn(struct smbXsrv_connection *xconn)
2102 : {
2103 1106 : struct smbXsrv_client *client = xconn->client;
2104 1106 : struct smbXsrv_session_table *table = client->session_table;
2105 1106 : struct smbXsrv_session_disconnect_xconn_state state = {
2106 : .xconn = xconn,
2107 : };
2108 52 : NTSTATUS status;
2109 1106 : int count = 0;
2110 :
2111 1106 : if (table == NULL) {
2112 0 : DBG_ERR("empty session_table, nothing to do.\n");
2113 0 : return NT_STATUS_OK;
2114 : }
2115 :
2116 1106 : status = dbwrap_traverse(table->local.db_ctx,
2117 : smbXsrv_session_disconnect_xconn_callback,
2118 : &state, &count);
2119 1106 : if (!NT_STATUS_IS_OK(status)) {
2120 0 : DBG_ERR("dbwrap_traverse() failed: %s\n",
2121 : nt_errstr(status));
2122 0 : return status;
2123 : }
2124 :
2125 1106 : if (!NT_STATUS_IS_OK(state.first_status)) {
2126 0 : DBG_ERR("count[%d] errors[%d] first[%s]\n",
2127 : count, state.errors,
2128 : nt_errstr(state.first_status));
2129 0 : return state.first_status;
2130 : }
2131 :
2132 1106 : return NT_STATUS_OK;
2133 : }
2134 :
2135 1184 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
2136 : void *private_data)
2137 : {
2138 1184 : struct smbXsrv_session_disconnect_xconn_state *state =
2139 : (struct smbXsrv_session_disconnect_xconn_state *)private_data;
2140 62 : TDB_DATA val;
2141 1184 : void *ptr = NULL;
2142 1184 : struct smbXsrv_session *session = NULL;
2143 62 : NTSTATUS status;
2144 :
2145 1184 : val = dbwrap_record_get_value(local_rec);
2146 1184 : if (val.dsize != sizeof(ptr)) {
2147 0 : status = NT_STATUS_INTERNAL_ERROR;
2148 0 : if (NT_STATUS_IS_OK(state->first_status)) {
2149 0 : state->first_status = status;
2150 : }
2151 0 : state->errors++;
2152 0 : return 0;
2153 : }
2154 :
2155 1184 : memcpy(&ptr, val.dptr, val.dsize);
2156 1184 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2157 :
2158 1184 : session->db_rec = local_rec;
2159 1184 : status = smbXsrv_session_remove_channel(session, state->xconn);
2160 1184 : session->db_rec = NULL;
2161 1184 : if (!NT_STATUS_IS_OK(status)) {
2162 0 : if (NT_STATUS_IS_OK(state->first_status)) {
2163 0 : state->first_status = status;
2164 : }
2165 0 : state->errors++;
2166 : }
2167 :
2168 1122 : return 0;
2169 : }
2170 :
2171 5779 : NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn)
2172 : {
2173 : /*
2174 : * Allow a range from 1..65534 with 65534 values.
2175 : */
2176 5779 : return smbXsrv_session_table_init(conn, 1, UINT16_MAX - 1,
2177 : UINT16_MAX - 1);
2178 : }
2179 :
2180 675313 : NTSTATUS smb1srv_session_lookup(struct smbXsrv_connection *conn,
2181 : uint16_t vuid, NTTIME now,
2182 : struct smbXsrv_session **session)
2183 : {
2184 675313 : struct smbXsrv_session_table *table = conn->client->session_table;
2185 675313 : uint32_t local_id = vuid;
2186 :
2187 675313 : return smbXsrv_session_local_lookup(table, conn, local_id, now,
2188 : session);
2189 : }
2190 :
2191 1850621 : NTSTATUS smbXsrv_session_info_lookup(struct smbXsrv_client *client,
2192 : uint64_t session_wire_id,
2193 : struct auth_session_info **si)
2194 : {
2195 1850621 : struct smbXsrv_session_table *table = client->session_table;
2196 17142 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2197 1850621 : struct smbXsrv_session_local_fetch_state state = {
2198 : .status = NT_STATUS_INTERNAL_ERROR,
2199 : };
2200 17142 : TDB_DATA key;
2201 17142 : NTSTATUS status;
2202 :
2203 1850621 : if (session_wire_id == 0) {
2204 0 : return NT_STATUS_USER_SESSION_DELETED;
2205 : }
2206 :
2207 1850621 : if (table == NULL) {
2208 : /* this might happen before the end of negprot */
2209 0 : return NT_STATUS_USER_SESSION_DELETED;
2210 : }
2211 :
2212 1850621 : if (table->local.db_ctx == NULL) {
2213 0 : return NT_STATUS_INTERNAL_ERROR;
2214 : }
2215 :
2216 1850621 : key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2217 :
2218 1850621 : status = dbwrap_parse_record(table->local.db_ctx, key,
2219 : smbXsrv_session_local_fetch_parser,
2220 : &state);
2221 1850621 : if (!NT_STATUS_IS_OK(status)) {
2222 17 : return status;
2223 : }
2224 1850604 : if (!NT_STATUS_IS_OK(state.status)) {
2225 0 : return state.status;
2226 : }
2227 1850604 : if (state.session->global->auth_session_info == NULL) {
2228 0 : return NT_STATUS_USER_SESSION_DELETED;
2229 : }
2230 :
2231 1850604 : *si = state.session->global->auth_session_info;
2232 1850604 : return NT_STATUS_OK;
2233 : }
2234 :
2235 : /*
2236 : * In memory of get_valid_user_struct()
2237 : *
2238 : * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
2239 : * but it doesn't implement the state checks of
2240 : * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
2241 : * session wire-id of incoming SMB requests, it MUST only be used in later
2242 : * internal processing where the session wire-id has already been validated.
2243 : */
2244 32941 : NTSTATUS get_valid_smbXsrv_session(struct smbXsrv_client *client,
2245 : uint64_t session_wire_id,
2246 : struct smbXsrv_session **session)
2247 : {
2248 32941 : struct smbXsrv_session_table *table = client->session_table;
2249 784 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2250 32941 : struct smbXsrv_session_local_fetch_state state = {
2251 : .status = NT_STATUS_INTERNAL_ERROR,
2252 : };
2253 784 : TDB_DATA key;
2254 784 : NTSTATUS status;
2255 :
2256 32941 : if (session_wire_id == 0) {
2257 0 : return NT_STATUS_USER_SESSION_DELETED;
2258 : }
2259 :
2260 32941 : if (table == NULL) {
2261 : /* this might happen before the end of negprot */
2262 0 : return NT_STATUS_USER_SESSION_DELETED;
2263 : }
2264 :
2265 32941 : if (table->local.db_ctx == NULL) {
2266 0 : return NT_STATUS_INTERNAL_ERROR;
2267 : }
2268 :
2269 32941 : key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2270 :
2271 32941 : status = dbwrap_parse_record(table->local.db_ctx, key,
2272 : smbXsrv_session_local_fetch_parser,
2273 : &state);
2274 32941 : if (!NT_STATUS_IS_OK(status)) {
2275 0 : return status;
2276 : }
2277 32941 : if (!NT_STATUS_IS_OK(state.status)) {
2278 0 : return state.status;
2279 : }
2280 32941 : if (state.session->global->auth_session_info == NULL) {
2281 3043 : return NT_STATUS_USER_SESSION_DELETED;
2282 : }
2283 :
2284 29898 : *session = state.session;
2285 29898 : return NT_STATUS_OK;
2286 : }
2287 :
2288 26733 : NTSTATUS smb2srv_session_lookup_global(struct smbXsrv_client *client,
2289 : uint64_t session_wire_id,
2290 : TALLOC_CTX *mem_ctx,
2291 : struct smbXsrv_session **_session)
2292 : {
2293 26733 : TALLOC_CTX *frame = talloc_stackframe();
2294 26733 : struct smbXsrv_session_table *table = client->session_table;
2295 26733 : uint32_t global_id = session_wire_id & UINT32_MAX;
2296 26733 : uint64_t global_zeros = session_wire_id & 0xFFFFFFFF00000000LLU;
2297 26733 : struct smbXsrv_session *session = NULL;
2298 26733 : struct db_record *global_rec = NULL;
2299 26733 : bool is_free = false;
2300 856 : NTSTATUS status;
2301 :
2302 26733 : if (global_id == 0) {
2303 25566 : TALLOC_FREE(frame);
2304 25566 : return NT_STATUS_USER_SESSION_DELETED;
2305 : }
2306 1167 : if (global_zeros != 0) {
2307 0 : TALLOC_FREE(frame);
2308 0 : return NT_STATUS_USER_SESSION_DELETED;
2309 : }
2310 :
2311 1167 : if (table == NULL) {
2312 : /* this might happen before the end of negprot */
2313 0 : TALLOC_FREE(frame);
2314 0 : return NT_STATUS_USER_SESSION_DELETED;
2315 : }
2316 :
2317 1167 : if (table->global.db_ctx == NULL) {
2318 0 : TALLOC_FREE(frame);
2319 0 : return NT_STATUS_INTERNAL_ERROR;
2320 : }
2321 :
2322 1167 : session = talloc_zero(mem_ctx, struct smbXsrv_session);
2323 1167 : if (session == NULL) {
2324 0 : TALLOC_FREE(frame);
2325 0 : return NT_STATUS_NO_MEMORY;
2326 : }
2327 1167 : talloc_steal(frame, session);
2328 :
2329 1167 : session->client = client;
2330 1167 : session->status = NT_STATUS_BAD_LOGON_SESSION_STATE;
2331 1167 : session->local_id = global_id;
2332 :
2333 : /*
2334 : * This means smb2_get_new_nonce() will return
2335 : * NT_STATUS_ENCRYPTION_FAILED.
2336 : *
2337 : * But we initialize some random parts just in case...
2338 : */
2339 1167 : session->nonce_high_max = session->nonce_high = 0;
2340 1167 : generate_nonce_buffer((uint8_t *)&session->nonce_high_random,
2341 : sizeof(session->nonce_high_random));
2342 1167 : generate_nonce_buffer((uint8_t *)&session->nonce_low,
2343 : sizeof(session->nonce_low));
2344 :
2345 1167 : global_rec = smbXsrv_session_global_fetch_locked(table->global.db_ctx,
2346 : global_id,
2347 : frame);
2348 1167 : if (global_rec == NULL) {
2349 0 : TALLOC_FREE(frame);
2350 0 : return NT_STATUS_INTERNAL_DB_ERROR;
2351 : }
2352 :
2353 1167 : smbXsrv_session_global_verify_record(global_rec,
2354 : &is_free,
2355 : NULL,
2356 : session,
2357 1167 : &session->global,
2358 : NULL);
2359 1167 : if (is_free) {
2360 10 : TALLOC_FREE(frame);
2361 10 : return NT_STATUS_USER_SESSION_DELETED;
2362 : }
2363 :
2364 : /*
2365 : * We don't have channels on this session
2366 : * and only the main signing key
2367 : */
2368 1157 : session->global->num_channels = 0;
2369 1362 : status = smb2_signing_key_sign_create(session->global,
2370 1157 : session->global->signing_algo,
2371 : NULL, /* no master key */
2372 : NULL, /* derivations */
2373 952 : &session->global->signing_key);
2374 1157 : if (!NT_STATUS_IS_OK(status)) {
2375 0 : TALLOC_FREE(frame);
2376 0 : return NT_STATUS_NO_MEMORY;
2377 : }
2378 1157 : session->global->signing_key->blob = session->global->signing_key_blob;
2379 1157 : session->global->signing_flags = 0;
2380 :
2381 1362 : status = smb2_signing_key_cipher_create(session->global,
2382 1157 : session->global->encryption_cipher,
2383 : NULL, /* no master key */
2384 : NULL, /* derivations */
2385 952 : &session->global->decryption_key);
2386 1157 : if (!NT_STATUS_IS_OK(status)) {
2387 0 : TALLOC_FREE(frame);
2388 0 : return NT_STATUS_NO_MEMORY;
2389 : }
2390 1157 : session->global->decryption_key->blob = session->global->decryption_key_blob;
2391 1157 : session->global->encryption_flags = 0;
2392 :
2393 1157 : *_session = talloc_move(mem_ctx, &session);
2394 1157 : TALLOC_FREE(frame);
2395 1157 : return NT_STATUS_OK;
2396 : }
2397 :
2398 25438 : NTSTATUS smb2srv_session_table_init(struct smbXsrv_connection *conn)
2399 : {
2400 : /*
2401 : * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
2402 : */
2403 25438 : return smbXsrv_session_table_init(conn, 1, UINT32_MAX - 1,
2404 : UINT16_MAX - 1);
2405 : }
2406 :
2407 1497949 : static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
2408 : /* conn: optional */
2409 : struct smbXsrv_connection *conn,
2410 : uint64_t session_id, NTTIME now,
2411 : struct smbXsrv_session **session)
2412 : {
2413 1497949 : uint32_t local_id = session_id & UINT32_MAX;
2414 1497949 : uint64_t local_zeros = session_id & 0xFFFFFFFF00000000LLU;
2415 :
2416 1497949 : if (local_zeros != 0) {
2417 24 : return NT_STATUS_USER_SESSION_DELETED;
2418 : }
2419 :
2420 1497925 : return smbXsrv_session_local_lookup(table, conn, local_id, now,
2421 : session);
2422 : }
2423 :
2424 1450218 : NTSTATUS smb2srv_session_lookup_conn(struct smbXsrv_connection *conn,
2425 : uint64_t session_id, NTTIME now,
2426 : struct smbXsrv_session **session)
2427 : {
2428 1450218 : struct smbXsrv_session_table *table = conn->client->session_table;
2429 1450218 : return smb2srv_session_lookup_raw(table, conn, session_id, now,
2430 : session);
2431 : }
2432 :
2433 47731 : NTSTATUS smb2srv_session_lookup_client(struct smbXsrv_client *client,
2434 : uint64_t session_id, NTTIME now,
2435 : struct smbXsrv_session **session)
2436 : {
2437 47731 : struct smbXsrv_session_table *table = client->session_table;
2438 47731 : return smb2srv_session_lookup_raw(table, NULL, session_id, now,
2439 : session);
2440 : }
2441 :
2442 : struct smbXsrv_session_global_traverse_state {
2443 : int (*fn)(struct smbXsrv_session_global0 *, void *);
2444 : void *private_data;
2445 : };
2446 :
2447 46 : static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
2448 : {
2449 46 : int ret = -1;
2450 46 : struct smbXsrv_session_global_traverse_state *state =
2451 : (struct smbXsrv_session_global_traverse_state*)data;
2452 46 : TDB_DATA key = dbwrap_record_get_key(rec);
2453 46 : TDB_DATA val = dbwrap_record_get_value(rec);
2454 46 : DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
2455 0 : struct smbXsrv_session_globalB global_blob;
2456 0 : enum ndr_err_code ndr_err;
2457 46 : TALLOC_CTX *frame = talloc_stackframe();
2458 :
2459 46 : ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
2460 : (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
2461 46 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2462 0 : DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2463 : "key '%s' ndr_pull_struct_blob - %s\n",
2464 : tdb_data_dbg(key),
2465 : ndr_errstr(ndr_err));
2466 0 : goto done;
2467 : }
2468 :
2469 46 : if (global_blob.version != SMBXSRV_VERSION_0) {
2470 0 : DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2471 : "key '%s' unsupported version - %d\n",
2472 : tdb_data_dbg(key),
2473 : (int)global_blob.version);
2474 0 : goto done;
2475 : }
2476 :
2477 46 : if (global_blob.info.info0 == NULL) {
2478 0 : DBG_WARNING("Invalid record in smbXsrv_tcon_global.tdb:"
2479 : "key '%s' info0 NULL pointer\n",
2480 : tdb_data_dbg(key));
2481 0 : goto done;
2482 : }
2483 :
2484 46 : global_blob.info.info0->db_rec = rec;
2485 46 : ret = state->fn(global_blob.info.info0, state->private_data);
2486 46 : done:
2487 46 : TALLOC_FREE(frame);
2488 46 : return ret;
2489 : }
2490 :
2491 42 : NTSTATUS smbXsrv_session_global_traverse(
2492 : int (*fn)(struct smbXsrv_session_global0 *, void *),
2493 : void *private_data)
2494 : {
2495 :
2496 0 : NTSTATUS status;
2497 42 : int count = 0;
2498 42 : struct smbXsrv_session_global_traverse_state state = {
2499 : .fn = fn,
2500 : .private_data = private_data,
2501 : };
2502 :
2503 42 : become_root();
2504 42 : status = smbXsrv_session_global_init(NULL);
2505 42 : if (!NT_STATUS_IS_OK(status)) {
2506 0 : unbecome_root();
2507 0 : DBG_ERR("Failed to initialize session_global: %s\n",
2508 : nt_errstr(status));
2509 0 : return status;
2510 : }
2511 :
2512 42 : status = dbwrap_traverse_read(smbXsrv_session_global_db_ctx,
2513 : smbXsrv_session_global_traverse_fn,
2514 : &state,
2515 : &count);
2516 42 : unbecome_root();
2517 :
2518 42 : return status;
2519 : }
|