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