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 check_for_lease_break_fsp_cmp_state
{
1743 struct smbXsrv_session
*session
;
1746 static bool check_for_lease_break_fsp_cmp_fn(struct files_struct
*fsp
,
1749 struct check_for_lease_break_fsp_cmp_state
*state
=
1750 (struct check_for_lease_break_fsp_cmp_state
*)private_data
;
1752 return (fsp
->vuid
== state
->session
->global
->session_wire_id
);
1755 struct tevent_req
*smb2srv_session_shutdown_send(TALLOC_CTX
*mem_ctx
,
1756 struct tevent_context
*ev
,
1757 struct smbXsrv_session
*session
,
1758 struct smbd_smb2_request
*current_req
)
1760 struct tevent_req
*req
= NULL
;
1761 struct smb2srv_session_shutdown_state
*state
= NULL
;
1762 struct tevent_req
*subreq
= NULL
;
1763 struct smbXsrv_connection
*xconn
= NULL
;
1764 struct check_for_lease_break_fsp_cmp_state fsp_cmp_state
;
1768 * Make sure that no new request will be able to use this session.
1770 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1772 req
= tevent_req_create(mem_ctx
, &state
,
1773 struct smb2srv_session_shutdown_state
);
1778 state
->wait_queue
= tevent_queue_create(state
, "smb2srv_session_shutdown_queue");
1779 if (tevent_req_nomem(state
->wait_queue
, req
)) {
1780 return tevent_req_post(req
, ev
);
1783 for (xconn
= session
->client
->connections
; xconn
!= NULL
; xconn
= xconn
->next
) {
1784 struct smbd_smb2_request
*preq
;
1786 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1787 if (preq
== current_req
) {
1788 /* Can't cancel current request. */
1791 if (preq
->session
!= session
) {
1792 /* Request on different session. */
1796 if (preq
->subreq
!= NULL
) {
1797 tevent_req_cancel(preq
->subreq
);
1801 * Now wait until the request is finished.
1803 * We don't set a callback, as we just want to block the
1804 * wait queue and the talloc_free() of the request will
1805 * remove the item from the wait queue.
1807 subreq
= tevent_queue_wait_send(preq
, ev
, state
->wait_queue
);
1808 if (tevent_req_nomem(subreq
, req
)) {
1809 return tevent_req_post(req
, ev
);
1814 fsp_cmp_state
= (struct check_for_lease_break_fsp_cmp_state
) {
1818 smbXsrv_wait_for_handle_lease_break(
1823 check_for_lease_break_fsp_cmp_fn
,
1825 if (!tevent_req_is_in_progress(req
)) {
1826 return tevent_req_post(req
, ev
);
1829 len
= tevent_queue_length(state
->wait_queue
);
1831 tevent_req_done(req
);
1832 return tevent_req_post(req
, ev
);
1836 * Now we add our own waiter to the end of the queue,
1837 * this way we get notified when all pending requests are finished
1838 * and send to the socket.
1840 subreq
= tevent_queue_wait_send(state
, ev
, state
->wait_queue
);
1841 if (tevent_req_nomem(subreq
, req
)) {
1842 return tevent_req_post(req
, ev
);
1844 tevent_req_set_callback(subreq
, smb2srv_session_shutdown_wait_done
, req
);
1849 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
)
1851 struct tevent_req
*req
=
1852 tevent_req_callback_data(subreq
,
1855 tevent_queue_wait_recv(subreq
);
1856 TALLOC_FREE(subreq
);
1858 tevent_req_done(req
);
1861 NTSTATUS
smb2srv_session_shutdown_recv(struct tevent_req
*req
)
1863 return tevent_req_simple_recv_ntstatus(req
);
1866 NTSTATUS
smbXsrv_session_logoff(struct smbXsrv_session
*session
)
1868 struct smbXsrv_session_table
*table
;
1869 struct db_record
*local_rec
= NULL
;
1870 struct db_record
*global_rec
= NULL
;
1871 struct smbd_server_connection
*sconn
= NULL
;
1873 NTSTATUS error
= NT_STATUS_OK
;
1875 if (session
->table
== NULL
) {
1876 return NT_STATUS_OK
;
1879 table
= session
->table
;
1880 session
->table
= NULL
;
1882 sconn
= session
->client
->sconn
;
1883 session
->client
= NULL
;
1884 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1887 * For SMB2 this is a bit redundant as files are also close
1888 * below via smb2srv_tcon_disconnect_all() -> ... ->
1889 * smbXsrv_tcon_disconnect() -> close_cnum() ->
1890 * file_close_conn().
1892 file_close_user(sconn
, session
->global
->session_wire_id
);
1894 if (session
->tcon_table
!= NULL
) {
1896 * Note: We only have a tcon_table for SMB2.
1898 status
= smb2srv_tcon_disconnect_all(session
);
1899 if (!NT_STATUS_IS_OK(status
)) {
1900 DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1901 "smb2srv_tcon_disconnect_all() failed: %s\n",
1902 session
->global
->session_global_id
,
1908 invalidate_vuid(sconn
, session
->global
->session_wire_id
);
1910 global_rec
= session
->global
->db_rec
;
1911 session
->global
->db_rec
= NULL
;
1912 if (global_rec
== NULL
) {
1913 global_rec
= smbXsrv_session_global_fetch_locked(
1914 table
->global
.db_ctx
,
1915 session
->global
->session_global_id
,
1916 session
->global
/* TALLOC_CTX */);
1917 if (global_rec
== NULL
) {
1918 error
= NT_STATUS_INTERNAL_ERROR
;
1922 if (global_rec
!= NULL
) {
1923 status
= dbwrap_record_delete(global_rec
);
1924 if (!NT_STATUS_IS_OK(status
)) {
1925 TDB_DATA key
= dbwrap_record_get_key(global_rec
);
1927 DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1928 "failed to delete global key '%s': %s\n",
1929 session
->global
->session_global_id
,
1935 TALLOC_FREE(global_rec
);
1937 local_rec
= session
->db_rec
;
1938 if (local_rec
== NULL
) {
1939 local_rec
= smbXsrv_session_local_fetch_locked(
1940 table
->local
.db_ctx
,
1942 session
/* TALLOC_CTX */);
1943 if (local_rec
== NULL
) {
1944 error
= NT_STATUS_INTERNAL_ERROR
;
1948 if (local_rec
!= NULL
) {
1949 status
= dbwrap_record_delete(local_rec
);
1950 if (!NT_STATUS_IS_OK(status
)) {
1951 TDB_DATA key
= dbwrap_record_get_key(local_rec
);
1953 DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1954 "failed to delete local key '%s': %s\n",
1955 session
->global
->session_global_id
,
1960 table
->local
.num_sessions
-= 1;
1962 if (session
->db_rec
== NULL
) {
1963 TALLOC_FREE(local_rec
);
1965 session
->db_rec
= NULL
;
1970 struct smbXsrv_session_logoff_all_state
{
1971 NTSTATUS first_status
;
1975 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1976 void *private_data
);
1978 NTSTATUS
smbXsrv_session_logoff_all(struct smbXsrv_client
*client
)
1980 struct smbXsrv_session_table
*table
= client
->session_table
;
1981 struct smbXsrv_session_logoff_all_state state
= {};
1985 if (table
== NULL
) {
1986 DBG_DEBUG("empty session_table, nothing to do.\n");
1987 return NT_STATUS_OK
;
1990 status
= dbwrap_traverse(table
->local
.db_ctx
,
1991 smbXsrv_session_logoff_all_callback
,
1993 if (!NT_STATUS_IS_OK(status
)) {
1994 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status
));
1998 if (!NT_STATUS_IS_OK(state
.first_status
)) {
1999 DBG_ERR("count[%d] errors[%d] first[%s]\n",
2002 nt_errstr(state
.first_status
));
2003 return state
.first_status
;
2006 return NT_STATUS_OK
;
2009 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
2012 struct smbXsrv_session_logoff_all_state
*state
=
2013 (struct smbXsrv_session_logoff_all_state
*)private_data
;
2016 struct smbXsrv_session
*session
= NULL
;
2019 val
= dbwrap_record_get_value(local_rec
);
2020 if (val
.dsize
!= sizeof(ptr
)) {
2021 status
= NT_STATUS_INTERNAL_ERROR
;
2022 if (NT_STATUS_IS_OK(state
->first_status
)) {
2023 state
->first_status
= status
;
2029 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2030 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2032 session
->db_rec
= local_rec
;
2033 status
= smbXsrv_session_clear_and_logoff(session
);
2034 session
->db_rec
= NULL
;
2035 if (!NT_STATUS_IS_OK(status
)) {
2036 if (NT_STATUS_IS_OK(state
->first_status
)) {
2037 state
->first_status
= status
;
2046 struct smbXsrv_session_local_trav_state
{
2048 int (*caller_cb
)(struct smbXsrv_session
*session
,
2053 static int smbXsrv_session_local_traverse_cb(struct db_record
*local_rec
,
2054 void *private_data
);
2056 NTSTATUS
smbXsrv_session_local_traverse(
2057 struct smbXsrv_client
*client
,
2058 int (*caller_cb
)(struct smbXsrv_session
*session
,
2062 struct smbXsrv_session_table
*table
= client
->session_table
;
2063 struct smbXsrv_session_local_trav_state state
;
2067 state
= (struct smbXsrv_session_local_trav_state
) {
2068 .status
= NT_STATUS_OK
,
2069 .caller_cb
= caller_cb
,
2070 .caller_data
= caller_data
,
2073 if (table
== NULL
) {
2074 DBG_DEBUG("empty session_table, nothing to do.\n");
2075 return NT_STATUS_OK
;
2078 status
= dbwrap_traverse(table
->local
.db_ctx
,
2079 smbXsrv_session_local_traverse_cb
,
2082 if (!NT_STATUS_IS_OK(status
)) {
2083 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status
));
2086 if (!NT_STATUS_IS_OK(state
.status
)) {
2087 DBG_ERR("count[%d] status[%s]\n",
2088 count
, nt_errstr(state
.status
));
2089 return state
.status
;
2092 return NT_STATUS_OK
;
2095 static int smbXsrv_session_local_traverse_cb(struct db_record
*local_rec
,
2098 struct smbXsrv_session_local_trav_state
*state
=
2099 (struct smbXsrv_session_local_trav_state
*)private_data
;
2102 struct smbXsrv_session
*session
= NULL
;
2105 val
= dbwrap_record_get_value(local_rec
);
2106 if (val
.dsize
!= sizeof(ptr
)) {
2107 state
->status
= NT_STATUS_INTERNAL_ERROR
;
2111 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2112 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2114 session
->db_rec
= local_rec
;
2115 ret
= state
->caller_cb(session
, state
->caller_data
);
2116 session
->db_rec
= NULL
;
2121 struct smbXsrv_session_disconnect_xconn_state
{
2122 struct smbXsrv_connection
*xconn
;
2123 NTSTATUS first_status
;
2127 static int smbXsrv_session_disconnect_xconn_callback(struct db_record
*local_rec
,
2128 void *private_data
);
2130 NTSTATUS
smbXsrv_session_disconnect_xconn(struct smbXsrv_connection
*xconn
)
2132 struct smbXsrv_client
*client
= xconn
->client
;
2133 struct smbXsrv_session_table
*table
= client
->session_table
;
2134 struct smbXsrv_session_disconnect_xconn_state state
= {
2140 if (table
== NULL
) {
2141 DBG_ERR("empty session_table, nothing to do.\n");
2142 return NT_STATUS_OK
;
2145 status
= dbwrap_traverse(table
->local
.db_ctx
,
2146 smbXsrv_session_disconnect_xconn_callback
,
2148 if (!NT_STATUS_IS_OK(status
)) {
2149 DBG_ERR("dbwrap_traverse() failed: %s\n",
2154 if (!NT_STATUS_IS_OK(state
.first_status
)) {
2155 DBG_ERR("count[%d] errors[%d] first[%s]\n",
2156 count
, state
.errors
,
2157 nt_errstr(state
.first_status
));
2158 return state
.first_status
;
2161 return NT_STATUS_OK
;
2164 static int smbXsrv_session_disconnect_xconn_callback(struct db_record
*local_rec
,
2167 struct smbXsrv_session_disconnect_xconn_state
*state
=
2168 (struct smbXsrv_session_disconnect_xconn_state
*)private_data
;
2171 struct smbXsrv_session
*session
= NULL
;
2174 val
= dbwrap_record_get_value(local_rec
);
2175 if (val
.dsize
!= sizeof(ptr
)) {
2176 status
= NT_STATUS_INTERNAL_ERROR
;
2177 if (NT_STATUS_IS_OK(state
->first_status
)) {
2178 state
->first_status
= status
;
2184 memcpy(&ptr
, val
.dptr
, val
.dsize
);
2185 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
2187 session
->db_rec
= local_rec
;
2188 status
= smbXsrv_session_remove_channel(session
, state
->xconn
);
2189 session
->db_rec
= NULL
;
2190 if (!NT_STATUS_IS_OK(status
)) {
2191 if (NT_STATUS_IS_OK(state
->first_status
)) {
2192 state
->first_status
= status
;
2200 NTSTATUS
smb1srv_session_table_init(struct smbXsrv_connection
*conn
)
2203 * Allow a range from 1..65534 with 65534 values.
2205 return smbXsrv_session_table_init(conn
, 1, UINT16_MAX
- 1,
2209 NTSTATUS
smb1srv_session_lookup(struct smbXsrv_connection
*conn
,
2210 uint16_t vuid
, NTTIME now
,
2211 struct smbXsrv_session
**session
)
2213 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
2214 uint32_t local_id
= vuid
;
2216 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
2220 NTSTATUS
smbXsrv_session_info_lookup(struct smbXsrv_client
*client
,
2221 uint64_t session_wire_id
,
2222 struct auth_session_info
**si
)
2224 struct smbXsrv_session_table
*table
= client
->session_table
;
2225 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
2226 struct smbXsrv_session_local_fetch_state state
= {
2227 .status
= NT_STATUS_INTERNAL_ERROR
,
2232 if (session_wire_id
== 0) {
2233 return NT_STATUS_USER_SESSION_DELETED
;
2236 if (table
== NULL
) {
2237 /* this might happen before the end of negprot */
2238 return NT_STATUS_USER_SESSION_DELETED
;
2241 if (table
->local
.db_ctx
== NULL
) {
2242 return NT_STATUS_INTERNAL_ERROR
;
2245 key
= smbXsrv_session_local_id_to_key(session_wire_id
, key_buf
);
2247 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
2248 smbXsrv_session_local_fetch_parser
,
2250 if (!NT_STATUS_IS_OK(status
)) {
2253 if (!NT_STATUS_IS_OK(state
.status
)) {
2254 return state
.status
;
2256 if (state
.session
->global
->auth_session_info
== NULL
) {
2257 return NT_STATUS_USER_SESSION_DELETED
;
2260 *si
= state
.session
->global
->auth_session_info
;
2261 return NT_STATUS_OK
;
2265 * In memory of get_valid_user_struct()
2267 * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
2268 * but it doesn't implement the state checks of
2269 * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
2270 * session wire-id of incoming SMB requests, it MUST only be used in later
2271 * internal processing where the session wire-id has already been validated.
2273 NTSTATUS
get_valid_smbXsrv_session(struct smbXsrv_client
*client
,
2274 uint64_t session_wire_id
,
2275 struct smbXsrv_session
**session
)
2277 struct smbXsrv_session_table
*table
= client
->session_table
;
2278 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
2279 struct smbXsrv_session_local_fetch_state state
= {
2280 .status
= NT_STATUS_INTERNAL_ERROR
,
2285 if (session_wire_id
== 0) {
2286 return NT_STATUS_USER_SESSION_DELETED
;
2289 if (table
== NULL
) {
2290 /* this might happen before the end of negprot */
2291 return NT_STATUS_USER_SESSION_DELETED
;
2294 if (table
->local
.db_ctx
== NULL
) {
2295 return NT_STATUS_INTERNAL_ERROR
;
2298 key
= smbXsrv_session_local_id_to_key(session_wire_id
, key_buf
);
2300 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
2301 smbXsrv_session_local_fetch_parser
,
2303 if (!NT_STATUS_IS_OK(status
)) {
2306 if (!NT_STATUS_IS_OK(state
.status
)) {
2307 return state
.status
;
2309 if (state
.session
->global
->auth_session_info
== NULL
) {
2310 return NT_STATUS_USER_SESSION_DELETED
;
2313 *session
= state
.session
;
2314 return NT_STATUS_OK
;
2317 NTSTATUS
smb2srv_session_lookup_global(struct smbXsrv_client
*client
,
2318 uint64_t session_wire_id
,
2319 TALLOC_CTX
*mem_ctx
,
2320 struct smbXsrv_session
**_session
)
2322 TALLOC_CTX
*frame
= talloc_stackframe();
2323 struct smbXsrv_session_table
*table
= client
->session_table
;
2324 uint32_t global_id
= session_wire_id
& UINT32_MAX
;
2325 uint64_t global_zeros
= session_wire_id
& 0xFFFFFFFF00000000LLU
;
2326 struct smbXsrv_session
*session
= NULL
;
2327 struct db_record
*global_rec
= NULL
;
2328 bool is_free
= false;
2331 if (global_id
== 0) {
2333 return NT_STATUS_USER_SESSION_DELETED
;
2335 if (global_zeros
!= 0) {
2337 return NT_STATUS_USER_SESSION_DELETED
;
2340 if (table
== NULL
) {
2341 /* this might happen before the end of negprot */
2343 return NT_STATUS_USER_SESSION_DELETED
;
2346 if (table
->global
.db_ctx
== NULL
) {
2348 return NT_STATUS_INTERNAL_ERROR
;
2351 session
= talloc_zero(mem_ctx
, struct smbXsrv_session
);
2352 if (session
== NULL
) {
2354 return NT_STATUS_NO_MEMORY
;
2356 talloc_steal(frame
, session
);
2358 session
->client
= client
;
2359 session
->status
= NT_STATUS_BAD_LOGON_SESSION_STATE
;
2360 session
->local_id
= global_id
;
2363 * This means smb2_get_new_nonce() will return
2364 * NT_STATUS_ENCRYPTION_FAILED.
2366 * But we initialize some random parts just in case...
2368 session
->nonce_high_max
= session
->nonce_high
= 0;
2369 generate_nonce_buffer((uint8_t *)&session
->nonce_high_random
,
2370 sizeof(session
->nonce_high_random
));
2371 generate_nonce_buffer((uint8_t *)&session
->nonce_low
,
2372 sizeof(session
->nonce_low
));
2374 global_rec
= smbXsrv_session_global_fetch_locked(table
->global
.db_ctx
,
2377 if (global_rec
== NULL
) {
2379 return NT_STATUS_INTERNAL_DB_ERROR
;
2382 smbXsrv_session_global_verify_record(global_rec
,
2390 return NT_STATUS_USER_SESSION_DELETED
;
2394 * We don't have channels on this session
2395 * and only the main signing key
2397 session
->global
->num_channels
= 0;
2398 status
= smb2_signing_key_sign_create(session
->global
,
2399 session
->global
->signing_algo
,
2400 NULL
, /* no master key */
2401 NULL
, /* derivations */
2402 &session
->global
->signing_key
);
2403 if (!NT_STATUS_IS_OK(status
)) {
2405 return NT_STATUS_NO_MEMORY
;
2407 session
->global
->signing_key
->blob
= session
->global
->signing_key_blob
;
2408 session
->global
->signing_flags
= 0;
2410 status
= smb2_signing_key_cipher_create(session
->global
,
2411 session
->global
->encryption_cipher
,
2412 NULL
, /* no master key */
2413 NULL
, /* derivations */
2414 &session
->global
->decryption_key
);
2415 if (!NT_STATUS_IS_OK(status
)) {
2417 return NT_STATUS_NO_MEMORY
;
2419 session
->global
->decryption_key
->blob
= session
->global
->decryption_key_blob
;
2420 session
->global
->encryption_flags
= 0;
2422 *_session
= talloc_move(mem_ctx
, &session
);
2424 return NT_STATUS_OK
;
2427 NTSTATUS
smb2srv_session_table_init(struct smbXsrv_connection
*conn
)
2430 * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
2432 return smbXsrv_session_table_init(conn
, 1, UINT32_MAX
- 1,
2436 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
2437 /* conn: optional */
2438 struct smbXsrv_connection
*conn
,
2439 uint64_t session_id
, NTTIME now
,
2440 struct smbXsrv_session
**session
)
2442 uint32_t local_id
= session_id
& UINT32_MAX
;
2443 uint64_t local_zeros
= session_id
& 0xFFFFFFFF00000000LLU
;
2445 if (local_zeros
!= 0) {
2446 return NT_STATUS_USER_SESSION_DELETED
;
2449 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
2453 NTSTATUS
smb2srv_session_lookup_conn(struct smbXsrv_connection
*conn
,
2454 uint64_t session_id
, NTTIME now
,
2455 struct smbXsrv_session
**session
)
2457 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
2458 return smb2srv_session_lookup_raw(table
, conn
, session_id
, now
,
2462 NTSTATUS
smb2srv_session_lookup_client(struct smbXsrv_client
*client
,
2463 uint64_t session_id
, NTTIME now
,
2464 struct smbXsrv_session
**session
)
2466 struct smbXsrv_session_table
*table
= client
->session_table
;
2467 return smb2srv_session_lookup_raw(table
, NULL
, session_id
, now
,
2471 struct smbXsrv_session_global_traverse_state
{
2472 int (*fn
)(struct smbXsrv_session_global0
*, void *);
2476 static int smbXsrv_session_global_traverse_fn(struct db_record
*rec
, void *data
)
2479 struct smbXsrv_session_global_traverse_state
*state
=
2480 (struct smbXsrv_session_global_traverse_state
*)data
;
2481 TDB_DATA key
= dbwrap_record_get_key(rec
);
2482 TDB_DATA val
= dbwrap_record_get_value(rec
);
2483 DATA_BLOB blob
= data_blob_const(val
.dptr
, val
.dsize
);
2484 struct smbXsrv_session_globalB global_blob
;
2485 enum ndr_err_code ndr_err
;
2486 TALLOC_CTX
*frame
= talloc_stackframe();
2488 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
2489 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
2490 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2491 DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2492 "key '%s' ndr_pull_struct_blob - %s\n",
2494 ndr_errstr(ndr_err
));
2498 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
2499 DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2500 "key '%s' unsupported version - %d\n",
2502 (int)global_blob
.version
);
2506 if (global_blob
.info
.info0
== NULL
) {
2507 DBG_WARNING("Invalid record in smbXsrv_tcon_global.tdb:"
2508 "key '%s' info0 NULL pointer\n",
2513 global_blob
.info
.info0
->db_rec
= rec
;
2514 ret
= state
->fn(global_blob
.info
.info0
, state
->private_data
);
2520 NTSTATUS
smbXsrv_session_global_traverse(
2521 int (*fn
)(struct smbXsrv_session_global0
*, void *),
2527 struct smbXsrv_session_global_traverse_state state
= {
2529 .private_data
= private_data
,
2533 status
= smbXsrv_session_global_init(NULL
);
2534 if (!NT_STATUS_IS_OK(status
)) {
2536 DBG_ERR("Failed to initialize session_global: %s\n",
2541 status
= dbwrap_traverse_read(smbXsrv_session_global_db_ctx
,
2542 smbXsrv_session_global_traverse_fn
,
2550 static struct files_struct
*smbXsrv_wait_for_handle_lease_break_fn(
2551 struct files_struct
*fsp
,
2552 void *private_data
);
2553 static void smbXsrv_wait_for_handle_lease_break_done(
2554 struct tevent_req
*subreq
);
2556 struct delay_for_handle_lease_break_state
{
2557 struct tevent_req
*req
;
2558 struct tevent_context
*ev
;
2559 struct smbXsrv_client
*client
;
2560 struct tevent_queue
*wait_queue
;
2561 bool (*fsp_cmp_fn
)(struct files_struct
*fsp
,
2562 void *private_data
);
2563 void *fsp_cmp_private_data
;
2566 void smbXsrv_wait_for_handle_lease_break(
2567 struct tevent_req
*req
,
2568 struct tevent_context
*ev
,
2569 struct smbXsrv_client
*client
,
2570 struct tevent_queue
*wait_queue
,
2571 bool (*fsp_cmp_fn
)(struct files_struct
*fsp
,
2572 void *private_data
),
2573 void *fsp_cmp_private_data
)
2575 struct delay_for_handle_lease_break_state state
;
2577 state
= (struct delay_for_handle_lease_break_state
) {
2581 .wait_queue
= wait_queue
,
2582 .fsp_cmp_fn
= fsp_cmp_fn
,
2583 .fsp_cmp_private_data
= fsp_cmp_private_data
,
2586 files_forall(client
->sconn
,
2587 smbXsrv_wait_for_handle_lease_break_fn
,
2591 static struct files_struct
*smbXsrv_wait_for_handle_lease_break_fn(
2592 struct files_struct
*fsp
,
2595 struct delay_for_handle_lease_break_state
*state
= private_data
;
2596 struct tevent_req
*subreq
= NULL
;
2597 struct share_mode_lock
*lck
= NULL
;
2598 struct timeval timeout
= timeval_current_ofs(OPLOCK_BREAK_TIMEOUT
, 0);
2602 match
= state
->fsp_cmp_fn(fsp
, state
->fsp_cmp_private_data
);
2607 if (!fsp
->fsp_flags
.initial_delete_on_close
) {
2611 lck
= get_existing_share_mode_lock(fsp
, fsp
->file_id
);
2613 /* No opens on this file */
2617 subreq
= delay_for_handle_lease_break_send(fsp
,
2623 if (tevent_req_nomem(subreq
, state
->req
)) {
2625 /* Reminder: returning != NULL means STOP traverse */
2628 if (tevent_req_is_in_progress(subreq
)) {
2629 struct tevent_req
*wait_subreq
= NULL
;
2631 tevent_req_set_callback(
2633 smbXsrv_wait_for_handle_lease_break_done
,
2637 * This just adds a blocker that unblocks when subreq is
2638 * completed and goes away.
2640 wait_subreq
= tevent_queue_wait_send(subreq
,
2643 if (wait_subreq
== NULL
) {
2644 exit_server("tevent_queue_wait_send failed");
2649 status
= delay_for_handle_lease_break_recv(subreq
, state
->req
, &lck
);
2650 TALLOC_FREE(subreq
);
2652 if (tevent_req_nterror(state
->req
, status
)) {
2653 DBG_ERR("delay_for_handle_lease_break_recv failed %s\n",
2660 static void smbXsrv_wait_for_handle_lease_break_done(
2661 struct tevent_req
*subreq
)
2663 struct tevent_req
*req
= tevent_req_callback_data(
2664 subreq
, struct tevent_req
);
2665 struct share_mode_lock
*lck
= NULL
;
2668 status
= delay_for_handle_lease_break_recv(subreq
,
2671 TALLOC_FREE(subreq
);
2673 if (tevent_req_nterror(req
, status
)) {
2674 DBG_ERR("delay_for_handle_lease_break_recv failed %s\n",