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 "smbXsrv_session.h"
23 #include "system/filesys.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"
34 #include "auth/gensec/gensec.h"
35 #include "../lib/tsocket/tsocket.h"
36 #include "../libcli/security/security.h"
38 #include "lib/util/util_tdb.h"
39 #include "librpc/gen_ndr/ndr_smbXsrv.h"
41 #include "lib/util/tevent_ntstatus.h"
42 #include "lib/global_contexts.h"
43 #include "source3/include/util_tdb.h"
45 struct smbXsrv_session_table
{
47 struct db_context
*db_ctx
;
50 uint32_t max_sessions
;
51 uint32_t num_sessions
;
54 struct db_context
*db_ctx
;
58 static struct db_context
*smbXsrv_session_global_db_ctx
= NULL
;
60 NTSTATUS
smbXsrv_session_global_init(struct messaging_context
*msg_ctx
)
62 char *global_path
= NULL
;
63 struct db_context
*backend
= NULL
;
64 struct db_context
*db_ctx
= NULL
;
66 if (smbXsrv_session_global_db_ctx
!= NULL
) {
71 * This contains secret information like session keys!
73 global_path
= lock_path(talloc_tos(), "smbXsrv_session_global.tdb");
74 if (global_path
== NULL
) {
75 return NT_STATUS_NO_MEMORY
;
78 backend
= db_open(NULL
, global_path
,
79 SMBD_VOLATILE_TDB_HASH_SIZE
,
80 SMBD_VOLATILE_TDB_FLAGS
,
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
,
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
,
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 DBG_WARNING("ndr_pull_struct_blob - %s\n", nt_errstr(status
));
308 DBG_DEBUG("MSG_SMBXSRV_SESSION_CLOSE\n");
309 if (DEBUGLVL(DBGLVL_DEBUG
)) {
310 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
313 if (close_blob
.version
!= SMBXSRV_VERSION_0
) {
314 DBG_ERR("ignore invalid version %u\n", close_blob
.version
);
315 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
319 close_info0
= close_blob
.info
.info0
;
320 if (close_info0
== NULL
) {
321 DBG_ERR("ignore NULL info %u\n", close_blob
.version
);
322 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
326 status
= smb2srv_session_lookup_client(client
,
327 close_info0
->old_session_wire_id
,
329 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_SESSION_DELETED
)) {
330 DBG_INFO("old_session_wire_id %" PRIu64
" not found\n",
331 close_info0
->old_session_wire_id
);
332 if (DEBUGLVL(DBGLVL_INFO
)) {
333 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
337 if (!NT_STATUS_IS_OK(status
) &&
338 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
339 !NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
340 DBG_WARNING("old_session_wire_id %" PRIu64
" - %s\n",
341 close_info0
->old_session_wire_id
,
343 if (DEBUGLVL(DBGLVL_WARNING
)) {
344 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
349 if (session
->global
->session_global_id
!= close_info0
->old_session_global_id
) {
350 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 if (DEBUGLVL(DBGLVL_WARNING
)) {
356 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
361 if (session
->global
->creation_time
!= close_info0
->old_creation_time
) {
362 DBG_WARNING("old_session_wire_id %" PRIu64
" - "
363 "creation %s (%" PRIu64
") != %s (%" PRIu64
")\n",
364 close_info0
->old_session_wire_id
,
366 session
->global
->creation_time
),
367 session
->global
->creation_time
,
369 close_info0
->old_creation_time
),
370 close_info0
->old_creation_time
);
371 if (DEBUGLVL(DBGLVL_WARNING
)) {
372 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
377 subreq
= smb2srv_session_shutdown_send(session
, client
->raw_ev_ctx
,
379 if (subreq
== NULL
) {
380 status
= NT_STATUS_NO_MEMORY
;
381 DBG_ERR("smb2srv_session_shutdown_send(%" PRIu64
383 session
->global
->session_wire_id
,
385 if (DEBUGLVL(DBGLVL_WARNING
)) {
386 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
390 tevent_req_set_callback(subreq
,
391 smbXsrv_session_close_shutdown_done
,
397 subreq
= messaging_read_send(table
,
400 MSG_SMBXSRV_SESSION_CLOSE
);
401 if (subreq
== NULL
) {
403 r
= "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
404 exit_server_cleanly(r
);
407 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
410 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
)
412 struct smbXsrv_session
*session
=
413 tevent_req_callback_data(subreq
,
414 struct smbXsrv_session
);
417 status
= smb2srv_session_shutdown_recv(subreq
);
419 if (!NT_STATUS_IS_OK(status
)) {
420 DBG_ERR("smb2srv_session_shutdown_recv(%" PRIu64
422 session
->global
->session_wire_id
,
426 status
= smbXsrv_session_logoff(session
);
427 if (!NT_STATUS_IS_OK(status
)) {
428 DBG_ERR("smbXsrv_session_logoff(%" PRIu64
") failed: %s\n",
429 session
->global
->session_wire_id
,
433 TALLOC_FREE(session
);
436 struct smb1srv_session_local_allocate_state
{
437 const uint32_t lowest_id
;
438 const uint32_t highest_id
;
444 static int smb1srv_session_local_allocate_traverse(struct db_record
*rec
,
447 struct smb1srv_session_local_allocate_state
*state
=
448 (struct smb1srv_session_local_allocate_state
*)private_data
;
449 TDB_DATA key
= dbwrap_record_get_key(rec
);
453 status
= smbXsrv_session_local_key_to_id(key
, &id
);
454 if (!NT_STATUS_IS_OK(status
)) {
455 state
->status
= status
;
459 if (id
<= state
->last_id
) {
460 state
->status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
465 if (id
> state
->useable_id
) {
466 state
->status
= NT_STATUS_OK
;
470 if (state
->useable_id
== state
->highest_id
) {
471 state
->status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
475 state
->useable_id
+=1;
479 static NTSTATUS
smb1srv_session_local_allocate_id(struct db_context
*db
,
483 struct db_record
**_rec
,
486 struct smb1srv_session_local_allocate_state state
= {
487 .lowest_id
= lowest_id
,
488 .highest_id
= highest_id
,
490 .useable_id
= lowest_id
,
491 .status
= NT_STATUS_INTERNAL_ERROR
,
501 if (lowest_id
> highest_id
) {
502 return NT_STATUS_INSUFFICIENT_RESOURCES
;
506 * first we try randomly
508 range
= (highest_id
- lowest_id
) + 1;
510 for (i
= 0; i
< (range
/ 2); i
++) {
513 struct db_record
*rec
= NULL
;
515 id
= generate_random() % range
;
518 if (id
< lowest_id
) {
521 if (id
> highest_id
) {
525 rec
= smbXsrv_session_local_fetch_locked(db
, id
, mem_ctx
);
527 return NT_STATUS_INSUFFICIENT_RESOURCES
;
530 val
= dbwrap_record_get_value(rec
);
531 if (val
.dsize
!= 0) {
542 * if the range is almost full,
543 * we traverse the whole table
544 * (this relies on sorted behavior of dbwrap_rbt)
546 status
= dbwrap_traverse_read(db
, smb1srv_session_local_allocate_traverse
,
548 if (NT_STATUS_IS_OK(status
)) {
549 if (NT_STATUS_IS_OK(state
.status
)) {
550 return NT_STATUS_INTERNAL_ERROR
;
553 if (!NT_STATUS_EQUAL(state
.status
, NT_STATUS_INTERNAL_ERROR
)) {
557 if (state
.useable_id
<= state
.highest_id
) {
558 state
.status
= NT_STATUS_OK
;
560 return NT_STATUS_INSUFFICIENT_RESOURCES
;
562 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_INTERNAL_DB_CORRUPTION
)) {
564 * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
566 * If we get anything else it is an error, because it
567 * means we did not manage to find a free slot in
570 return NT_STATUS_INSUFFICIENT_RESOURCES
;
573 if (NT_STATUS_IS_OK(state
.status
)) {
576 struct db_record
*rec
= NULL
;
578 id
= state
.useable_id
;
580 rec
= smbXsrv_session_local_fetch_locked(db
, id
, mem_ctx
);
582 return NT_STATUS_INSUFFICIENT_RESOURCES
;
585 val
= dbwrap_record_get_value(rec
);
586 if (val
.dsize
!= 0) {
588 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
599 struct smbXsrv_session_local_fetch_state
{
600 struct smbXsrv_session
*session
;
604 static void smbXsrv_session_local_fetch_parser(TDB_DATA key
, TDB_DATA data
,
607 struct smbXsrv_session_local_fetch_state
*state
=
608 (struct smbXsrv_session_local_fetch_state
*)private_data
;
611 if (data
.dsize
!= sizeof(ptr
)) {
612 state
->status
= NT_STATUS_INTERNAL_DB_ERROR
;
616 memcpy(&ptr
, data
.dptr
, data
.dsize
);
617 state
->session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
618 state
->status
= NT_STATUS_OK
;
621 static NTSTATUS
smbXsrv_session_local_lookup(struct smbXsrv_session_table
*table
,
623 struct smbXsrv_connection
*conn
,
624 uint32_t session_local_id
,
626 struct smbXsrv_session
**_session
)
628 struct smbXsrv_session_local_fetch_state state
= {
630 .status
= NT_STATUS_INTERNAL_ERROR
,
632 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
638 if (session_local_id
== 0) {
639 return NT_STATUS_USER_SESSION_DELETED
;
643 /* this might happen before the end of negprot */
644 return NT_STATUS_USER_SESSION_DELETED
;
647 if (table
->local
.db_ctx
== NULL
) {
648 return NT_STATUS_INTERNAL_ERROR
;
651 key
= smbXsrv_session_local_id_to_key(session_local_id
, key_buf
);
653 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
654 smbXsrv_session_local_fetch_parser
,
656 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
657 return NT_STATUS_USER_SESSION_DELETED
;
658 } else if (!NT_STATUS_IS_OK(status
)) {
661 if (!NT_STATUS_IS_OK(state
.status
)) {
665 if (NT_STATUS_EQUAL(state
.session
->status
, NT_STATUS_USER_SESSION_DELETED
)) {
666 return NT_STATUS_USER_SESSION_DELETED
;
670 * If a connection is specified check if the session is
671 * valid on the channel.
674 struct smbXsrv_channel_global0
*c
= NULL
;
676 status
= smbXsrv_session_find_channel(state
.session
, conn
, &c
);
677 if (!NT_STATUS_IS_OK(status
)) {
682 state
.session
->idle_time
= now
;
684 if (!NT_STATUS_IS_OK(state
.session
->status
)) {
685 *_session
= state
.session
;
686 return state
.session
->status
;
689 if (now
> state
.session
->global
->expiration_time
) {
690 state
.session
->status
= NT_STATUS_NETWORK_SESSION_EXPIRED
;
693 *_session
= state
.session
;
694 return state
.session
->status
;
697 static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0
*global
)
702 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
706 struct smbXsrv_session_global0
**_g
,
709 static NTSTATUS
smbXsrv_session_global_allocate(struct db_context
*db
,
711 struct smbXsrv_session_global0
**_global
)
714 struct smbXsrv_session_global0
*global
= NULL
;
715 uint32_t last_free
= 0;
716 const uint32_t min_tries
= 3;
720 global
= talloc_zero(mem_ctx
, struct smbXsrv_session_global0
);
721 if (global
== NULL
) {
722 return NT_STATUS_NO_MEMORY
;
724 talloc_set_destructor(global
, smbXsrv_session_global_destructor
);
727 * Here we just randomly try the whole 32-bit space
729 * We use just 32-bit, because we want to reuse the
732 for (i
= 0; i
< UINT32_MAX
; i
++) {
733 bool is_free
= false;
734 bool was_free
= false;
737 if (i
>= min_tries
&& last_free
!= 0) {
740 id
= generate_random();
745 if (id
== UINT32_MAX
) {
749 global
->db_rec
= smbXsrv_session_global_fetch_locked(db
, id
,
751 if (global
->db_rec
== NULL
) {
753 return NT_STATUS_INSUFFICIENT_RESOURCES
;
756 smbXsrv_session_global_verify_record(global
->db_rec
,
762 TALLOC_FREE(global
->db_rec
);
766 if (!was_free
&& i
< min_tries
) {
768 * The session_id is free now,
769 * but was not free before.
771 * This happens if a smbd crashed
772 * and did not cleanup the record.
774 * If this is one of our first tries,
775 * then we try to find a real free one.
777 if (last_free
== 0) {
780 TALLOC_FREE(global
->db_rec
);
784 global
->session_global_id
= id
;
790 /* should not be reached */
792 return NT_STATUS_INTERNAL_ERROR
;
795 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
799 struct smbXsrv_session_global0
**_g
,
805 struct smbXsrv_session_globalB global_blob
;
806 enum ndr_err_code ndr_err
;
807 struct smbXsrv_session_global0
*global
= NULL
;
809 TALLOC_CTX
*frame
= talloc_stackframe();
823 key
= dbwrap_record_get_key(db_rec
);
825 val
= dbwrap_record_get_value(db_rec
);
826 if (val
.dsize
== 0) {
835 blob
= data_blob_const(val
.dptr
, val
.dsize
);
837 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
838 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
839 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
840 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
841 DBG_WARNING("key '%s' ndr_pull_struct_blob - %s\n",
852 DBG_DEBUG("smbXsrv_session_global_verify_record\n");
853 if (DEBUGLVL(DBGLVL_DEBUG
)) {
854 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
857 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
858 DBG_ERR("key '%s' use unsupported version %u\n",
860 global_blob
.version
);
861 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
870 global
= global_blob
.info
.info0
;
872 #define __BLOB_KEEP_SECRET(__blob) do { \
873 if ((__blob).length != 0) { \
874 talloc_keep_secret((__blob).data); \
879 __BLOB_KEEP_SECRET(global
->application_key_blob
);
880 __BLOB_KEEP_SECRET(global
->signing_key_blob
);
881 __BLOB_KEEP_SECRET(global
->encryption_key_blob
);
882 __BLOB_KEEP_SECRET(global
->decryption_key_blob
);
883 for (i
= 0; i
< global
->num_channels
; i
++) {
884 __BLOB_KEEP_SECRET(global
->channels
[i
].signing_key_blob
);
887 #undef __BLOB_KEEP_SECRET
889 exists
= serverid_exists(&global
->channels
[0].server_id
);
891 struct server_id_buf idbuf
;
892 DBG_NOTICE("key '%s' server_id %s does not exist.\n",
894 server_id_str_buf(global
->channels
[0].server_id
,
896 if (DEBUGLVL(DBGLVL_NOTICE
)) {
897 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
900 dbwrap_record_delete(db_rec
);
906 *_g
= talloc_move(mem_ctx
, &global
);
909 *pseqnum
= global_blob
.seqnum
;
914 static NTSTATUS
smbXsrv_session_global_store(struct smbXsrv_session_global0
*global
)
916 struct smbXsrv_session_globalB global_blob
;
917 DATA_BLOB blob
= data_blob_null
;
921 enum ndr_err_code ndr_err
;
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.
929 key
= dbwrap_record_get_key(global
->db_rec
);
930 val
= dbwrap_record_get_value(global
->db_rec
);
932 global_blob
= (struct smbXsrv_session_globalB
){
933 .version
= smbXsrv_version_global_current(),
934 .info
.info0
= global
,
937 if (val
.dsize
>= 8) {
938 global_blob
.seqnum
= IVAL(val
.dptr
, 4);
940 global_blob
.seqnum
+= 1;
942 ndr_err
= ndr_push_struct_blob(
946 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_globalB
);
947 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
948 status
= ndr_map_error2ntstatus(ndr_err
);
949 DBG_WARNING("key '%s' ndr_push - %s\n",
952 TALLOC_FREE(global
->db_rec
);
956 val
= make_tdb_data(blob
.data
, blob
.length
);
957 status
= dbwrap_record_store(global
->db_rec
, val
, TDB_REPLACE
);
958 TALLOC_FREE(blob
.data
);
959 if (!NT_STATUS_IS_OK(status
)) {
960 DBG_WARNING("key '%s' store - %s\n",
963 TALLOC_FREE(global
->db_rec
);
967 if (DEBUGLVL(DBGLVL_DEBUG
)) {
968 DBG_DEBUG("key '%s' stored\n", tdb_data_dbg(key
));
969 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
972 TALLOC_FREE(global
->db_rec
);
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
;
988 static void smb2srv_session_close_previous_cleanup(struct tevent_req
*req
,
989 enum tevent_req_state req_state
)
991 struct smb2srv_session_close_previous_state
*state
=
993 struct smb2srv_session_close_previous_state
);
995 if (state
->db_rec
!= NULL
) {
996 dbwrap_watched_watch_remove_instance(state
->db_rec
,
997 state
->watch_instance
);
998 state
->watch_instance
= 0;
999 TALLOC_FREE(state
->db_rec
);
1003 static void smb2srv_session_close_previous_check(struct tevent_req
*req
);
1004 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
);
1006 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
)
1013 struct tevent_req
*req
= NULL
;
1014 struct smb2srv_session_close_previous_state
*state
= NULL
;
1015 uint32_t global_id
= previous_session_id
& UINT32_MAX
;
1016 uint64_t global_zeros
= previous_session_id
& 0xFFFFFFFF00000000LLU
;
1017 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1018 struct security_token
*current_token
= NULL
;
1020 req
= tevent_req_create(mem_ctx
, &state
,
1021 struct smb2srv_session_close_previous_state
);
1026 state
->connection
= conn
;
1027 state
->previous_session_id
= previous_session_id
;
1028 state
->current_session_id
= current_session_id
;
1030 tevent_req_set_cleanup_fn(req
, smb2srv_session_close_previous_cleanup
);
1032 if (global_zeros
!= 0) {
1033 tevent_req_done(req
);
1034 return tevent_req_post(req
, ev
);
1037 if (session_info
== NULL
) {
1038 tevent_req_done(req
);
1039 return tevent_req_post(req
, ev
);
1041 current_token
= session_info
->security_token
;
1043 if (current_token
->num_sids
<= PRIMARY_USER_SID_INDEX
) {
1044 tevent_req_done(req
);
1045 return tevent_req_post(req
, ev
);
1047 state
->current_sid
= ¤t_token
->sids
[PRIMARY_USER_SID_INDEX
];
1049 if (!security_token_has_nt_authenticated_users(current_token
)) {
1051 tevent_req_done(req
);
1052 return tevent_req_post(req
, ev
);
1055 state
->db_rec
= smbXsrv_session_global_fetch_locked(
1056 table
->global
.db_ctx
,
1058 state
/* TALLOC_CTX */);
1059 if (state
->db_rec
== NULL
) {
1060 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1061 return tevent_req_post(req
, ev
);
1064 smb2srv_session_close_previous_check(req
);
1065 if (!tevent_req_is_in_progress(req
)) {
1066 return tevent_req_post(req
, ev
);
1072 static void smb2srv_session_close_previous_check(struct tevent_req
*req
)
1074 struct smb2srv_session_close_previous_state
*state
=
1075 tevent_req_data(req
,
1076 struct smb2srv_session_close_previous_state
);
1077 struct smbXsrv_connection
*conn
= state
->connection
;
1079 struct security_token
*previous_token
= NULL
;
1080 struct smbXsrv_session_global0
*global
= NULL
;
1081 enum ndr_err_code ndr_err
;
1082 struct smbXsrv_session_close0 close_info0
;
1083 struct smbXsrv_session_closeB close_blob
;
1084 struct tevent_req
*subreq
= NULL
;
1086 bool is_free
= false;
1087 uint32_t seqnum
= 0;
1089 smbXsrv_session_global_verify_record(state
->db_rec
,
1097 tevent_req_done(req
);
1101 if (global
->auth_session_info
== NULL
) {
1102 tevent_req_done(req
);
1106 previous_token
= global
->auth_session_info
->security_token
;
1108 if (!security_token_is_sid(previous_token
, state
->current_sid
)) {
1109 tevent_req_done(req
);
1114 * If the record changed, but we are not happy with the change yet,
1115 * we better remove ourself from the waiter list
1116 * (most likely the first position)
1117 * and re-add us at the end of the list.
1119 * This gives other waiters a change
1122 * Otherwise we'll keep our waiter instance alive,
1123 * keep waiting (most likely at first position).
1124 * It means the order of watchers stays fair.
1126 if (state
->last_seqnum
!= seqnum
) {
1127 state
->last_seqnum
= seqnum
;
1128 dbwrap_watched_watch_remove_instance(state
->db_rec
,
1129 state
->watch_instance
);
1130 state
->watch_instance
=
1131 dbwrap_watched_watch_add_instance(state
->db_rec
);
1134 subreq
= dbwrap_watched_watch_send(state
, state
->ev
, state
->db_rec
,
1135 state
->watch_instance
,
1136 (struct server_id
){0});
1137 if (tevent_req_nomem(subreq
, req
)) {
1140 tevent_req_set_callback(subreq
,
1141 smb2srv_session_close_previous_modified
,
1144 close_info0
= (struct smbXsrv_session_close0
){
1145 .old_session_global_id
= global
->session_global_id
,
1146 .old_session_wire_id
= global
->session_wire_id
,
1147 .old_creation_time
= global
->creation_time
,
1148 .new_session_wire_id
= state
->current_session_id
,
1151 close_blob
= (struct smbXsrv_session_closeB
){
1152 .version
= smbXsrv_version_global_current(),
1153 .info
.info0
= &close_info0
,
1156 ndr_err
= ndr_push_struct_blob(&blob
, state
, &close_blob
,
1157 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_closeB
);
1158 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1159 status
= ndr_map_error2ntstatus(ndr_err
);
1160 DBG_WARNING("old_session[%" PRIu64
"] "
1161 "new_session[%" PRIu64
"] ndr_push - %s\n",
1162 close_info0
.old_session_wire_id
,
1163 close_info0
.new_session_wire_id
,
1165 tevent_req_nterror(req
, status
);
1169 status
= messaging_send(conn
->client
->msg_ctx
,
1170 global
->channels
[0].server_id
,
1171 MSG_SMBXSRV_SESSION_CLOSE
, &blob
);
1172 TALLOC_FREE(global
);
1173 if (tevent_req_nterror(req
, status
)) {
1177 TALLOC_FREE(state
->db_rec
);
1181 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
)
1183 struct tevent_req
*req
=
1184 tevent_req_callback_data(subreq
,
1186 struct smb2srv_session_close_previous_state
*state
=
1187 tevent_req_data(req
,
1188 struct smb2srv_session_close_previous_state
);
1191 uint64_t instance
= 0;
1193 status
= dbwrap_watched_watch_recv(subreq
, &instance
, NULL
, NULL
);
1194 TALLOC_FREE(subreq
);
1195 if (tevent_req_nterror(req
, status
)) {
1199 state
->watch_instance
= instance
;
1201 global_id
= state
->previous_session_id
& UINT32_MAX
;
1203 state
->db_rec
= smbXsrv_session_global_fetch_locked(
1204 state
->connection
->client
->session_table
->global
.db_ctx
,
1205 global_id
, state
/* TALLOC_CTX */);
1206 if (state
->db_rec
== NULL
) {
1207 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1211 smb2srv_session_close_previous_check(req
);
1214 NTSTATUS
smb2srv_session_close_previous_recv(struct tevent_req
*req
)
1218 if (tevent_req_is_nterror(req
, &status
)) {
1219 tevent_req_received(req
);
1223 tevent_req_received(req
);
1224 return NT_STATUS_OK
;
1227 static NTSTATUS
smbXsrv_session_clear_and_logoff(struct smbXsrv_session
*session
)
1230 struct smbXsrv_connection
*xconn
= NULL
;
1232 if (session
->client
!= NULL
) {
1233 xconn
= session
->client
->connections
;
1236 for (; xconn
!= NULL
; xconn
= xconn
->next
) {
1237 struct smbd_smb2_request
*preq
;
1239 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1240 if (preq
->session
!= session
) {
1244 preq
->session
= NULL
;
1246 * If we no longer have a session we can't
1247 * sign or encrypt replies.
1249 preq
->do_signing
= false;
1250 preq
->do_encryption
= false;
1251 preq
->preauth
= NULL
;
1255 status
= smbXsrv_session_logoff(session
);
1259 static int smbXsrv_session_destructor(struct smbXsrv_session
*session
)
1263 DBG_DEBUG("destructing session(%" PRIu64
")\n",
1264 session
->global
->session_wire_id
);
1266 status
= smbXsrv_session_clear_and_logoff(session
);
1267 if (!NT_STATUS_IS_OK(status
)) {
1268 DBG_ERR("smbXsrv_session_logoff() failed: %s\n",
1272 TALLOC_FREE(session
->global
);
1277 NTSTATUS
smbXsrv_session_create(struct smbXsrv_connection
*conn
,
1279 struct smbXsrv_session
**_session
)
1281 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1282 struct db_record
*local_rec
= NULL
;
1283 struct smbXsrv_session
*session
= NULL
;
1286 struct smbXsrv_session_global0
*global
= NULL
;
1287 struct smbXsrv_channel_global0
*channel
= NULL
;
1290 if (table
->local
.num_sessions
>= table
->local
.max_sessions
) {
1291 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1294 session
= talloc_zero(table
, struct smbXsrv_session
);
1295 if (session
== NULL
) {
1296 return NT_STATUS_NO_MEMORY
;
1298 session
->table
= table
;
1299 session
->idle_time
= now
;
1300 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
1301 session
->client
= conn
->client
;
1302 session
->homes_snum
= -1;
1304 status
= smbXsrv_session_global_allocate(table
->global
.db_ctx
,
1307 if (!NT_STATUS_IS_OK(status
)) {
1308 TALLOC_FREE(session
);
1311 session
->global
= global
;
1313 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1314 uint64_t id
= global
->session_global_id
;
1316 global
->connection_dialect
= conn
->smb2
.server
.dialect
;
1317 global
->client_guid
= conn
->smb2
.client
.guid
;
1319 global
->session_wire_id
= id
;
1321 status
= smb2srv_tcon_table_init(session
);
1322 if (!NT_STATUS_IS_OK(status
)) {
1323 TALLOC_FREE(session
);
1327 session
->local_id
= global
->session_global_id
;
1329 local_rec
= smbXsrv_session_local_fetch_locked(
1330 table
->local
.db_ctx
,
1332 session
/* TALLOC_CTX */);
1333 if (local_rec
== NULL
) {
1334 TALLOC_FREE(session
);
1335 return NT_STATUS_NO_MEMORY
;
1338 val
= dbwrap_record_get_value(local_rec
);
1339 if (val
.dsize
!= 0) {
1340 TALLOC_FREE(session
);
1341 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1345 status
= smb1srv_session_local_allocate_id(table
->local
.db_ctx
,
1346 table
->local
.lowest_id
,
1347 table
->local
.highest_id
,
1350 &session
->local_id
);
1351 if (!NT_STATUS_IS_OK(status
)) {
1352 TALLOC_FREE(session
);
1356 global
->session_wire_id
= session
->local_id
;
1359 global
->creation_time
= now
;
1360 global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1362 status
= smbXsrv_session_add_channel(session
, conn
, now
, &channel
);
1363 if (!NT_STATUS_IS_OK(status
)) {
1364 TALLOC_FREE(session
);
1369 val
= make_tdb_data((uint8_t const *)&ptr
, sizeof(ptr
));
1370 status
= dbwrap_record_store(local_rec
, val
, TDB_REPLACE
);
1371 TALLOC_FREE(local_rec
);
1372 if (!NT_STATUS_IS_OK(status
)) {
1373 TALLOC_FREE(session
);
1376 table
->local
.num_sessions
+= 1;
1378 talloc_set_destructor(session
, smbXsrv_session_destructor
);
1380 status
= smbXsrv_session_global_store(global
);
1381 if (!NT_STATUS_IS_OK(status
)) {
1382 DBG_ERR("global_id (0x%08x) store failed - %s\n",
1383 session
->global
->session_global_id
,
1385 TALLOC_FREE(session
);
1389 if (DEBUGLVL(DBGLVL_DEBUG
)) {
1390 struct smbXsrv_sessionB session_blob
= {
1391 .version
= SMBXSRV_VERSION_0
,
1392 .info
.info0
= session
,
1395 DBG_DEBUG("global_id (0x%08x) stored\n",
1396 session
->global
->session_global_id
);
1397 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1400 *_session
= session
;
1401 return NT_STATUS_OK
;
1404 NTSTATUS
smbXsrv_session_add_channel(struct smbXsrv_session
*session
,
1405 struct smbXsrv_connection
*conn
,
1407 struct smbXsrv_channel_global0
**_c
)
1409 struct smbXsrv_session_global0
*global
= session
->global
;
1410 struct smbXsrv_channel_global0
*c
= NULL
;
1412 if (global
->num_channels
> 31) {
1414 * Windows allow up to 32 channels
1416 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1419 c
= talloc_realloc(global
,
1421 struct smbXsrv_channel_global0
,
1422 global
->num_channels
+ 1);
1424 return NT_STATUS_NO_MEMORY
;
1426 global
->channels
= c
;
1428 c
= &global
->channels
[global
->num_channels
];
1430 *c
= (struct smbXsrv_channel_global0
){
1431 .server_id
= messaging_server_id(conn
->client
->msg_ctx
),
1432 .channel_id
= conn
->channel_id
,
1433 .creation_time
= now
,
1437 c
->local_address
= tsocket_address_string(conn
->local_address
,
1439 if (c
->local_address
== NULL
) {
1440 return NT_STATUS_NO_MEMORY
;
1442 c
->remote_address
= tsocket_address_string(conn
->remote_address
,
1444 if (c
->remote_address
== NULL
) {
1445 return NT_STATUS_NO_MEMORY
;
1447 c
->remote_name
= talloc_strdup(global
->channels
,
1448 conn
->remote_hostname
);
1449 if (c
->remote_name
== NULL
) {
1450 return NT_STATUS_NO_MEMORY
;
1453 global
->num_channels
+= 1;
1456 return NT_STATUS_OK
;
1459 NTSTATUS
smbXsrv_session_update(struct smbXsrv_session
*session
)
1461 struct smbXsrv_session_table
*table
= session
->table
;
1464 if (session
->global
->db_rec
!= NULL
) {
1465 DBG_ERR("smbXsrv_session_update(0x%08x): "
1466 "Called with db_rec != NULL'\n",
1467 session
->global
->session_global_id
);
1468 return NT_STATUS_INTERNAL_ERROR
;
1471 if (table
== NULL
) {
1472 DBG_ERR("smbXsrv_session_update(0x%08x): "
1473 "Called with table == NULL'\n",
1474 session
->global
->session_global_id
);
1475 return NT_STATUS_INTERNAL_ERROR
;
1478 session
->global
->db_rec
= smbXsrv_session_global_fetch_locked(
1479 table
->global
.db_ctx
,
1480 session
->global
->session_global_id
,
1481 session
->global
/* TALLOC_CTX */);
1482 if (session
->global
->db_rec
== NULL
) {
1483 return NT_STATUS_INTERNAL_DB_ERROR
;
1486 status
= smbXsrv_session_global_store(session
->global
);
1487 if (!NT_STATUS_IS_OK(status
)) {
1488 DBG_ERR("global_id (0x%08x) store failed - %s\n",
1489 session
->global
->session_global_id
,
1494 if (DEBUGLVL(DBGLVL_DEBUG
)) {
1495 struct smbXsrv_sessionB session_blob
= {
1496 .version
= SMBXSRV_VERSION_0
,
1497 .info
.info0
= session
,
1500 DBG_DEBUG("global_id (0x%08x) stored\n",
1501 session
->global
->session_global_id
);
1502 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1505 return NT_STATUS_OK
;
1508 NTSTATUS
smbXsrv_session_find_channel(const struct smbXsrv_session
*session
,
1509 const struct smbXsrv_connection
*conn
,
1510 struct smbXsrv_channel_global0
**_c
)
1514 for (i
=0; i
< session
->global
->num_channels
; i
++) {
1515 struct smbXsrv_channel_global0
*c
= &session
->global
->channels
[i
];
1517 if (c
->channel_id
!= conn
->channel_id
) {
1521 if (c
->connection
!= conn
) {
1526 return NT_STATUS_OK
;
1529 return NT_STATUS_USER_SESSION_DELETED
;
1532 NTSTATUS
smbXsrv_session_find_auth(const struct smbXsrv_session
*session
,
1533 const struct smbXsrv_connection
*conn
,
1535 struct smbXsrv_session_auth0
**_a
)
1537 struct smbXsrv_session_auth0
*a
;
1539 for (a
= session
->pending_auth
; a
!= NULL
; a
= a
->next
) {
1540 if (a
->channel_id
!= conn
->channel_id
) {
1544 if (a
->connection
== conn
) {
1549 return NT_STATUS_OK
;
1553 return NT_STATUS_USER_SESSION_DELETED
;
1556 static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0
*a
)
1558 if (a
->session
== NULL
) {
1562 DLIST_REMOVE(a
->session
->pending_auth
, a
);
1567 NTSTATUS
smbXsrv_session_create_auth(struct smbXsrv_session
*session
,
1568 struct smbXsrv_connection
*conn
,
1571 uint8_t in_security_mode
,
1572 struct smbXsrv_session_auth0
**_a
)
1574 struct smbXsrv_session_auth0
*a
;
1577 status
= smbXsrv_session_find_auth(session
, conn
, 0, &a
);
1578 if (NT_STATUS_IS_OK(status
)) {
1579 return NT_STATUS_INTERNAL_ERROR
;
1582 a
= talloc(session
, struct smbXsrv_session_auth0
);
1584 return NT_STATUS_NO_MEMORY
;
1587 *a
= (struct smbXsrv_session_auth0
){
1590 .in_flags
= in_flags
,
1591 .in_security_mode
= in_security_mode
,
1592 .creation_time
= now
,
1594 .channel_id
= conn
->channel_id
,
1597 if (conn
->protocol
>= PROTOCOL_SMB3_11
) {
1598 a
->preauth
= talloc(a
, struct smbXsrv_preauth
);
1599 if (a
->preauth
== NULL
) {
1600 TALLOC_FREE(session
);
1601 return NT_STATUS_NO_MEMORY
;
1603 *a
->preauth
= conn
->smb2
.preauth
;
1606 talloc_set_destructor(a
, smbXsrv_session_auth0_destructor
);
1607 DLIST_ADD_END(session
->pending_auth
, a
);
1610 return NT_STATUS_OK
;
1613 static void smbXsrv_session_remove_channel_done(struct tevent_req
*subreq
);
1615 NTSTATUS
smbXsrv_session_remove_channel(struct smbXsrv_session
*session
,
1616 struct smbXsrv_connection
*xconn
)
1618 struct smbXsrv_session_auth0
*a
= NULL
;
1619 struct smbXsrv_channel_global0
*c
= NULL
;
1621 bool need_update
= false;
1623 status
= smbXsrv_session_find_auth(session
, xconn
, 0, &a
);
1624 if (!NT_STATUS_IS_OK(status
)) {
1627 status
= smbXsrv_session_find_channel(session
, xconn
, &c
);
1628 if (!NT_STATUS_IS_OK(status
)) {
1633 smbXsrv_session_auth0_destructor(a
);
1634 a
->connection
= NULL
;
1639 struct smbXsrv_session_global0
*global
= session
->global
;
1642 n
= (c
- global
->channels
);
1643 if (n
>= global
->num_channels
|| n
< 0) {
1644 return NT_STATUS_INTERNAL_ERROR
;
1646 ARRAY_DEL_ELEMENT(global
->channels
, n
, global
->num_channels
);
1647 global
->num_channels
--;
1648 if (global
->num_channels
== 0) {
1649 struct smbXsrv_client
*client
= session
->client
;
1650 struct tevent_queue
*xconn_wait_queue
=
1651 xconn
->transport
.shutdown_wait_queue
;
1652 struct tevent_req
*subreq
= NULL
;
1655 * Let the connection wait until the session is
1658 * We don't set a callback, as we just want to block the
1659 * wait queue and the talloc_free() of the session will
1660 * remove the item from the wait queue in order
1661 * to remove allow the connection to disappear.
1663 if (xconn_wait_queue
!= NULL
) {
1664 subreq
= tevent_queue_wait_send(session
,
1667 if (subreq
== NULL
) {
1668 status
= NT_STATUS_NO_MEMORY
;
1669 DBG_ERR("tevent_queue_wait_send() "
1680 * This is guaranteed to set
1681 * session->status = NT_STATUS_USER_SESSION_DELETED
1682 * even if NULL is returned.
1684 subreq
= smb2srv_session_shutdown_send(session
,
1688 if (subreq
== NULL
) {
1689 status
= NT_STATUS_NO_MEMORY
;
1690 DBG_ERR("smb2srv_session_shutdown_send("
1691 "%" PRIu64
" failed: %s\n",
1692 session
->global
->session_wire_id
,
1696 tevent_req_set_callback(subreq
,
1697 smbXsrv_session_remove_channel_done
,
1704 return NT_STATUS_OK
;
1707 return smbXsrv_session_update(session
);
1710 static void smbXsrv_session_remove_channel_done(struct tevent_req
*subreq
)
1712 struct smbXsrv_session
*session
=
1713 tevent_req_callback_data(subreq
,
1714 struct smbXsrv_session
);
1717 status
= smb2srv_session_shutdown_recv(subreq
);
1718 TALLOC_FREE(subreq
);
1719 if (!NT_STATUS_IS_OK(status
)) {
1720 DBG_ERR("smb2srv_session_shutdown_recv(%" PRIu64
1722 session
->global
->session_wire_id
,
1726 status
= smbXsrv_session_logoff(session
);
1727 if (!NT_STATUS_IS_OK(status
)) {
1728 DBG_ERR("smbXsrv_session_logoff(%" PRIu64
") failed: %s\n",
1729 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
= NULL
;
1748 struct smb2srv_session_shutdown_state
*state
= NULL
;
1749 struct tevent_req
*subreq
= NULL
;
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 DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1872 "smb2srv_tcon_disconnect_all() failed: %s\n",
1873 session
->global
->session_global_id
,
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 DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1899 "failed to delete global key '%s': %s\n",
1900 session
->global
->session_global_id
,
1906 TALLOC_FREE(global_rec
);
1908 local_rec
= session
->db_rec
;
1909 if (local_rec
== NULL
) {
1910 local_rec
= smbXsrv_session_local_fetch_locked(
1911 table
->local
.db_ctx
,
1913 session
/* TALLOC_CTX */);
1914 if (local_rec
== NULL
) {
1915 error
= NT_STATUS_INTERNAL_ERROR
;
1919 if (local_rec
!= NULL
) {
1920 status
= dbwrap_record_delete(local_rec
);
1921 if (!NT_STATUS_IS_OK(status
)) {
1922 TDB_DATA key
= dbwrap_record_get_key(local_rec
);
1924 DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1925 "failed to delete local key '%s': %s\n",
1926 session
->global
->session_global_id
,
1931 table
->local
.num_sessions
-= 1;
1933 if (session
->db_rec
== NULL
) {
1934 TALLOC_FREE(local_rec
);
1936 session
->db_rec
= NULL
;
1941 struct smbXsrv_session_logoff_all_state
{
1942 NTSTATUS first_status
;
1946 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1947 void *private_data
);
1949 NTSTATUS
smbXsrv_session_logoff_all(struct smbXsrv_client
*client
)
1951 struct smbXsrv_session_table
*table
= client
->session_table
;
1952 struct smbXsrv_session_logoff_all_state state
= {};
1956 if (table
== NULL
) {
1957 DBG_DEBUG("empty session_table, nothing to do.\n");
1958 return NT_STATUS_OK
;
1961 status
= dbwrap_traverse(table
->local
.db_ctx
,
1962 smbXsrv_session_logoff_all_callback
,
1964 if (!NT_STATUS_IS_OK(status
)) {
1965 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status
));
1969 if (!NT_STATUS_IS_OK(state
.first_status
)) {
1970 DBG_ERR("count[%d] errors[%d] first[%s]\n",
1973 nt_errstr(state
.first_status
));
1974 return state
.first_status
;
1977 return NT_STATUS_OK
;
1980 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1983 struct smbXsrv_session_logoff_all_state
*state
=
1984 (struct smbXsrv_session_logoff_all_state
*)private_data
;
1987 struct smbXsrv_session
*session
= NULL
;
1990 val
= dbwrap_record_get_value(local_rec
);
1991 if (val
.dsize
!= sizeof(ptr
)) {
1992 status
= NT_STATUS_INTERNAL_ERROR
;
1993 if (NT_STATUS_IS_OK(state
->first_status
)) {
1994 state
->first_status
= status
;
2000 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2001 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2003 session
->db_rec
= local_rec
;
2004 status
= smbXsrv_session_clear_and_logoff(session
);
2005 session
->db_rec
= NULL
;
2006 if (!NT_STATUS_IS_OK(status
)) {
2007 if (NT_STATUS_IS_OK(state
->first_status
)) {
2008 state
->first_status
= status
;
2017 struct smbXsrv_session_local_trav_state
{
2019 int (*caller_cb
)(struct smbXsrv_session
*session
,
2024 static int smbXsrv_session_local_traverse_cb(struct db_record
*local_rec
,
2025 void *private_data
);
2027 NTSTATUS
smbXsrv_session_local_traverse(
2028 struct smbXsrv_client
*client
,
2029 int (*caller_cb
)(struct smbXsrv_session
*session
,
2033 struct smbXsrv_session_table
*table
= client
->session_table
;
2034 struct smbXsrv_session_local_trav_state state
;
2038 state
= (struct smbXsrv_session_local_trav_state
) {
2039 .status
= NT_STATUS_OK
,
2040 .caller_cb
= caller_cb
,
2041 .caller_data
= caller_data
,
2044 if (table
== NULL
) {
2045 DBG_DEBUG("empty session_table, nothing to do.\n");
2046 return NT_STATUS_OK
;
2049 status
= dbwrap_traverse(table
->local
.db_ctx
,
2050 smbXsrv_session_local_traverse_cb
,
2053 if (!NT_STATUS_IS_OK(status
)) {
2054 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status
));
2057 if (!NT_STATUS_IS_OK(state
.status
)) {
2058 DBG_ERR("count[%d] status[%s]\n",
2059 count
, nt_errstr(state
.status
));
2060 return state
.status
;
2063 return NT_STATUS_OK
;
2066 static int smbXsrv_session_local_traverse_cb(struct db_record
*local_rec
,
2069 struct smbXsrv_session_local_trav_state
*state
=
2070 (struct smbXsrv_session_local_trav_state
*)private_data
;
2073 struct smbXsrv_session
*session
= NULL
;
2076 val
= dbwrap_record_get_value(local_rec
);
2077 if (val
.dsize
!= sizeof(ptr
)) {
2078 state
->status
= NT_STATUS_INTERNAL_ERROR
;
2082 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2083 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2085 session
->db_rec
= local_rec
;
2086 ret
= state
->caller_cb(session
, state
->caller_data
);
2087 session
->db_rec
= NULL
;
2092 struct smbXsrv_session_disconnect_xconn_state
{
2093 struct smbXsrv_connection
*xconn
;
2094 NTSTATUS first_status
;
2098 static int smbXsrv_session_disconnect_xconn_callback(struct db_record
*local_rec
,
2099 void *private_data
);
2101 NTSTATUS
smbXsrv_session_disconnect_xconn(struct smbXsrv_connection
*xconn
)
2103 struct smbXsrv_client
*client
= xconn
->client
;
2104 struct smbXsrv_session_table
*table
= client
->session_table
;
2105 struct smbXsrv_session_disconnect_xconn_state state
= {
2111 if (table
== NULL
) {
2112 DBG_ERR("empty session_table, nothing to do.\n");
2113 return NT_STATUS_OK
;
2116 status
= dbwrap_traverse(table
->local
.db_ctx
,
2117 smbXsrv_session_disconnect_xconn_callback
,
2119 if (!NT_STATUS_IS_OK(status
)) {
2120 DBG_ERR("dbwrap_traverse() failed: %s\n",
2125 if (!NT_STATUS_IS_OK(state
.first_status
)) {
2126 DBG_ERR("count[%d] errors[%d] first[%s]\n",
2127 count
, state
.errors
,
2128 nt_errstr(state
.first_status
));
2129 return state
.first_status
;
2132 return NT_STATUS_OK
;
2135 static int smbXsrv_session_disconnect_xconn_callback(struct db_record
*local_rec
,
2138 struct smbXsrv_session_disconnect_xconn_state
*state
=
2139 (struct smbXsrv_session_disconnect_xconn_state
*)private_data
;
2142 struct smbXsrv_session
*session
= NULL
;
2145 val
= dbwrap_record_get_value(local_rec
);
2146 if (val
.dsize
!= sizeof(ptr
)) {
2147 status
= NT_STATUS_INTERNAL_ERROR
;
2148 if (NT_STATUS_IS_OK(state
->first_status
)) {
2149 state
->first_status
= status
;
2155 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2156 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2158 session
->db_rec
= local_rec
;
2159 status
= smbXsrv_session_remove_channel(session
, state
->xconn
);
2160 session
->db_rec
= NULL
;
2161 if (!NT_STATUS_IS_OK(status
)) {
2162 if (NT_STATUS_IS_OK(state
->first_status
)) {
2163 state
->first_status
= status
;
2171 NTSTATUS
smb1srv_session_table_init(struct smbXsrv_connection
*conn
)
2174 * Allow a range from 1..65534 with 65534 values.
2176 return smbXsrv_session_table_init(conn
, 1, UINT16_MAX
- 1,
2180 NTSTATUS
smb1srv_session_lookup(struct smbXsrv_connection
*conn
,
2181 uint16_t vuid
, NTTIME now
,
2182 struct smbXsrv_session
**session
)
2184 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
2185 uint32_t local_id
= vuid
;
2187 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
2191 NTSTATUS
smbXsrv_session_info_lookup(struct smbXsrv_client
*client
,
2192 uint64_t session_wire_id
,
2193 struct auth_session_info
**si
)
2195 struct smbXsrv_session_table
*table
= client
->session_table
;
2196 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
2197 struct smbXsrv_session_local_fetch_state state
= {
2198 .status
= NT_STATUS_INTERNAL_ERROR
,
2203 if (session_wire_id
== 0) {
2204 return NT_STATUS_USER_SESSION_DELETED
;
2207 if (table
== NULL
) {
2208 /* this might happen before the end of negprot */
2209 return NT_STATUS_USER_SESSION_DELETED
;
2212 if (table
->local
.db_ctx
== NULL
) {
2213 return NT_STATUS_INTERNAL_ERROR
;
2216 key
= smbXsrv_session_local_id_to_key(session_wire_id
, key_buf
);
2218 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
2219 smbXsrv_session_local_fetch_parser
,
2221 if (!NT_STATUS_IS_OK(status
)) {
2224 if (!NT_STATUS_IS_OK(state
.status
)) {
2225 return state
.status
;
2227 if (state
.session
->global
->auth_session_info
== NULL
) {
2228 return NT_STATUS_USER_SESSION_DELETED
;
2231 *si
= state
.session
->global
->auth_session_info
;
2232 return NT_STATUS_OK
;
2236 * In memory of get_valid_user_struct()
2238 * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
2239 * but it doesn't implement the state checks of
2240 * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
2241 * session wire-id of incoming SMB requests, it MUST only be used in later
2242 * internal processing where the session wire-id has already been validated.
2244 NTSTATUS
get_valid_smbXsrv_session(struct smbXsrv_client
*client
,
2245 uint64_t session_wire_id
,
2246 struct smbXsrv_session
**session
)
2248 struct smbXsrv_session_table
*table
= client
->session_table
;
2249 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
2250 struct smbXsrv_session_local_fetch_state state
= {
2251 .status
= NT_STATUS_INTERNAL_ERROR
,
2256 if (session_wire_id
== 0) {
2257 return NT_STATUS_USER_SESSION_DELETED
;
2260 if (table
== NULL
) {
2261 /* this might happen before the end of negprot */
2262 return NT_STATUS_USER_SESSION_DELETED
;
2265 if (table
->local
.db_ctx
== NULL
) {
2266 return NT_STATUS_INTERNAL_ERROR
;
2269 key
= smbXsrv_session_local_id_to_key(session_wire_id
, key_buf
);
2271 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
2272 smbXsrv_session_local_fetch_parser
,
2274 if (!NT_STATUS_IS_OK(status
)) {
2277 if (!NT_STATUS_IS_OK(state
.status
)) {
2278 return state
.status
;
2280 if (state
.session
->global
->auth_session_info
== NULL
) {
2281 return NT_STATUS_USER_SESSION_DELETED
;
2284 *session
= state
.session
;
2285 return NT_STATUS_OK
;
2288 NTSTATUS
smb2srv_session_lookup_global(struct smbXsrv_client
*client
,
2289 uint64_t session_wire_id
,
2290 TALLOC_CTX
*mem_ctx
,
2291 struct smbXsrv_session
**_session
)
2293 TALLOC_CTX
*frame
= talloc_stackframe();
2294 struct smbXsrv_session_table
*table
= client
->session_table
;
2295 uint32_t global_id
= session_wire_id
& UINT32_MAX
;
2296 uint64_t global_zeros
= session_wire_id
& 0xFFFFFFFF00000000LLU
;
2297 struct smbXsrv_session
*session
= NULL
;
2298 struct db_record
*global_rec
= NULL
;
2299 bool is_free
= false;
2302 if (global_id
== 0) {
2304 return NT_STATUS_USER_SESSION_DELETED
;
2306 if (global_zeros
!= 0) {
2308 return NT_STATUS_USER_SESSION_DELETED
;
2311 if (table
== NULL
) {
2312 /* this might happen before the end of negprot */
2314 return NT_STATUS_USER_SESSION_DELETED
;
2317 if (table
->global
.db_ctx
== NULL
) {
2319 return NT_STATUS_INTERNAL_ERROR
;
2322 session
= talloc_zero(mem_ctx
, struct smbXsrv_session
);
2323 if (session
== NULL
) {
2325 return NT_STATUS_NO_MEMORY
;
2327 talloc_steal(frame
, session
);
2329 session
->client
= client
;
2330 session
->status
= NT_STATUS_BAD_LOGON_SESSION_STATE
;
2331 session
->local_id
= global_id
;
2334 * This means smb2_get_new_nonce() will return
2335 * NT_STATUS_ENCRYPTION_FAILED.
2337 * But we initialize some random parts just in case...
2339 session
->nonce_high_max
= session
->nonce_high
= 0;
2340 generate_nonce_buffer((uint8_t *)&session
->nonce_high_random
,
2341 sizeof(session
->nonce_high_random
));
2342 generate_nonce_buffer((uint8_t *)&session
->nonce_low
,
2343 sizeof(session
->nonce_low
));
2345 global_rec
= smbXsrv_session_global_fetch_locked(table
->global
.db_ctx
,
2348 if (global_rec
== NULL
) {
2350 return NT_STATUS_INTERNAL_DB_ERROR
;
2353 smbXsrv_session_global_verify_record(global_rec
,
2361 return NT_STATUS_USER_SESSION_DELETED
;
2365 * We don't have channels on this session
2366 * and only the main signing key
2368 session
->global
->num_channels
= 0;
2369 status
= smb2_signing_key_sign_create(session
->global
,
2370 session
->global
->signing_algo
,
2371 NULL
, /* no master key */
2372 NULL
, /* derivations */
2373 &session
->global
->signing_key
);
2374 if (!NT_STATUS_IS_OK(status
)) {
2376 return NT_STATUS_NO_MEMORY
;
2378 session
->global
->signing_key
->blob
= session
->global
->signing_key_blob
;
2379 session
->global
->signing_flags
= 0;
2381 status
= smb2_signing_key_cipher_create(session
->global
,
2382 session
->global
->encryption_cipher
,
2383 NULL
, /* no master key */
2384 NULL
, /* derivations */
2385 &session
->global
->decryption_key
);
2386 if (!NT_STATUS_IS_OK(status
)) {
2388 return NT_STATUS_NO_MEMORY
;
2390 session
->global
->decryption_key
->blob
= session
->global
->decryption_key_blob
;
2391 session
->global
->encryption_flags
= 0;
2393 *_session
= talloc_move(mem_ctx
, &session
);
2395 return NT_STATUS_OK
;
2398 NTSTATUS
smb2srv_session_table_init(struct smbXsrv_connection
*conn
)
2401 * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
2403 return smbXsrv_session_table_init(conn
, 1, UINT32_MAX
- 1,
2407 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
2408 /* conn: optional */
2409 struct smbXsrv_connection
*conn
,
2410 uint64_t session_id
, NTTIME now
,
2411 struct smbXsrv_session
**session
)
2413 uint32_t local_id
= session_id
& UINT32_MAX
;
2414 uint64_t local_zeros
= session_id
& 0xFFFFFFFF00000000LLU
;
2416 if (local_zeros
!= 0) {
2417 return NT_STATUS_USER_SESSION_DELETED
;
2420 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
2424 NTSTATUS
smb2srv_session_lookup_conn(struct smbXsrv_connection
*conn
,
2425 uint64_t session_id
, NTTIME now
,
2426 struct smbXsrv_session
**session
)
2428 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
2429 return smb2srv_session_lookup_raw(table
, conn
, session_id
, now
,
2433 NTSTATUS
smb2srv_session_lookup_client(struct smbXsrv_client
*client
,
2434 uint64_t session_id
, NTTIME now
,
2435 struct smbXsrv_session
**session
)
2437 struct smbXsrv_session_table
*table
= client
->session_table
;
2438 return smb2srv_session_lookup_raw(table
, NULL
, session_id
, now
,
2442 struct smbXsrv_session_global_traverse_state
{
2443 int (*fn
)(struct smbXsrv_session_global0
*, void *);
2447 static int smbXsrv_session_global_traverse_fn(struct db_record
*rec
, void *data
)
2450 struct smbXsrv_session_global_traverse_state
*state
=
2451 (struct smbXsrv_session_global_traverse_state
*)data
;
2452 TDB_DATA key
= dbwrap_record_get_key(rec
);
2453 TDB_DATA val
= dbwrap_record_get_value(rec
);
2454 DATA_BLOB blob
= data_blob_const(val
.dptr
, val
.dsize
);
2455 struct smbXsrv_session_globalB global_blob
;
2456 enum ndr_err_code ndr_err
;
2457 TALLOC_CTX
*frame
= talloc_stackframe();
2459 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
2460 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
2461 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2462 DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2463 "key '%s' ndr_pull_struct_blob - %s\n",
2465 ndr_errstr(ndr_err
));
2469 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
2470 DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2471 "key '%s' unsupported version - %d\n",
2473 (int)global_blob
.version
);
2477 if (global_blob
.info
.info0
== NULL
) {
2478 DBG_WARNING("Invalid record in smbXsrv_tcon_global.tdb:"
2479 "key '%s' info0 NULL pointer\n",
2484 global_blob
.info
.info0
->db_rec
= rec
;
2485 ret
= state
->fn(global_blob
.info
.info0
, state
->private_data
);
2491 NTSTATUS
smbXsrv_session_global_traverse(
2492 int (*fn
)(struct smbXsrv_session_global0
*, void *),
2498 struct smbXsrv_session_global_traverse_state state
= {
2500 .private_data
= private_data
,
2504 status
= smbXsrv_session_global_init(NULL
);
2505 if (!NT_STATUS_IS_OK(status
)) {
2507 DBG_ERR("Failed to initialize session_global: %s\n",
2512 status
= dbwrap_traverse_read(smbXsrv_session_global_db_ctx
,
2513 smbXsrv_session_global_traverse_fn
,