2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2011-2012
5 Copyright (C) Michael Adam 2012
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.
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.
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/>.
22 #include "system/filesys.h"
24 #include "lib/util/server_id.h"
25 #include "smbd/smbd.h"
26 #include "smbd/globals.h"
27 #include "dbwrap/dbwrap.h"
28 #include "dbwrap/dbwrap_rbt.h"
29 #include "dbwrap/dbwrap_open.h"
30 #include "dbwrap/dbwrap_watch.h"
33 #include "auth/gensec/gensec.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/security/security.h"
37 #include "lib/util/util_tdb.h"
38 #include "librpc/gen_ndr/ndr_smbXsrv.h"
40 #include "lib/util/tevent_ntstatus.h"
41 #include "lib/global_contexts.h"
43 struct smbXsrv_session_table
{
45 struct db_context
*db_ctx
;
48 uint32_t max_sessions
;
49 uint32_t num_sessions
;
52 struct db_context
*db_ctx
;
56 static struct db_context
*smbXsrv_session_global_db_ctx
= NULL
;
58 NTSTATUS
smbXsrv_session_global_init(struct messaging_context
*msg_ctx
)
60 char *global_path
= NULL
;
61 struct db_context
*backend
= NULL
;
62 struct db_context
*db_ctx
= NULL
;
64 if (smbXsrv_session_global_db_ctx
!= NULL
) {
69 * This contains secret information like session keys!
71 global_path
= lock_path(talloc_tos(), "smbXsrv_session_global.tdb");
72 if (global_path
== NULL
) {
73 return NT_STATUS_NO_MEMORY
;
76 backend
= db_open(NULL
, global_path
,
80 TDB_INCOMPATIBLE_HASH
,
81 O_RDWR
| O_CREAT
, 0600,
84 TALLOC_FREE(global_path
);
85 if (backend
== NULL
) {
88 status
= map_nt_error_from_unix_common(errno
);
93 db_ctx
= db_open_watched(NULL
, &backend
, global_messaging_context());
96 return NT_STATUS_NO_MEMORY
;
99 smbXsrv_session_global_db_ctx
= db_ctx
;
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
110 * TODO: implement string based key
113 #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
115 static TDB_DATA
smbXsrv_session_global_id_to_key(uint32_t id
,
120 RSIVAL(key_buf
, 0, id
);
122 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
);
128 static NTSTATUS
smbXsrv_session_global_key_to_id(TDB_DATA key
, uint32_t *id
)
131 return NT_STATUS_INVALID_PARAMETER
;
134 if (key
.dsize
!= SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
) {
135 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
138 *id
= RIVAL(key
.dptr
, 0);
144 #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
146 static TDB_DATA
smbXsrv_session_local_id_to_key(uint32_t id
,
151 RSIVAL(key_buf
, 0, id
);
153 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
);
158 static NTSTATUS
smbXsrv_session_local_key_to_id(TDB_DATA key
, uint32_t *id
)
161 return NT_STATUS_INVALID_PARAMETER
;
164 if (key
.dsize
!= SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
) {
165 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
168 *id
= RIVAL(key
.dptr
, 0);
173 static struct db_record
*smbXsrv_session_global_fetch_locked(
174 struct db_context
*db
,
179 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
180 struct db_record
*rec
= NULL
;
182 key
= smbXsrv_session_global_id_to_key(id
, key_buf
);
184 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
187 DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id
,
188 hex_encode_talloc(talloc_tos(), key
.dptr
, key
.dsize
));
194 static struct db_record
*smbXsrv_session_local_fetch_locked(
195 struct db_context
*db
,
200 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
201 struct db_record
*rec
= NULL
;
203 key
= smbXsrv_session_local_id_to_key(id
, key_buf
);
205 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
208 DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id
,
209 hex_encode_talloc(talloc_tos(), key
.dptr
, key
.dsize
));
215 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
);
217 static NTSTATUS
smbXsrv_session_table_init(struct smbXsrv_connection
*conn
,
220 uint32_t max_sessions
)
222 struct smbXsrv_client
*client
= conn
->client
;
223 struct smbXsrv_session_table
*table
;
225 struct tevent_req
*subreq
;
228 if (lowest_id
> highest_id
) {
229 return NT_STATUS_INTERNAL_ERROR
;
232 max_range
= highest_id
;
233 max_range
-= lowest_id
;
236 if (max_sessions
> max_range
) {
237 return NT_STATUS_INTERNAL_ERROR
;
240 table
= talloc_zero(client
, struct smbXsrv_session_table
);
242 return NT_STATUS_NO_MEMORY
;
245 table
->local
.db_ctx
= db_open_rbt(table
);
246 if (table
->local
.db_ctx
== NULL
) {
248 return NT_STATUS_NO_MEMORY
;
250 table
->local
.lowest_id
= lowest_id
;
251 table
->local
.highest_id
= highest_id
;
252 table
->local
.max_sessions
= max_sessions
;
254 status
= smbXsrv_session_global_init(client
->msg_ctx
);
255 if (!NT_STATUS_IS_OK(status
)) {
260 table
->global
.db_ctx
= smbXsrv_session_global_db_ctx
;
262 subreq
= messaging_read_send(table
,
265 MSG_SMBXSRV_SESSION_CLOSE
);
266 if (subreq
== NULL
) {
268 return NT_STATUS_NO_MEMORY
;
270 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
272 client
->session_table
= table
;
276 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
);
278 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
)
280 struct smbXsrv_client
*client
=
281 tevent_req_callback_data(subreq
,
282 struct smbXsrv_client
);
283 struct smbXsrv_session_table
*table
= client
->session_table
;
285 struct messaging_rec
*rec
= NULL
;
286 struct smbXsrv_session_closeB close_blob
;
287 enum ndr_err_code ndr_err
;
288 struct smbXsrv_session_close0
*close_info0
= NULL
;
289 struct smbXsrv_session
*session
= NULL
;
291 struct timeval tv
= timeval_current();
292 NTTIME now
= timeval_to_nttime(&tv
);
294 ret
= messaging_read_recv(subreq
, talloc_tos(), &rec
);
300 ndr_err
= ndr_pull_struct_blob(&rec
->buf
, rec
, &close_blob
,
301 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_closeB
);
302 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
303 status
= ndr_map_error2ntstatus(ndr_err
);
304 DEBUG(1,("smbXsrv_session_close_loop: "
305 "ndr_pull_struct_blob - %s\n",
310 DEBUG(10,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
312 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
315 if (close_blob
.version
!= SMBXSRV_VERSION_0
) {
316 DEBUG(0,("smbXsrv_session_close_loop: "
317 "ignore invalid version %u\n", close_blob
.version
));
318 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
322 close_info0
= close_blob
.info
.info0
;
323 if (close_info0
== NULL
) {
324 DEBUG(0,("smbXsrv_session_close_loop: "
325 "ignore NULL info %u\n", close_blob
.version
));
326 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
330 status
= smb2srv_session_lookup_client(client
,
331 close_info0
->old_session_wire_id
,
333 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_SESSION_DELETED
)) {
334 DEBUG(4,("smbXsrv_session_close_loop: "
335 "old_session_wire_id %llu not found\n",
336 (unsigned long long)close_info0
->old_session_wire_id
));
338 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
342 if (!NT_STATUS_IS_OK(status
) &&
343 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
344 !NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
345 DEBUG(1,("smbXsrv_session_close_loop: "
346 "old_session_wire_id %llu - %s\n",
347 (unsigned long long)close_info0
->old_session_wire_id
,
350 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
355 if (session
->global
->session_global_id
!= close_info0
->old_session_global_id
) {
356 DEBUG(1,("smbXsrv_session_close_loop: "
357 "old_session_wire_id %llu - global %u != %u\n",
358 (unsigned long long)close_info0
->old_session_wire_id
,
359 session
->global
->session_global_id
,
360 close_info0
->old_session_global_id
));
362 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
367 if (session
->global
->creation_time
!= close_info0
->old_creation_time
) {
368 DEBUG(1,("smbXsrv_session_close_loop: "
369 "old_session_wire_id %llu - "
370 "creation %s (%llu) != %s (%llu)\n",
371 (unsigned long long)close_info0
->old_session_wire_id
,
372 nt_time_string(rec
, session
->global
->creation_time
),
373 (unsigned long long)session
->global
->creation_time
,
374 nt_time_string(rec
, close_info0
->old_creation_time
),
375 (unsigned long long)close_info0
->old_creation_time
));
377 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
382 subreq
= smb2srv_session_shutdown_send(session
, client
->raw_ev_ctx
,
384 if (subreq
== NULL
) {
385 status
= NT_STATUS_NO_MEMORY
;
386 DEBUG(0, ("smbXsrv_session_close_loop: "
387 "smb2srv_session_shutdown_send(%llu) failed: %s\n",
388 (unsigned long long)session
->global
->session_wire_id
,
391 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
395 tevent_req_set_callback(subreq
,
396 smbXsrv_session_close_shutdown_done
,
402 subreq
= messaging_read_send(table
,
405 MSG_SMBXSRV_SESSION_CLOSE
);
406 if (subreq
== NULL
) {
408 r
= "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
409 exit_server_cleanly(r
);
412 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
415 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
)
417 struct smbXsrv_session
*session
=
418 tevent_req_callback_data(subreq
,
419 struct smbXsrv_session
);
422 status
= smb2srv_session_shutdown_recv(subreq
);
424 if (!NT_STATUS_IS_OK(status
)) {
425 DEBUG(0, ("smbXsrv_session_close_loop: "
426 "smb2srv_session_shutdown_recv(%llu) failed: %s\n",
427 (unsigned long long)session
->global
->session_wire_id
,
431 status
= smbXsrv_session_logoff(session
);
432 if (!NT_STATUS_IS_OK(status
)) {
433 DEBUG(0, ("smbXsrv_session_close_loop: "
434 "smbXsrv_session_logoff(%llu) failed: %s\n",
435 (unsigned long long)session
->global
->session_wire_id
,
439 TALLOC_FREE(session
);
442 struct smb1srv_session_local_allocate_state
{
443 const uint32_t lowest_id
;
444 const uint32_t highest_id
;
450 static int smb1srv_session_local_allocate_traverse(struct db_record
*rec
,
453 struct smb1srv_session_local_allocate_state
*state
=
454 (struct smb1srv_session_local_allocate_state
*)private_data
;
455 TDB_DATA key
= dbwrap_record_get_key(rec
);
459 status
= smbXsrv_session_local_key_to_id(key
, &id
);
460 if (!NT_STATUS_IS_OK(status
)) {
461 state
->status
= status
;
465 if (id
<= state
->last_id
) {
466 state
->status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
471 if (id
> state
->useable_id
) {
472 state
->status
= NT_STATUS_OK
;
476 if (state
->useable_id
== state
->highest_id
) {
477 state
->status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
481 state
->useable_id
+=1;
485 static NTSTATUS
smb1srv_session_local_allocate_id(struct db_context
*db
,
489 struct db_record
**_rec
,
492 struct smb1srv_session_local_allocate_state state
= {
493 .lowest_id
= lowest_id
,
494 .highest_id
= highest_id
,
496 .useable_id
= lowest_id
,
497 .status
= NT_STATUS_INTERNAL_ERROR
,
507 if (lowest_id
> highest_id
) {
508 return NT_STATUS_INSUFFICIENT_RESOURCES
;
512 * first we try randomly
514 range
= (highest_id
- lowest_id
) + 1;
516 for (i
= 0; i
< (range
/ 2); i
++) {
519 struct db_record
*rec
= NULL
;
521 id
= generate_random() % range
;
524 if (id
< lowest_id
) {
527 if (id
> highest_id
) {
531 rec
= smbXsrv_session_local_fetch_locked(db
, id
, mem_ctx
);
533 return NT_STATUS_INSUFFICIENT_RESOURCES
;
536 val
= dbwrap_record_get_value(rec
);
537 if (val
.dsize
!= 0) {
548 * if the range is almost full,
549 * we traverse the whole table
550 * (this relies on sorted behavior of dbwrap_rbt)
552 status
= dbwrap_traverse_read(db
, smb1srv_session_local_allocate_traverse
,
554 if (NT_STATUS_IS_OK(status
)) {
555 if (NT_STATUS_IS_OK(state
.status
)) {
556 return NT_STATUS_INTERNAL_ERROR
;
559 if (!NT_STATUS_EQUAL(state
.status
, NT_STATUS_INTERNAL_ERROR
)) {
563 if (state
.useable_id
<= state
.highest_id
) {
564 state
.status
= NT_STATUS_OK
;
566 return NT_STATUS_INSUFFICIENT_RESOURCES
;
568 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_INTERNAL_DB_CORRUPTION
)) {
570 * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
572 * If we get anything else it is an error, because it
573 * means we did not manage to find a free slot in
576 return NT_STATUS_INSUFFICIENT_RESOURCES
;
579 if (NT_STATUS_IS_OK(state
.status
)) {
582 struct db_record
*rec
= NULL
;
584 id
= state
.useable_id
;
586 rec
= smbXsrv_session_local_fetch_locked(db
, id
, mem_ctx
);
588 return NT_STATUS_INSUFFICIENT_RESOURCES
;
591 val
= dbwrap_record_get_value(rec
);
592 if (val
.dsize
!= 0) {
594 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
605 struct smbXsrv_session_local_fetch_state
{
606 struct smbXsrv_session
*session
;
610 static void smbXsrv_session_local_fetch_parser(TDB_DATA key
, TDB_DATA data
,
613 struct smbXsrv_session_local_fetch_state
*state
=
614 (struct smbXsrv_session_local_fetch_state
*)private_data
;
617 if (data
.dsize
!= sizeof(ptr
)) {
618 state
->status
= NT_STATUS_INTERNAL_DB_ERROR
;
622 memcpy(&ptr
, data
.dptr
, data
.dsize
);
623 state
->session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
624 state
->status
= NT_STATUS_OK
;
627 static NTSTATUS
smbXsrv_session_local_lookup(struct smbXsrv_session_table
*table
,
629 struct smbXsrv_connection
*conn
,
630 uint32_t session_local_id
,
632 struct smbXsrv_session
**_session
)
634 struct smbXsrv_session_local_fetch_state state
= {
636 .status
= NT_STATUS_INTERNAL_ERROR
,
638 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
644 if (session_local_id
== 0) {
645 return NT_STATUS_USER_SESSION_DELETED
;
649 /* this might happen before the end of negprot */
650 return NT_STATUS_USER_SESSION_DELETED
;
653 if (table
->local
.db_ctx
== NULL
) {
654 return NT_STATUS_INTERNAL_ERROR
;
657 key
= smbXsrv_session_local_id_to_key(session_local_id
, key_buf
);
659 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
660 smbXsrv_session_local_fetch_parser
,
662 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
663 return NT_STATUS_USER_SESSION_DELETED
;
664 } else if (!NT_STATUS_IS_OK(status
)) {
667 if (!NT_STATUS_IS_OK(state
.status
)) {
671 if (NT_STATUS_EQUAL(state
.session
->status
, NT_STATUS_USER_SESSION_DELETED
)) {
672 return NT_STATUS_USER_SESSION_DELETED
;
676 * If a connection is specified check if the session is
677 * valid on the channel.
680 struct smbXsrv_channel_global0
*c
= NULL
;
682 status
= smbXsrv_session_find_channel(state
.session
, conn
, &c
);
683 if (!NT_STATUS_IS_OK(status
)) {
688 state
.session
->idle_time
= now
;
690 if (!NT_STATUS_IS_OK(state
.session
->status
)) {
691 *_session
= state
.session
;
692 return state
.session
->status
;
695 if (now
> state
.session
->global
->expiration_time
) {
696 state
.session
->status
= NT_STATUS_NETWORK_SESSION_EXPIRED
;
699 *_session
= state
.session
;
700 return state
.session
->status
;
703 static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0
*global
)
708 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
712 struct smbXsrv_session_global0
**_g
,
715 static NTSTATUS
smbXsrv_session_global_allocate(struct db_context
*db
,
717 struct smbXsrv_session_global0
**_global
)
720 struct smbXsrv_session_global0
*global
= NULL
;
721 uint32_t last_free
= 0;
722 const uint32_t min_tries
= 3;
726 global
= talloc_zero(mem_ctx
, struct smbXsrv_session_global0
);
727 if (global
== NULL
) {
728 return NT_STATUS_NO_MEMORY
;
730 talloc_set_destructor(global
, smbXsrv_session_global_destructor
);
733 * Here we just randomly try the whole 32-bit space
735 * We use just 32-bit, because we want to reuse the
738 for (i
= 0; i
< UINT32_MAX
; i
++) {
739 bool is_free
= false;
740 bool was_free
= false;
743 if (i
>= min_tries
&& last_free
!= 0) {
746 id
= generate_random();
751 if (id
== UINT32_MAX
) {
755 global
->db_rec
= smbXsrv_session_global_fetch_locked(db
, id
,
757 if (global
->db_rec
== NULL
) {
759 return NT_STATUS_INSUFFICIENT_RESOURCES
;
762 smbXsrv_session_global_verify_record(global
->db_rec
,
768 TALLOC_FREE(global
->db_rec
);
772 if (!was_free
&& i
< min_tries
) {
774 * The session_id is free now,
775 * but was not free before.
777 * This happens if a smbd crashed
778 * and did not cleanup the record.
780 * If this is one of our first tries,
781 * then we try to find a real free one.
783 if (last_free
== 0) {
786 TALLOC_FREE(global
->db_rec
);
790 global
->session_global_id
= id
;
796 /* should not be reached */
798 return NT_STATUS_INTERNAL_ERROR
;
801 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
805 struct smbXsrv_session_global0
**_g
,
811 struct smbXsrv_session_globalB global_blob
;
812 enum ndr_err_code ndr_err
;
813 struct smbXsrv_session_global0
*global
= NULL
;
815 TALLOC_CTX
*frame
= talloc_stackframe();
829 key
= dbwrap_record_get_key(db_rec
);
831 val
= dbwrap_record_get_value(db_rec
);
832 if (val
.dsize
== 0) {
841 blob
= data_blob_const(val
.dptr
, val
.dsize
);
843 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
844 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
845 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
846 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
847 DEBUG(1,("smbXsrv_session_global_verify_record: "
848 "key '%s' ndr_pull_struct_blob - %s\n",
849 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
859 DEBUG(10,("smbXsrv_session_global_verify_record\n"));
861 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
864 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
865 DEBUG(0,("smbXsrv_session_global_verify_record: "
866 "key '%s' use unsupported version %u\n",
867 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
868 global_blob
.version
));
869 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
878 global
= global_blob
.info
.info0
;
880 #define __BLOB_KEEP_SECRET(__blob) do { \
881 if ((__blob).length != 0) { \
882 talloc_keep_secret((__blob).data); \
887 __BLOB_KEEP_SECRET(global
->application_key_blob
);
888 __BLOB_KEEP_SECRET(global
->signing_key_blob
);
889 __BLOB_KEEP_SECRET(global
->encryption_key_blob
);
890 __BLOB_KEEP_SECRET(global
->decryption_key_blob
);
891 for (i
= 0; i
< global
->num_channels
; i
++) {
892 __BLOB_KEEP_SECRET(global
->channels
[i
].signing_key_blob
);
895 #undef __BLOB_KEEP_SECRET
897 exists
= serverid_exists(&global
->channels
[0].server_id
);
899 struct server_id_buf idbuf
;
900 DEBUG(2,("smbXsrv_session_global_verify_record: "
901 "key '%s' server_id %s does not exist.\n",
902 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
903 server_id_str_buf(global
->channels
[0].server_id
,
906 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
909 dbwrap_record_delete(db_rec
);
915 *_g
= talloc_move(mem_ctx
, &global
);
918 *pseqnum
= global_blob
.seqnum
;
923 static NTSTATUS
smbXsrv_session_global_store(struct smbXsrv_session_global0
*global
)
925 struct smbXsrv_session_globalB global_blob
;
926 DATA_BLOB blob
= data_blob_null
;
930 enum ndr_err_code ndr_err
;
933 * TODO: if we use other versions than '0'
934 * we would add glue code here, that would be able to
935 * store the information in the old format.
938 if (global
->db_rec
== NULL
) {
939 return NT_STATUS_INTERNAL_ERROR
;
942 key
= dbwrap_record_get_key(global
->db_rec
);
943 val
= dbwrap_record_get_value(global
->db_rec
);
945 ZERO_STRUCT(global_blob
);
946 global_blob
.version
= smbXsrv_version_global_current();
947 if (val
.dsize
>= 8) {
948 global_blob
.seqnum
= IVAL(val
.dptr
, 4);
950 global_blob
.seqnum
+= 1;
951 global_blob
.info
.info0
= global
;
953 ndr_err
= ndr_push_struct_blob(&blob
, global
->db_rec
, &global_blob
,
954 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_globalB
);
955 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
956 status
= ndr_map_error2ntstatus(ndr_err
);
957 DEBUG(1,("smbXsrv_session_global_store: key '%s' ndr_push - %s\n",
958 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
960 TALLOC_FREE(global
->db_rec
);
964 val
= make_tdb_data(blob
.data
, blob
.length
);
965 status
= dbwrap_record_store(global
->db_rec
, val
, TDB_REPLACE
);
966 if (!NT_STATUS_IS_OK(status
)) {
967 DEBUG(1,("smbXsrv_session_global_store: key '%s' store - %s\n",
968 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
970 TALLOC_FREE(global
->db_rec
);
975 DEBUG(10,("smbXsrv_session_global_store: key '%s' stored\n",
976 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
)));
977 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
980 TALLOC_FREE(global
->db_rec
);
985 struct smb2srv_session_close_previous_state
{
986 struct tevent_context
*ev
;
987 struct smbXsrv_connection
*connection
;
988 struct dom_sid
*current_sid
;
989 uint64_t previous_session_id
;
990 uint64_t current_session_id
;
991 struct db_record
*db_rec
;
992 uint64_t watch_instance
;
993 uint32_t last_seqnum
;
996 static void smb2srv_session_close_previous_cleanup(struct tevent_req
*req
,
997 enum tevent_req_state req_state
)
999 struct smb2srv_session_close_previous_state
*state
=
1000 tevent_req_data(req
,
1001 struct smb2srv_session_close_previous_state
);
1003 if (state
->db_rec
!= NULL
) {
1004 dbwrap_watched_watch_remove_instance(state
->db_rec
,
1005 state
->watch_instance
);
1006 state
->watch_instance
= 0;
1007 TALLOC_FREE(state
->db_rec
);
1011 static void smb2srv_session_close_previous_check(struct tevent_req
*req
);
1012 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
);
1014 struct tevent_req
*smb2srv_session_close_previous_send(TALLOC_CTX
*mem_ctx
,
1015 struct tevent_context
*ev
,
1016 struct smbXsrv_connection
*conn
,
1017 struct auth_session_info
*session_info
,
1018 uint64_t previous_session_id
,
1019 uint64_t current_session_id
)
1021 struct tevent_req
*req
;
1022 struct smb2srv_session_close_previous_state
*state
;
1023 uint32_t global_id
= previous_session_id
& UINT32_MAX
;
1024 uint64_t global_zeros
= previous_session_id
& 0xFFFFFFFF00000000LLU
;
1025 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1026 struct security_token
*current_token
= NULL
;
1028 req
= tevent_req_create(mem_ctx
, &state
,
1029 struct smb2srv_session_close_previous_state
);
1034 state
->connection
= conn
;
1035 state
->previous_session_id
= previous_session_id
;
1036 state
->current_session_id
= current_session_id
;
1038 tevent_req_set_cleanup_fn(req
, smb2srv_session_close_previous_cleanup
);
1040 if (global_zeros
!= 0) {
1041 tevent_req_done(req
);
1042 return tevent_req_post(req
, ev
);
1045 if (session_info
== NULL
) {
1046 tevent_req_done(req
);
1047 return tevent_req_post(req
, ev
);
1049 current_token
= session_info
->security_token
;
1051 if (current_token
->num_sids
> PRIMARY_USER_SID_INDEX
) {
1052 state
->current_sid
= ¤t_token
->sids
[PRIMARY_USER_SID_INDEX
];
1055 if (state
->current_sid
== NULL
) {
1056 tevent_req_done(req
);
1057 return tevent_req_post(req
, ev
);
1060 if (!security_token_has_nt_authenticated_users(current_token
)) {
1062 tevent_req_done(req
);
1063 return tevent_req_post(req
, ev
);
1066 state
->db_rec
= smbXsrv_session_global_fetch_locked(
1067 table
->global
.db_ctx
,
1069 state
/* TALLOC_CTX */);
1070 if (state
->db_rec
== NULL
) {
1071 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1072 return tevent_req_post(req
, ev
);
1075 smb2srv_session_close_previous_check(req
);
1076 if (!tevent_req_is_in_progress(req
)) {
1077 return tevent_req_post(req
, ev
);
1083 static void smb2srv_session_close_previous_check(struct tevent_req
*req
)
1085 struct smb2srv_session_close_previous_state
*state
=
1086 tevent_req_data(req
,
1087 struct smb2srv_session_close_previous_state
);
1088 struct smbXsrv_connection
*conn
= state
->connection
;
1090 struct security_token
*previous_token
= NULL
;
1091 struct smbXsrv_session_global0
*global
= NULL
;
1092 enum ndr_err_code ndr_err
;
1093 struct smbXsrv_session_close0 close_info0
;
1094 struct smbXsrv_session_closeB close_blob
;
1095 struct tevent_req
*subreq
= NULL
;
1097 bool is_free
= false;
1098 uint32_t seqnum
= 0;
1100 smbXsrv_session_global_verify_record(state
->db_rec
,
1108 tevent_req_done(req
);
1112 if (global
->auth_session_info
== NULL
) {
1113 tevent_req_done(req
);
1117 previous_token
= global
->auth_session_info
->security_token
;
1119 if (!security_token_is_sid(previous_token
, state
->current_sid
)) {
1120 tevent_req_done(req
);
1125 * If the record changed, but we are not happy with the change yet,
1126 * we better remove ourself from the waiter list
1127 * (most likely the first position)
1128 * and re-add us at the end of the list.
1130 * This gives other waiters a change
1133 * Otherwise we'll keep our waiter instance alive,
1134 * keep waiting (most likely at first position).
1135 * It means the order of watchers stays fair.
1137 if (state
->last_seqnum
!= seqnum
) {
1138 state
->last_seqnum
= seqnum
;
1139 dbwrap_watched_watch_remove_instance(state
->db_rec
,
1140 state
->watch_instance
);
1141 state
->watch_instance
=
1142 dbwrap_watched_watch_add_instance(state
->db_rec
);
1145 subreq
= dbwrap_watched_watch_send(state
, state
->ev
, state
->db_rec
,
1146 state
->watch_instance
,
1147 (struct server_id
){0});
1148 if (tevent_req_nomem(subreq
, req
)) {
1151 tevent_req_set_callback(subreq
,
1152 smb2srv_session_close_previous_modified
,
1155 close_info0
.old_session_global_id
= global
->session_global_id
;
1156 close_info0
.old_session_wire_id
= global
->session_wire_id
;
1157 close_info0
.old_creation_time
= global
->creation_time
;
1158 close_info0
.new_session_wire_id
= state
->current_session_id
;
1160 ZERO_STRUCT(close_blob
);
1161 close_blob
.version
= smbXsrv_version_global_current();
1162 close_blob
.info
.info0
= &close_info0
;
1164 ndr_err
= ndr_push_struct_blob(&blob
, state
, &close_blob
,
1165 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_closeB
);
1166 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1167 status
= ndr_map_error2ntstatus(ndr_err
);
1168 DEBUG(1,("smb2srv_session_close_previous_check: "
1169 "old_session[%llu] new_session[%llu] ndr_push - %s\n",
1170 (unsigned long long)close_info0
.old_session_wire_id
,
1171 (unsigned long long)close_info0
.new_session_wire_id
,
1172 nt_errstr(status
)));
1173 tevent_req_nterror(req
, status
);
1177 status
= messaging_send(conn
->client
->msg_ctx
,
1178 global
->channels
[0].server_id
,
1179 MSG_SMBXSRV_SESSION_CLOSE
, &blob
);
1180 TALLOC_FREE(global
);
1181 if (tevent_req_nterror(req
, status
)) {
1185 TALLOC_FREE(state
->db_rec
);
1189 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
)
1191 struct tevent_req
*req
=
1192 tevent_req_callback_data(subreq
,
1194 struct smb2srv_session_close_previous_state
*state
=
1195 tevent_req_data(req
,
1196 struct smb2srv_session_close_previous_state
);
1199 uint64_t instance
= 0;
1201 status
= dbwrap_watched_watch_recv(subreq
, &instance
, NULL
, NULL
);
1202 TALLOC_FREE(subreq
);
1203 if (tevent_req_nterror(req
, status
)) {
1207 state
->watch_instance
= instance
;
1209 global_id
= state
->previous_session_id
& UINT32_MAX
;
1211 state
->db_rec
= smbXsrv_session_global_fetch_locked(
1212 state
->connection
->client
->session_table
->global
.db_ctx
,
1213 global_id
, state
/* TALLOC_CTX */);
1214 if (state
->db_rec
== NULL
) {
1215 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1219 smb2srv_session_close_previous_check(req
);
1222 NTSTATUS
smb2srv_session_close_previous_recv(struct tevent_req
*req
)
1226 if (tevent_req_is_nterror(req
, &status
)) {
1227 tevent_req_received(req
);
1231 tevent_req_received(req
);
1232 return NT_STATUS_OK
;
1235 static NTSTATUS
smbXsrv_session_clear_and_logoff(struct smbXsrv_session
*session
)
1238 struct smbXsrv_connection
*xconn
= NULL
;
1240 if (session
->client
!= NULL
) {
1241 xconn
= session
->client
->connections
;
1244 for (; xconn
!= NULL
; xconn
= xconn
->next
) {
1245 struct smbd_smb2_request
*preq
;
1247 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1248 if (preq
->session
!= session
) {
1252 preq
->session
= NULL
;
1254 * If we no longer have a session we can't
1255 * sign or encrypt replies.
1257 preq
->do_signing
= false;
1258 preq
->do_encryption
= false;
1259 preq
->preauth
= NULL
;
1263 status
= smbXsrv_session_logoff(session
);
1267 static int smbXsrv_session_destructor(struct smbXsrv_session
*session
)
1271 DBG_DEBUG("destructing session(%llu)\n",
1272 (unsigned long long)session
->global
->session_wire_id
);
1274 status
= smbXsrv_session_clear_and_logoff(session
);
1275 if (!NT_STATUS_IS_OK(status
)) {
1276 DEBUG(0, ("smbXsrv_session_destructor: "
1277 "smbXsrv_session_logoff() failed: %s\n",
1278 nt_errstr(status
)));
1281 TALLOC_FREE(session
->global
);
1286 NTSTATUS
smbXsrv_session_create(struct smbXsrv_connection
*conn
,
1288 struct smbXsrv_session
**_session
)
1290 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1291 struct db_record
*local_rec
= NULL
;
1292 struct smbXsrv_session
*session
= NULL
;
1295 struct smbXsrv_session_global0
*global
= NULL
;
1296 struct smbXsrv_channel_global0
*channel
= NULL
;
1299 if (table
->local
.num_sessions
>= table
->local
.max_sessions
) {
1300 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1303 session
= talloc_zero(table
, struct smbXsrv_session
);
1304 if (session
== NULL
) {
1305 return NT_STATUS_NO_MEMORY
;
1307 session
->table
= table
;
1308 session
->idle_time
= now
;
1309 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
1310 session
->client
= conn
->client
;
1311 session
->homes_snum
= -1;
1313 status
= smbXsrv_session_global_allocate(table
->global
.db_ctx
,
1316 if (!NT_STATUS_IS_OK(status
)) {
1317 TALLOC_FREE(session
);
1320 session
->global
= global
;
1322 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1323 uint64_t id
= global
->session_global_id
;
1325 global
->connection_dialect
= conn
->smb2
.server
.dialect
;
1327 global
->session_wire_id
= id
;
1329 status
= smb2srv_tcon_table_init(session
);
1330 if (!NT_STATUS_IS_OK(status
)) {
1331 TALLOC_FREE(session
);
1335 session
->local_id
= global
->session_global_id
;
1337 local_rec
= smbXsrv_session_local_fetch_locked(
1338 table
->local
.db_ctx
,
1340 session
/* TALLOC_CTX */);
1341 if (local_rec
== NULL
) {
1342 TALLOC_FREE(session
);
1343 return NT_STATUS_NO_MEMORY
;
1346 val
= dbwrap_record_get_value(local_rec
);
1347 if (val
.dsize
!= 0) {
1348 TALLOC_FREE(session
);
1349 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1353 status
= smb1srv_session_local_allocate_id(table
->local
.db_ctx
,
1354 table
->local
.lowest_id
,
1355 table
->local
.highest_id
,
1358 &session
->local_id
);
1359 if (!NT_STATUS_IS_OK(status
)) {
1360 TALLOC_FREE(session
);
1364 global
->session_wire_id
= session
->local_id
;
1367 global
->creation_time
= now
;
1368 global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1370 status
= smbXsrv_session_add_channel(session
, conn
, now
, &channel
);
1371 if (!NT_STATUS_IS_OK(status
)) {
1372 TALLOC_FREE(session
);
1377 val
= make_tdb_data((uint8_t const *)&ptr
, sizeof(ptr
));
1378 status
= dbwrap_record_store(local_rec
, val
, TDB_REPLACE
);
1379 TALLOC_FREE(local_rec
);
1380 if (!NT_STATUS_IS_OK(status
)) {
1381 TALLOC_FREE(session
);
1384 table
->local
.num_sessions
+= 1;
1386 talloc_set_destructor(session
, smbXsrv_session_destructor
);
1388 status
= smbXsrv_session_global_store(global
);
1389 if (!NT_STATUS_IS_OK(status
)) {
1390 DEBUG(0,("smbXsrv_session_create: "
1391 "global_id (0x%08x) store failed - %s\n",
1392 session
->global
->session_global_id
,
1393 nt_errstr(status
)));
1394 TALLOC_FREE(session
);
1399 struct smbXsrv_sessionB session_blob
= {
1400 .version
= SMBXSRV_VERSION_0
,
1401 .info
.info0
= session
,
1404 DEBUG(10,("smbXsrv_session_create: global_id (0x%08x) stored\n",
1405 session
->global
->session_global_id
));
1406 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1409 *_session
= session
;
1410 return NT_STATUS_OK
;
1413 NTSTATUS
smbXsrv_session_add_channel(struct smbXsrv_session
*session
,
1414 struct smbXsrv_connection
*conn
,
1416 struct smbXsrv_channel_global0
**_c
)
1418 struct smbXsrv_session_global0
*global
= session
->global
;
1419 struct smbXsrv_channel_global0
*c
= NULL
;
1421 if (global
->num_channels
> 31) {
1423 * Windows allow up to 32 channels
1425 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1428 c
= talloc_realloc(global
,
1430 struct smbXsrv_channel_global0
,
1431 global
->num_channels
+ 1);
1433 return NT_STATUS_NO_MEMORY
;
1435 global
->channels
= c
;
1437 c
= &global
->channels
[global
->num_channels
];
1440 c
->server_id
= messaging_server_id(conn
->client
->msg_ctx
);
1441 c
->channel_id
= conn
->channel_id
;
1442 c
->creation_time
= now
;
1443 c
->local_address
= tsocket_address_string(conn
->local_address
,
1445 if (c
->local_address
== NULL
) {
1446 return NT_STATUS_NO_MEMORY
;
1448 c
->remote_address
= tsocket_address_string(conn
->remote_address
,
1450 if (c
->remote_address
== NULL
) {
1451 return NT_STATUS_NO_MEMORY
;
1453 c
->remote_name
= talloc_strdup(global
->channels
,
1454 conn
->remote_hostname
);
1455 if (c
->remote_name
== NULL
) {
1456 return NT_STATUS_NO_MEMORY
;
1458 c
->connection
= conn
;
1460 global
->num_channels
+= 1;
1463 return NT_STATUS_OK
;
1466 NTSTATUS
smbXsrv_session_update(struct smbXsrv_session
*session
)
1468 struct smbXsrv_session_table
*table
= session
->table
;
1471 if (session
->global
->db_rec
!= NULL
) {
1472 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1473 "Called with db_rec != NULL'\n",
1474 session
->global
->session_global_id
));
1475 return NT_STATUS_INTERNAL_ERROR
;
1478 if (table
== NULL
) {
1479 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1480 "Called with table == NULL'\n",
1481 session
->global
->session_global_id
));
1482 return NT_STATUS_INTERNAL_ERROR
;
1485 session
->global
->db_rec
= smbXsrv_session_global_fetch_locked(
1486 table
->global
.db_ctx
,
1487 session
->global
->session_global_id
,
1488 session
->global
/* TALLOC_CTX */);
1489 if (session
->global
->db_rec
== NULL
) {
1490 return NT_STATUS_INTERNAL_DB_ERROR
;
1493 status
= smbXsrv_session_global_store(session
->global
);
1494 if (!NT_STATUS_IS_OK(status
)) {
1495 DEBUG(0,("smbXsrv_session_update: "
1496 "global_id (0x%08x) store failed - %s\n",
1497 session
->global
->session_global_id
,
1498 nt_errstr(status
)));
1503 struct smbXsrv_sessionB session_blob
= {
1504 .version
= SMBXSRV_VERSION_0
,
1505 .info
.info0
= session
,
1508 DEBUG(10,("smbXsrv_session_update: global_id (0x%08x) stored\n",
1509 session
->global
->session_global_id
));
1510 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1513 return NT_STATUS_OK
;
1516 NTSTATUS
smbXsrv_session_find_channel(const struct smbXsrv_session
*session
,
1517 const struct smbXsrv_connection
*conn
,
1518 struct smbXsrv_channel_global0
**_c
)
1522 for (i
=0; i
< session
->global
->num_channels
; i
++) {
1523 struct smbXsrv_channel_global0
*c
= &session
->global
->channels
[i
];
1525 if (c
->channel_id
!= conn
->channel_id
) {
1529 if (c
->connection
!= conn
) {
1534 return NT_STATUS_OK
;
1537 return NT_STATUS_USER_SESSION_DELETED
;
1540 NTSTATUS
smbXsrv_session_find_auth(const struct smbXsrv_session
*session
,
1541 const struct smbXsrv_connection
*conn
,
1543 struct smbXsrv_session_auth0
**_a
)
1545 struct smbXsrv_session_auth0
*a
;
1547 for (a
= session
->pending_auth
; a
!= NULL
; a
= a
->next
) {
1548 if (a
->channel_id
!= conn
->channel_id
) {
1552 if (a
->connection
== conn
) {
1557 return NT_STATUS_OK
;
1561 return NT_STATUS_USER_SESSION_DELETED
;
1564 static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0
*a
)
1566 if (a
->session
== NULL
) {
1570 DLIST_REMOVE(a
->session
->pending_auth
, a
);
1575 NTSTATUS
smbXsrv_session_create_auth(struct smbXsrv_session
*session
,
1576 struct smbXsrv_connection
*conn
,
1579 uint8_t in_security_mode
,
1580 struct smbXsrv_session_auth0
**_a
)
1582 struct smbXsrv_session_auth0
*a
;
1585 status
= smbXsrv_session_find_auth(session
, conn
, 0, &a
);
1586 if (NT_STATUS_IS_OK(status
)) {
1587 return NT_STATUS_INTERNAL_ERROR
;
1590 a
= talloc_zero(session
, struct smbXsrv_session_auth0
);
1592 return NT_STATUS_NO_MEMORY
;
1594 a
->session
= session
;
1595 a
->connection
= conn
;
1596 a
->in_flags
= in_flags
;
1597 a
->in_security_mode
= in_security_mode
;
1598 a
->creation_time
= now
;
1600 a
->channel_id
= conn
->channel_id
;
1602 if (conn
->protocol
>= PROTOCOL_SMB3_11
) {
1603 a
->preauth
= talloc(a
, struct smbXsrv_preauth
);
1604 if (a
->preauth
== NULL
) {
1605 TALLOC_FREE(session
);
1606 return NT_STATUS_NO_MEMORY
;
1608 *a
->preauth
= conn
->smb2
.preauth
;
1611 talloc_set_destructor(a
, smbXsrv_session_auth0_destructor
);
1612 DLIST_ADD_END(session
->pending_auth
, a
);
1615 return NT_STATUS_OK
;
1618 static void smbXsrv_session_remove_channel_done(struct tevent_req
*subreq
);
1620 NTSTATUS
smbXsrv_session_remove_channel(struct smbXsrv_session
*session
,
1621 struct smbXsrv_connection
*xconn
)
1623 struct smbXsrv_session_auth0
*a
= NULL
;
1624 struct smbXsrv_channel_global0
*c
= NULL
;
1626 bool need_update
= false;
1628 status
= smbXsrv_session_find_auth(session
, xconn
, 0, &a
);
1629 if (!NT_STATUS_IS_OK(status
)) {
1632 status
= smbXsrv_session_find_channel(session
, xconn
, &c
);
1633 if (!NT_STATUS_IS_OK(status
)) {
1638 smbXsrv_session_auth0_destructor(a
);
1639 a
->connection
= NULL
;
1644 struct smbXsrv_session_global0
*global
= session
->global
;
1647 n
= (c
- global
->channels
);
1648 if (n
>= global
->num_channels
|| n
< 0) {
1649 return NT_STATUS_INTERNAL_ERROR
;
1651 ARRAY_DEL_ELEMENT(global
->channels
, n
, global
->num_channels
);
1652 global
->num_channels
--;
1653 if (global
->num_channels
== 0) {
1654 struct smbXsrv_client
*client
= session
->client
;
1655 struct tevent_queue
*xconn_wait_queue
=
1656 xconn
->transport
.shutdown_wait_queue
;
1657 struct tevent_req
*subreq
= NULL
;
1660 * Let the connection wait until the session is
1663 * We don't set a callback, as we just want to block the
1664 * wait queue and the talloc_free() of the session will
1665 * remove the item from the wait queue in order
1666 * to remove allow the connection to disapear.
1668 if (xconn_wait_queue
!= NULL
) {
1669 subreq
= tevent_queue_wait_send(session
,
1672 if (subreq
== NULL
) {
1673 status
= NT_STATUS_NO_MEMORY
;
1674 DBG_ERR("tevent_queue_wait_send() session(%llu) failed: %s\n",
1675 (unsigned long long)session
->global
->session_wire_id
,
1682 * This is garanteed to set
1683 * session->status = NT_STATUS_USER_SESSION_DELETED
1684 * even if NULL is returned.
1686 subreq
= smb2srv_session_shutdown_send(session
,
1690 if (subreq
== NULL
) {
1691 status
= NT_STATUS_NO_MEMORY
;
1692 DBG_ERR("smb2srv_session_shutdown_send(%llu) failed: %s\n",
1693 (unsigned long long)session
->global
->session_wire_id
,
1697 tevent_req_set_callback(subreq
,
1698 smbXsrv_session_remove_channel_done
,
1705 return NT_STATUS_OK
;
1708 return smbXsrv_session_update(session
);
1711 static void smbXsrv_session_remove_channel_done(struct tevent_req
*subreq
)
1713 struct smbXsrv_session
*session
=
1714 tevent_req_callback_data(subreq
,
1715 struct smbXsrv_session
);
1718 status
= smb2srv_session_shutdown_recv(subreq
);
1719 TALLOC_FREE(subreq
);
1720 if (!NT_STATUS_IS_OK(status
)) {
1721 DBG_ERR("smb2srv_session_shutdown_recv(%llu) failed: %s\n",
1722 (unsigned long long)session
->global
->session_wire_id
,
1726 status
= smbXsrv_session_logoff(session
);
1727 if (!NT_STATUS_IS_OK(status
)) {
1728 DBG_ERR("smbXsrv_session_logoff(%llu) failed: %s\n",
1729 (unsigned long long)session
->global
->session_wire_id
,
1733 TALLOC_FREE(session
);
1736 struct smb2srv_session_shutdown_state
{
1737 struct tevent_queue
*wait_queue
;
1740 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
);
1742 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
)
1747 struct tevent_req
*req
;
1748 struct smb2srv_session_shutdown_state
*state
;
1749 struct tevent_req
*subreq
;
1750 struct smbXsrv_connection
*xconn
= NULL
;
1754 * Make sure that no new request will be able to use this session.
1756 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1758 req
= tevent_req_create(mem_ctx
, &state
,
1759 struct smb2srv_session_shutdown_state
);
1764 state
->wait_queue
= tevent_queue_create(state
, "smb2srv_session_shutdown_queue");
1765 if (tevent_req_nomem(state
->wait_queue
, req
)) {
1766 return tevent_req_post(req
, ev
);
1769 for (xconn
= session
->client
->connections
; xconn
!= NULL
; xconn
= xconn
->next
) {
1770 struct smbd_smb2_request
*preq
;
1772 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1773 if (preq
== current_req
) {
1774 /* Can't cancel current request. */
1777 if (preq
->session
!= session
) {
1778 /* Request on different session. */
1782 if (preq
->subreq
!= NULL
) {
1783 tevent_req_cancel(preq
->subreq
);
1787 * Now wait until the request is finished.
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.
1793 subreq
= tevent_queue_wait_send(preq
, ev
, state
->wait_queue
);
1794 if (tevent_req_nomem(subreq
, req
)) {
1795 return tevent_req_post(req
, ev
);
1800 len
= tevent_queue_length(state
->wait_queue
);
1802 tevent_req_done(req
);
1803 return tevent_req_post(req
, ev
);
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.
1811 subreq
= tevent_queue_wait_send(state
, ev
, state
->wait_queue
);
1812 if (tevent_req_nomem(subreq
, req
)) {
1813 return tevent_req_post(req
, ev
);
1815 tevent_req_set_callback(subreq
, smb2srv_session_shutdown_wait_done
, req
);
1820 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
)
1822 struct tevent_req
*req
=
1823 tevent_req_callback_data(subreq
,
1826 tevent_queue_wait_recv(subreq
);
1827 TALLOC_FREE(subreq
);
1829 tevent_req_done(req
);
1832 NTSTATUS
smb2srv_session_shutdown_recv(struct tevent_req
*req
)
1834 return tevent_req_simple_recv_ntstatus(req
);
1837 NTSTATUS
smbXsrv_session_logoff(struct smbXsrv_session
*session
)
1839 struct smbXsrv_session_table
*table
;
1840 struct db_record
*local_rec
= NULL
;
1841 struct db_record
*global_rec
= NULL
;
1842 struct smbd_server_connection
*sconn
= NULL
;
1844 NTSTATUS error
= NT_STATUS_OK
;
1846 if (session
->table
== NULL
) {
1847 return NT_STATUS_OK
;
1850 table
= session
->table
;
1851 session
->table
= NULL
;
1853 sconn
= session
->client
->sconn
;
1854 session
->client
= NULL
;
1855 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
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().
1863 file_close_user(sconn
, session
->global
->session_wire_id
);
1865 if (session
->tcon_table
!= NULL
) {
1867 * Note: We only have a tcon_table for SMB2.
1869 status
= smb2srv_tcon_disconnect_all(session
);
1870 if (!NT_STATUS_IS_OK(status
)) {
1871 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1872 "smb2srv_tcon_disconnect_all() failed: %s\n",
1873 session
->global
->session_global_id
,
1874 nt_errstr(status
)));
1879 invalidate_vuid(sconn
, session
->global
->session_wire_id
);
1881 global_rec
= session
->global
->db_rec
;
1882 session
->global
->db_rec
= NULL
;
1883 if (global_rec
== NULL
) {
1884 global_rec
= smbXsrv_session_global_fetch_locked(
1885 table
->global
.db_ctx
,
1886 session
->global
->session_global_id
,
1887 session
->global
/* TALLOC_CTX */);
1888 if (global_rec
== NULL
) {
1889 error
= NT_STATUS_INTERNAL_ERROR
;
1893 if (global_rec
!= NULL
) {
1894 status
= dbwrap_record_delete(global_rec
);
1895 if (!NT_STATUS_IS_OK(status
)) {
1896 TDB_DATA key
= dbwrap_record_get_key(global_rec
);
1898 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1899 "failed to delete global key '%s': %s\n",
1900 session
->global
->session_global_id
,
1901 hex_encode_talloc(global_rec
, key
.dptr
,
1903 nt_errstr(status
)));
1907 TALLOC_FREE(global_rec
);
1909 local_rec
= session
->db_rec
;
1910 if (local_rec
== NULL
) {
1911 local_rec
= smbXsrv_session_local_fetch_locked(
1912 table
->local
.db_ctx
,
1914 session
/* TALLOC_CTX */);
1915 if (local_rec
== NULL
) {
1916 error
= NT_STATUS_INTERNAL_ERROR
;
1920 if (local_rec
!= NULL
) {
1921 status
= dbwrap_record_delete(local_rec
);
1922 if (!NT_STATUS_IS_OK(status
)) {
1923 TDB_DATA key
= dbwrap_record_get_key(local_rec
);
1925 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1926 "failed to delete local key '%s': %s\n",
1927 session
->global
->session_global_id
,
1928 hex_encode_talloc(local_rec
, key
.dptr
,
1930 nt_errstr(status
)));
1933 table
->local
.num_sessions
-= 1;
1935 if (session
->db_rec
== NULL
) {
1936 TALLOC_FREE(local_rec
);
1938 session
->db_rec
= NULL
;
1943 struct smbXsrv_session_logoff_all_state
{
1944 NTSTATUS first_status
;
1948 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1949 void *private_data
);
1951 NTSTATUS
smbXsrv_session_logoff_all(struct smbXsrv_client
*client
)
1953 struct smbXsrv_session_table
*table
= client
->session_table
;
1954 struct smbXsrv_session_logoff_all_state state
;
1958 if (table
== NULL
) {
1959 DEBUG(10, ("smbXsrv_session_logoff_all: "
1960 "empty session_table, nothing to do.\n"));
1961 return NT_STATUS_OK
;
1966 status
= dbwrap_traverse(table
->local
.db_ctx
,
1967 smbXsrv_session_logoff_all_callback
,
1969 if (!NT_STATUS_IS_OK(status
)) {
1970 DEBUG(0, ("smbXsrv_session_logoff_all: "
1971 "dbwrap_traverse() failed: %s\n",
1972 nt_errstr(status
)));
1976 if (!NT_STATUS_IS_OK(state
.first_status
)) {
1977 DEBUG(0, ("smbXsrv_session_logoff_all: "
1978 "count[%d] errors[%d] first[%s]\n",
1979 count
, state
.errors
,
1980 nt_errstr(state
.first_status
)));
1981 return state
.first_status
;
1984 return NT_STATUS_OK
;
1987 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1990 struct smbXsrv_session_logoff_all_state
*state
=
1991 (struct smbXsrv_session_logoff_all_state
*)private_data
;
1994 struct smbXsrv_session
*session
= NULL
;
1997 val
= dbwrap_record_get_value(local_rec
);
1998 if (val
.dsize
!= sizeof(ptr
)) {
1999 status
= NT_STATUS_INTERNAL_ERROR
;
2000 if (NT_STATUS_IS_OK(state
->first_status
)) {
2001 state
->first_status
= status
;
2007 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2008 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2010 session
->db_rec
= local_rec
;
2011 status
= smbXsrv_session_clear_and_logoff(session
);
2012 session
->db_rec
= NULL
;
2013 if (!NT_STATUS_IS_OK(status
)) {
2014 if (NT_STATUS_IS_OK(state
->first_status
)) {
2015 state
->first_status
= status
;
2024 struct smbXsrv_session_local_trav_state
{
2026 int (*caller_cb
)(struct smbXsrv_session
*session
,
2031 static int smbXsrv_session_local_traverse_cb(struct db_record
*local_rec
,
2032 void *private_data
);
2034 NTSTATUS
smbXsrv_session_local_traverse(
2035 struct smbXsrv_client
*client
,
2036 int (*caller_cb
)(struct smbXsrv_session
*session
,
2040 struct smbXsrv_session_table
*table
= client
->session_table
;
2041 struct smbXsrv_session_local_trav_state state
;
2045 state
= (struct smbXsrv_session_local_trav_state
) {
2046 .status
= NT_STATUS_OK
,
2047 .caller_cb
= caller_cb
,
2048 .caller_data
= caller_data
,
2051 if (table
== NULL
) {
2052 DBG_DEBUG("empty session_table, nothing to do.\n");
2053 return NT_STATUS_OK
;
2056 status
= dbwrap_traverse(table
->local
.db_ctx
,
2057 smbXsrv_session_local_traverse_cb
,
2060 if (!NT_STATUS_IS_OK(status
)) {
2061 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status
));
2064 if (!NT_STATUS_IS_OK(state
.status
)) {
2065 DBG_ERR("count[%d] status[%s]\n",
2066 count
, nt_errstr(state
.status
));
2067 return state
.status
;
2070 return NT_STATUS_OK
;
2073 static int smbXsrv_session_local_traverse_cb(struct db_record
*local_rec
,
2076 struct smbXsrv_session_local_trav_state
*state
=
2077 (struct smbXsrv_session_local_trav_state
*)private_data
;
2080 struct smbXsrv_session
*session
= NULL
;
2083 val
= dbwrap_record_get_value(local_rec
);
2084 if (val
.dsize
!= sizeof(ptr
)) {
2085 state
->status
= NT_STATUS_INTERNAL_ERROR
;
2089 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2090 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2092 session
->db_rec
= local_rec
;
2093 ret
= state
->caller_cb(session
, state
->caller_data
);
2094 session
->db_rec
= NULL
;
2099 struct smbXsrv_session_disconnect_xconn_state
{
2100 struct smbXsrv_connection
*xconn
;
2101 NTSTATUS first_status
;
2105 static int smbXsrv_session_disconnect_xconn_callback(struct db_record
*local_rec
,
2106 void *private_data
);
2108 NTSTATUS
smbXsrv_session_disconnect_xconn(struct smbXsrv_connection
*xconn
)
2110 struct smbXsrv_client
*client
= xconn
->client
;
2111 struct smbXsrv_session_table
*table
= client
->session_table
;
2112 struct smbXsrv_session_disconnect_xconn_state state
;
2116 if (table
== NULL
) {
2117 DBG_ERR("empty session_table, nothing to do.\n");
2118 return NT_STATUS_OK
;
2122 state
.xconn
= xconn
;
2124 status
= dbwrap_traverse(table
->local
.db_ctx
,
2125 smbXsrv_session_disconnect_xconn_callback
,
2127 if (!NT_STATUS_IS_OK(status
)) {
2128 DBG_ERR("dbwrap_traverse() failed: %s\n",
2133 if (!NT_STATUS_IS_OK(state
.first_status
)) {
2134 DBG_ERR("count[%d] errors[%d] first[%s]\n",
2135 count
, state
.errors
,
2136 nt_errstr(state
.first_status
));
2137 return state
.first_status
;
2140 return NT_STATUS_OK
;
2143 static int smbXsrv_session_disconnect_xconn_callback(struct db_record
*local_rec
,
2146 struct smbXsrv_session_disconnect_xconn_state
*state
=
2147 (struct smbXsrv_session_disconnect_xconn_state
*)private_data
;
2150 struct smbXsrv_session
*session
= NULL
;
2153 val
= dbwrap_record_get_value(local_rec
);
2154 if (val
.dsize
!= sizeof(ptr
)) {
2155 status
= NT_STATUS_INTERNAL_ERROR
;
2156 if (NT_STATUS_IS_OK(state
->first_status
)) {
2157 state
->first_status
= status
;
2163 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2164 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2166 session
->db_rec
= local_rec
;
2167 status
= smbXsrv_session_remove_channel(session
, state
->xconn
);
2168 session
->db_rec
= NULL
;
2169 if (!NT_STATUS_IS_OK(status
)) {
2170 if (NT_STATUS_IS_OK(state
->first_status
)) {
2171 state
->first_status
= status
;
2179 NTSTATUS
smb1srv_session_table_init(struct smbXsrv_connection
*conn
)
2182 * Allow a range from 1..65534 with 65534 values.
2184 return smbXsrv_session_table_init(conn
, 1, UINT16_MAX
- 1,
2188 NTSTATUS
smb1srv_session_lookup(struct smbXsrv_connection
*conn
,
2189 uint16_t vuid
, NTTIME now
,
2190 struct smbXsrv_session
**session
)
2192 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
2193 uint32_t local_id
= vuid
;
2195 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
2199 NTSTATUS
smbXsrv_session_info_lookup(struct smbXsrv_client
*client
,
2200 uint64_t session_wire_id
,
2201 struct auth_session_info
**si
)
2203 struct smbXsrv_session_table
*table
= client
->session_table
;
2204 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
2205 struct smbXsrv_session_local_fetch_state state
= {
2207 .status
= NT_STATUS_INTERNAL_ERROR
,
2212 if (session_wire_id
== 0) {
2213 return NT_STATUS_USER_SESSION_DELETED
;
2216 if (table
== NULL
) {
2217 /* this might happen before the end of negprot */
2218 return NT_STATUS_USER_SESSION_DELETED
;
2221 if (table
->local
.db_ctx
== NULL
) {
2222 return NT_STATUS_INTERNAL_ERROR
;
2225 key
= smbXsrv_session_local_id_to_key(session_wire_id
, key_buf
);
2227 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
2228 smbXsrv_session_local_fetch_parser
,
2230 if (!NT_STATUS_IS_OK(status
)) {
2233 if (!NT_STATUS_IS_OK(state
.status
)) {
2234 return state
.status
;
2236 if (state
.session
->global
->auth_session_info
== NULL
) {
2237 return NT_STATUS_USER_SESSION_DELETED
;
2240 *si
= state
.session
->global
->auth_session_info
;
2241 return NT_STATUS_OK
;
2245 * In memory of get_valid_user_struct()
2247 * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
2248 * but it doesn't implement the state checks of
2249 * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
2250 * session wire-id of incoming SMB requests, it MUST only be used in later
2251 * internal processing where the session wire-id has already been validated.
2253 NTSTATUS
get_valid_smbXsrv_session(struct smbXsrv_client
*client
,
2254 uint64_t session_wire_id
,
2255 struct smbXsrv_session
**session
)
2257 struct smbXsrv_session_table
*table
= client
->session_table
;
2258 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
2259 struct smbXsrv_session_local_fetch_state state
= {
2261 .status
= NT_STATUS_INTERNAL_ERROR
,
2266 if (session_wire_id
== 0) {
2267 return NT_STATUS_USER_SESSION_DELETED
;
2270 if (table
== NULL
) {
2271 /* this might happen before the end of negprot */
2272 return NT_STATUS_USER_SESSION_DELETED
;
2275 if (table
->local
.db_ctx
== NULL
) {
2276 return NT_STATUS_INTERNAL_ERROR
;
2279 key
= smbXsrv_session_local_id_to_key(session_wire_id
, key_buf
);
2281 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
2282 smbXsrv_session_local_fetch_parser
,
2284 if (!NT_STATUS_IS_OK(status
)) {
2287 if (!NT_STATUS_IS_OK(state
.status
)) {
2288 return state
.status
;
2290 if (state
.session
->global
->auth_session_info
== NULL
) {
2291 return NT_STATUS_USER_SESSION_DELETED
;
2294 *session
= state
.session
;
2295 return NT_STATUS_OK
;
2298 NTSTATUS
smb2srv_session_lookup_global(struct smbXsrv_client
*client
,
2299 uint64_t session_wire_id
,
2300 TALLOC_CTX
*mem_ctx
,
2301 struct smbXsrv_session
**_session
)
2303 TALLOC_CTX
*frame
= talloc_stackframe();
2304 struct smbXsrv_session_table
*table
= client
->session_table
;
2305 uint32_t global_id
= session_wire_id
& UINT32_MAX
;
2306 uint64_t global_zeros
= session_wire_id
& 0xFFFFFFFF00000000LLU
;
2307 struct smbXsrv_session
*session
= NULL
;
2308 struct db_record
*global_rec
= NULL
;
2309 bool is_free
= false;
2312 if (global_id
== 0) {
2314 return NT_STATUS_USER_SESSION_DELETED
;
2316 if (global_zeros
!= 0) {
2318 return NT_STATUS_USER_SESSION_DELETED
;
2321 if (table
== NULL
) {
2322 /* this might happen before the end of negprot */
2324 return NT_STATUS_USER_SESSION_DELETED
;
2327 if (table
->global
.db_ctx
== NULL
) {
2329 return NT_STATUS_INTERNAL_ERROR
;
2332 session
= talloc_zero(mem_ctx
, struct smbXsrv_session
);
2333 if (session
== NULL
) {
2335 return NT_STATUS_NO_MEMORY
;
2337 talloc_steal(frame
, session
);
2339 session
->client
= client
;
2340 session
->status
= NT_STATUS_BAD_LOGON_SESSION_STATE
;
2341 session
->local_id
= global_id
;
2344 * This means smb2_get_new_nonce() will return
2345 * NT_STATUS_ENCRYPTION_FAILED.
2347 * But we intialize some random parts just in case...
2349 session
->nonce_high_max
= session
->nonce_high
= 0;
2350 generate_nonce_buffer((uint8_t *)&session
->nonce_high_random
,
2351 sizeof(session
->nonce_high_random
));
2352 generate_nonce_buffer((uint8_t *)&session
->nonce_low
,
2353 sizeof(session
->nonce_low
));
2355 global_rec
= smbXsrv_session_global_fetch_locked(table
->global
.db_ctx
,
2358 if (global_rec
== NULL
) {
2360 return NT_STATUS_INTERNAL_DB_ERROR
;
2363 smbXsrv_session_global_verify_record(global_rec
,
2371 return NT_STATUS_USER_SESSION_DELETED
;
2375 * We don't have channels on this session
2376 * and only the main signing key
2378 session
->global
->num_channels
= 0;
2379 status
= smb2_signing_key_sign_create(session
->global
,
2380 session
->global
->signing_algo
,
2381 NULL
, /* no master key */
2382 NULL
, /* derivations */
2383 &session
->global
->signing_key
);
2384 if (!NT_STATUS_IS_OK(status
)) {
2386 return NT_STATUS_NO_MEMORY
;
2388 session
->global
->signing_key
->blob
= session
->global
->signing_key_blob
;
2389 session
->global
->signing_flags
= 0;
2391 status
= smb2_signing_key_cipher_create(session
->global
,
2392 session
->global
->encryption_cipher
,
2393 NULL
, /* no master key */
2394 NULL
, /* derivations */
2395 &session
->global
->decryption_key
);
2396 if (!NT_STATUS_IS_OK(status
)) {
2398 return NT_STATUS_NO_MEMORY
;
2400 session
->global
->decryption_key
->blob
= session
->global
->decryption_key_blob
;
2401 session
->global
->encryption_flags
= 0;
2403 *_session
= talloc_move(mem_ctx
, &session
);
2405 return NT_STATUS_OK
;
2408 NTSTATUS
smb2srv_session_table_init(struct smbXsrv_connection
*conn
)
2411 * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
2413 return smbXsrv_session_table_init(conn
, 1, UINT32_MAX
- 1,
2417 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
2418 /* conn: optional */
2419 struct smbXsrv_connection
*conn
,
2420 uint64_t session_id
, NTTIME now
,
2421 struct smbXsrv_session
**session
)
2423 uint32_t local_id
= session_id
& UINT32_MAX
;
2424 uint64_t local_zeros
= session_id
& 0xFFFFFFFF00000000LLU
;
2426 if (local_zeros
!= 0) {
2427 return NT_STATUS_USER_SESSION_DELETED
;
2430 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
2434 NTSTATUS
smb2srv_session_lookup_conn(struct smbXsrv_connection
*conn
,
2435 uint64_t session_id
, NTTIME now
,
2436 struct smbXsrv_session
**session
)
2438 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
2439 return smb2srv_session_lookup_raw(table
, conn
, session_id
, now
,
2443 NTSTATUS
smb2srv_session_lookup_client(struct smbXsrv_client
*client
,
2444 uint64_t session_id
, NTTIME now
,
2445 struct smbXsrv_session
**session
)
2447 struct smbXsrv_session_table
*table
= client
->session_table
;
2448 return smb2srv_session_lookup_raw(table
, NULL
, session_id
, now
,
2452 struct smbXsrv_session_global_traverse_state
{
2453 int (*fn
)(struct smbXsrv_session_global0
*, void *);
2457 static int smbXsrv_session_global_traverse_fn(struct db_record
*rec
, void *data
)
2460 struct smbXsrv_session_global_traverse_state
*state
=
2461 (struct smbXsrv_session_global_traverse_state
*)data
;
2462 TDB_DATA key
= dbwrap_record_get_key(rec
);
2463 TDB_DATA val
= dbwrap_record_get_value(rec
);
2464 DATA_BLOB blob
= data_blob_const(val
.dptr
, val
.dsize
);
2465 struct smbXsrv_session_globalB global_blob
;
2466 enum ndr_err_code ndr_err
;
2467 TALLOC_CTX
*frame
= talloc_stackframe();
2469 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
2470 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
2471 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2472 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
2473 "key '%s' ndr_pull_struct_blob - %s\n",
2474 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
2475 ndr_errstr(ndr_err
)));
2479 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
2480 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
2481 "key '%s' unsupported version - %d\n",
2482 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
2483 (int)global_blob
.version
));
2487 if (global_blob
.info
.info0
== NULL
) {
2488 DEBUG(1,("Invalid record in smbXsrv_tcon_global.tdb:"
2489 "key '%s' info0 NULL pointer\n",
2490 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
)));
2494 global_blob
.info
.info0
->db_rec
= rec
;
2495 ret
= state
->fn(global_blob
.info
.info0
, state
->private_data
);
2501 NTSTATUS
smbXsrv_session_global_traverse(
2502 int (*fn
)(struct smbXsrv_session_global0
*, void *),
2508 struct smbXsrv_session_global_traverse_state state
= {
2510 .private_data
= private_data
,
2514 status
= smbXsrv_session_global_init(NULL
);
2515 if (!NT_STATUS_IS_OK(status
)) {
2517 DEBUG(0, ("Failed to initialize session_global: %s\n",
2518 nt_errstr(status
)));
2522 status
= dbwrap_traverse_read(smbXsrv_session_global_db_ctx
,
2523 smbXsrv_session_global_traverse_fn
,