2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2011-2012
5 Copyright (C) Michael Adam 2012
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "dbwrap/dbwrap.h"
27 #include "dbwrap/dbwrap_rbt.h"
28 #include "dbwrap/dbwrap_open.h"
29 #include "dbwrap/dbwrap_watch.h"
32 #include "auth/gensec/gensec.h"
33 #include "../lib/tsocket/tsocket.h"
34 #include "../libcli/security/security.h"
36 #include "lib/util/util_tdb.h"
37 #include "librpc/gen_ndr/ndr_smbXsrv.h"
39 #include "lib/util/tevent_ntstatus.h"
41 struct smbXsrv_session_table
{
43 struct db_context
*db_ctx
;
46 uint32_t max_sessions
;
47 uint32_t num_sessions
;
50 struct db_context
*db_ctx
;
54 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
55 uint64_t session_id
, NTTIME now
,
56 struct smbXsrv_session
**session
);
58 static struct db_context
*smbXsrv_session_global_db_ctx
= NULL
;
60 NTSTATUS
smbXsrv_session_global_init(void)
62 char *global_path
= NULL
;
63 struct db_context
*db_ctx
= NULL
;
65 if (smbXsrv_session_global_db_ctx
!= NULL
) {
70 * This contains secret information like session keys!
72 global_path
= lock_path("smbXsrv_session_global.tdb");
73 if (global_path
== NULL
) {
74 return NT_STATUS_NO_MEMORY
;
77 db_ctx
= db_open(NULL
, global_path
,
81 TDB_INCOMPATIBLE_HASH
,
82 O_RDWR
| O_CREAT
, 0600,
85 TALLOC_FREE(global_path
);
89 status
= map_nt_error_from_unix_common(errno
);
94 smbXsrv_session_global_db_ctx
= db_ctx
;
101 * We need to store the keys in big endian so that dbwrap_rbt's memcmp
102 * has the same result as integer comparison between the uint32_t
105 * TODO: implement string based key
108 #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
110 static TDB_DATA
smbXsrv_session_global_id_to_key(uint32_t id
,
115 RSIVAL(key_buf
, 0, id
);
117 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
);
123 static NTSTATUS
smbXsrv_session_global_key_to_id(TDB_DATA key
, uint32_t *id
)
126 return NT_STATUS_INVALID_PARAMETER
;
129 if (key
.dsize
!= SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
) {
130 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
133 *id
= RIVAL(key
.dptr
, 0);
139 #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
141 static TDB_DATA
smbXsrv_session_local_id_to_key(uint32_t id
,
146 RSIVAL(key_buf
, 0, id
);
148 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
);
153 static NTSTATUS
smbXsrv_session_local_key_to_id(TDB_DATA key
, uint32_t *id
)
156 return NT_STATUS_INVALID_PARAMETER
;
159 if (key
.dsize
!= SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
) {
160 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
163 *id
= RIVAL(key
.dptr
, 0);
168 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
);
170 static NTSTATUS
smbXsrv_session_table_init(struct smbXsrv_connection
*conn
,
173 uint32_t max_sessions
)
175 struct smbXsrv_client
*client
= conn
->client
;
176 struct smbXsrv_session_table
*table
;
178 struct tevent_req
*subreq
;
181 if (lowest_id
> highest_id
) {
182 return NT_STATUS_INTERNAL_ERROR
;
185 max_range
= highest_id
;
186 max_range
-= lowest_id
;
189 if (max_sessions
> max_range
) {
190 return NT_STATUS_INTERNAL_ERROR
;
193 table
= talloc_zero(client
, struct smbXsrv_session_table
);
195 return NT_STATUS_NO_MEMORY
;
198 table
->local
.db_ctx
= db_open_rbt(table
);
199 if (table
->local
.db_ctx
== NULL
) {
201 return NT_STATUS_NO_MEMORY
;
203 table
->local
.lowest_id
= lowest_id
;
204 table
->local
.highest_id
= highest_id
;
205 table
->local
.max_sessions
= max_sessions
;
207 status
= smbXsrv_session_global_init();
208 if (!NT_STATUS_IS_OK(status
)) {
213 table
->global
.db_ctx
= smbXsrv_session_global_db_ctx
;
215 dbwrap_watch_db(table
->global
.db_ctx
, client
->msg_ctx
);
217 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
218 MSG_SMBXSRV_SESSION_CLOSE
);
219 if (subreq
== NULL
) {
221 return NT_STATUS_NO_MEMORY
;
223 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
225 client
->session_table
= table
;
229 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
);
231 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
)
233 struct smbXsrv_client
*client
=
234 tevent_req_callback_data(subreq
,
235 struct smbXsrv_client
);
236 struct smbXsrv_session_table
*table
= client
->session_table
;
238 struct messaging_rec
*rec
= NULL
;
239 struct smbXsrv_session_closeB close_blob
;
240 enum ndr_err_code ndr_err
;
241 struct smbXsrv_session_close0
*close_info0
= NULL
;
242 struct smbXsrv_session
*session
= NULL
;
244 struct timeval tv
= timeval_current();
245 NTTIME now
= timeval_to_nttime(&tv
);
247 ret
= messaging_read_recv(subreq
, talloc_tos(), &rec
);
253 ndr_err
= ndr_pull_struct_blob(&rec
->buf
, rec
, &close_blob
,
254 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_closeB
);
255 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
256 status
= ndr_map_error2ntstatus(ndr_err
);
257 DEBUG(1,("smbXsrv_session_close_loop: "
258 "ndr_pull_struct_blob - %s\n",
263 DEBUG(10,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
265 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
268 if (close_blob
.version
!= SMBXSRV_VERSION_0
) {
269 DEBUG(0,("smbXsrv_session_close_loop: "
270 "ignore invalid version %u\n", close_blob
.version
));
271 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
275 close_info0
= close_blob
.info
.info0
;
276 if (close_info0
== NULL
) {
277 DEBUG(0,("smbXsrv_session_close_loop: "
278 "ignore NULL info %u\n", close_blob
.version
));
279 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
283 status
= smb2srv_session_lookup_raw(client
->session_table
,
284 close_info0
->old_session_wire_id
,
286 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_SESSION_DELETED
)) {
287 DEBUG(4,("smbXsrv_session_close_loop: "
288 "old_session_wire_id %llu not found\n",
289 (unsigned long long)close_info0
->old_session_wire_id
));
291 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
295 if (!NT_STATUS_IS_OK(status
) &&
296 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
297 !NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
298 DEBUG(1,("smbXsrv_session_close_loop: "
299 "old_session_wire_id %llu - %s\n",
300 (unsigned long long)close_info0
->old_session_wire_id
,
303 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
308 if (session
->global
->session_global_id
!= close_info0
->old_session_global_id
) {
309 DEBUG(1,("smbXsrv_session_close_loop: "
310 "old_session_wire_id %llu - global %u != %u\n",
311 (unsigned long long)close_info0
->old_session_wire_id
,
312 session
->global
->session_global_id
,
313 close_info0
->old_session_global_id
));
315 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
320 if (session
->global
->creation_time
!= close_info0
->old_creation_time
) {
321 DEBUG(1,("smbXsrv_session_close_loop: "
322 "old_session_wire_id %llu - "
323 "creation %s (%llu) != %s (%llu)\n",
324 (unsigned long long)close_info0
->old_session_wire_id
,
325 nt_time_string(rec
, session
->global
->creation_time
),
326 (unsigned long long)session
->global
->creation_time
,
327 nt_time_string(rec
, close_info0
->old_creation_time
),
328 (unsigned long long)close_info0
->old_creation_time
));
330 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
335 subreq
= smb2srv_session_shutdown_send(session
, client
->ev_ctx
,
337 if (subreq
== NULL
) {
338 status
= NT_STATUS_NO_MEMORY
;
339 DEBUG(0, ("smbXsrv_session_close_loop: "
340 "smb2srv_session_shutdown_send(%llu) failed: %s\n",
341 (unsigned long long)session
->global
->session_wire_id
,
344 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
348 tevent_req_set_callback(subreq
,
349 smbXsrv_session_close_shutdown_done
,
355 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
356 MSG_SMBXSRV_SESSION_CLOSE
);
357 if (subreq
== NULL
) {
359 r
= "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
360 exit_server_cleanly(r
);
363 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
366 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
)
368 struct smbXsrv_session
*session
=
369 tevent_req_callback_data(subreq
,
370 struct smbXsrv_session
);
373 status
= smb2srv_session_shutdown_recv(subreq
);
375 if (!NT_STATUS_IS_OK(status
)) {
376 DEBUG(0, ("smbXsrv_session_close_loop: "
377 "smb2srv_session_shutdown_recv(%llu) failed: %s\n",
378 (unsigned long long)session
->global
->session_wire_id
,
382 status
= smbXsrv_session_logoff(session
);
383 if (!NT_STATUS_IS_OK(status
)) {
384 DEBUG(0, ("smbXsrv_session_close_loop: "
385 "smbXsrv_session_logoff(%llu) failed: %s\n",
386 (unsigned long long)session
->global
->session_wire_id
,
390 TALLOC_FREE(session
);
393 struct smb1srv_session_local_allocate_state
{
394 const uint32_t lowest_id
;
395 const uint32_t highest_id
;
401 static int smb1srv_session_local_allocate_traverse(struct db_record
*rec
,
404 struct smb1srv_session_local_allocate_state
*state
=
405 (struct smb1srv_session_local_allocate_state
*)private_data
;
406 TDB_DATA key
= dbwrap_record_get_key(rec
);
410 status
= smbXsrv_session_local_key_to_id(key
, &id
);
411 if (!NT_STATUS_IS_OK(status
)) {
412 state
->status
= status
;
416 if (id
<= state
->last_id
) {
417 state
->status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
422 if (id
> state
->useable_id
) {
423 state
->status
= NT_STATUS_OK
;
427 if (state
->useable_id
== state
->highest_id
) {
428 state
->status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
432 state
->useable_id
+=1;
436 static NTSTATUS
smb1srv_session_local_allocate_id(struct db_context
*db
,
440 struct db_record
**_rec
,
443 struct smb1srv_session_local_allocate_state state
= {
444 .lowest_id
= lowest_id
,
445 .highest_id
= highest_id
,
447 .useable_id
= lowest_id
,
448 .status
= NT_STATUS_INTERNAL_ERROR
,
458 if (lowest_id
> highest_id
) {
459 return NT_STATUS_INSUFFICIENT_RESOURCES
;
463 * first we try randomly
465 range
= (highest_id
- lowest_id
) + 1;
467 for (i
= 0; i
< (range
/ 2); i
++) {
469 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
472 struct db_record
*rec
= NULL
;
474 id
= generate_random() % range
;
477 if (id
< lowest_id
) {
480 if (id
> highest_id
) {
484 key
= smbXsrv_session_local_id_to_key(id
, key_buf
);
486 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
488 return NT_STATUS_INSUFFICIENT_RESOURCES
;
491 val
= dbwrap_record_get_value(rec
);
492 if (val
.dsize
!= 0) {
503 * if the range is almost full,
504 * we traverse the whole table
505 * (this relies on sorted behavior of dbwrap_rbt)
507 status
= dbwrap_traverse_read(db
, smb1srv_session_local_allocate_traverse
,
509 if (NT_STATUS_IS_OK(status
)) {
510 if (NT_STATUS_IS_OK(state
.status
)) {
511 return NT_STATUS_INTERNAL_ERROR
;
514 if (!NT_STATUS_EQUAL(state
.status
, NT_STATUS_INTERNAL_ERROR
)) {
518 if (state
.useable_id
<= state
.highest_id
) {
519 state
.status
= NT_STATUS_OK
;
521 return NT_STATUS_INSUFFICIENT_RESOURCES
;
523 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_INTERNAL_DB_CORRUPTION
)) {
525 * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
527 * If we get anything else it is an error, because it
528 * means we did not manage to find a free slot in
531 return NT_STATUS_INSUFFICIENT_RESOURCES
;
534 if (NT_STATUS_IS_OK(state
.status
)) {
536 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
539 struct db_record
*rec
= NULL
;
541 id
= state
.useable_id
;
543 key
= smbXsrv_session_local_id_to_key(id
, key_buf
);
545 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
547 return NT_STATUS_INSUFFICIENT_RESOURCES
;
550 val
= dbwrap_record_get_value(rec
);
551 if (val
.dsize
!= 0) {
553 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
564 struct smbXsrv_session_local_fetch_state
{
565 struct smbXsrv_session
*session
;
569 static void smbXsrv_session_local_fetch_parser(TDB_DATA key
, TDB_DATA data
,
572 struct smbXsrv_session_local_fetch_state
*state
=
573 (struct smbXsrv_session_local_fetch_state
*)private_data
;
576 if (data
.dsize
!= sizeof(ptr
)) {
577 state
->status
= NT_STATUS_INTERNAL_DB_ERROR
;
581 memcpy(&ptr
, data
.dptr
, data
.dsize
);
582 state
->session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
583 state
->status
= NT_STATUS_OK
;
586 static NTSTATUS
smbXsrv_session_local_lookup(struct smbXsrv_session_table
*table
,
588 struct smbXsrv_connection
*conn
,
589 uint32_t session_local_id
,
591 struct smbXsrv_session
**_session
)
593 struct smbXsrv_session_local_fetch_state state
= {
595 .status
= NT_STATUS_INTERNAL_ERROR
,
597 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
603 if (session_local_id
== 0) {
604 return NT_STATUS_USER_SESSION_DELETED
;
608 /* this might happen before the end of negprot */
609 return NT_STATUS_USER_SESSION_DELETED
;
612 if (table
->local
.db_ctx
== NULL
) {
613 return NT_STATUS_INTERNAL_ERROR
;
616 key
= smbXsrv_session_local_id_to_key(session_local_id
, key_buf
);
618 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
619 smbXsrv_session_local_fetch_parser
,
621 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
622 return NT_STATUS_USER_SESSION_DELETED
;
623 } else if (!NT_STATUS_IS_OK(status
)) {
626 if (!NT_STATUS_IS_OK(state
.status
)) {
630 if (NT_STATUS_EQUAL(state
.session
->status
, NT_STATUS_USER_SESSION_DELETED
)) {
631 return NT_STATUS_USER_SESSION_DELETED
;
635 * If a connection is specified check if the session is
636 * valid on the channel.
639 struct smbXsrv_channel_global0
*c
= NULL
;
641 status
= smbXsrv_session_find_channel(state
.session
, conn
, &c
);
642 if (!NT_STATUS_IS_OK(status
)) {
647 state
.session
->idle_time
= now
;
649 if (!NT_STATUS_IS_OK(state
.session
->status
)) {
650 *_session
= state
.session
;
651 return state
.session
->status
;
654 if (now
> state
.session
->global
->expiration_time
) {
655 state
.session
->status
= NT_STATUS_NETWORK_SESSION_EXPIRED
;
658 *_session
= state
.session
;
659 return state
.session
->status
;
662 static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0
*global
)
667 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
671 struct smbXsrv_session_global0
**_g
);
673 static NTSTATUS
smbXsrv_session_global_allocate(struct db_context
*db
,
675 struct smbXsrv_session_global0
**_global
)
678 struct smbXsrv_session_global0
*global
= NULL
;
679 uint32_t last_free
= 0;
680 const uint32_t min_tries
= 3;
684 global
= talloc_zero(mem_ctx
, struct smbXsrv_session_global0
);
685 if (global
== NULL
) {
686 return NT_STATUS_NO_MEMORY
;
688 talloc_set_destructor(global
, smbXsrv_session_global_destructor
);
691 * Here we just randomly try the whole 32-bit space
693 * We use just 32-bit, because we want to reuse the
696 for (i
= 0; i
< UINT32_MAX
; i
++) {
697 bool is_free
= false;
698 bool was_free
= false;
700 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
703 if (i
>= min_tries
&& last_free
!= 0) {
706 id
= generate_random();
711 if (id
== UINT32_MAX
) {
715 key
= smbXsrv_session_global_id_to_key(id
, key_buf
);
717 global
->db_rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
718 if (global
->db_rec
== NULL
) {
720 return NT_STATUS_INSUFFICIENT_RESOURCES
;
723 smbXsrv_session_global_verify_record(global
->db_rec
,
729 TALLOC_FREE(global
->db_rec
);
733 if (!was_free
&& i
< min_tries
) {
735 * The session_id is free now,
736 * but was not free before.
738 * This happens if a smbd crashed
739 * and did not cleanup the record.
741 * If this is one of our first tries,
742 * then we try to find a real free one.
744 if (last_free
== 0) {
747 TALLOC_FREE(global
->db_rec
);
751 global
->session_global_id
= id
;
757 /* should not be reached */
759 return NT_STATUS_INTERNAL_ERROR
;
762 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
766 struct smbXsrv_session_global0
**_g
)
771 struct smbXsrv_session_globalB global_blob
;
772 enum ndr_err_code ndr_err
;
773 struct smbXsrv_session_global0
*global
= NULL
;
775 TALLOC_CTX
*frame
= talloc_stackframe();
786 key
= dbwrap_record_get_key(db_rec
);
788 val
= dbwrap_record_get_value(db_rec
);
789 if (val
.dsize
== 0) {
798 blob
= data_blob_const(val
.dptr
, val
.dsize
);
800 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
801 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
802 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
803 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
804 DEBUG(1,("smbXsrv_session_global_verify_record: "
805 "key '%s' ndr_pull_struct_blob - %s\n",
806 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
812 DEBUG(10,("smbXsrv_session_global_verify_record\n"));
814 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
817 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
818 DEBUG(0,("smbXsrv_session_global_verify_record: "
819 "key '%s' use unsupported version %u\n",
820 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
821 global_blob
.version
));
822 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
827 global
= global_blob
.info
.info0
;
829 exists
= serverid_exists(&global
->channels
[0].server_id
);
831 struct server_id_buf idbuf
;
832 DEBUG(2,("smbXsrv_session_global_verify_record: "
833 "key '%s' server_id %s does not exist.\n",
834 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
835 server_id_str_buf(global
->channels
[0].server_id
,
838 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
841 dbwrap_record_delete(db_rec
);
847 *_g
= talloc_move(mem_ctx
, &global
);
852 static NTSTATUS
smbXsrv_session_global_store(struct smbXsrv_session_global0
*global
)
854 struct smbXsrv_session_globalB global_blob
;
855 DATA_BLOB blob
= data_blob_null
;
859 enum ndr_err_code ndr_err
;
862 * TODO: if we use other versions than '0'
863 * we would add glue code here, that would be able to
864 * store the information in the old format.
867 if (global
->db_rec
== NULL
) {
868 return NT_STATUS_INTERNAL_ERROR
;
871 key
= dbwrap_record_get_key(global
->db_rec
);
872 val
= dbwrap_record_get_value(global
->db_rec
);
874 ZERO_STRUCT(global_blob
);
875 global_blob
.version
= smbXsrv_version_global_current();
876 if (val
.dsize
>= 8) {
877 global_blob
.seqnum
= IVAL(val
.dptr
, 4);
879 global_blob
.seqnum
+= 1;
880 global_blob
.info
.info0
= global
;
882 ndr_err
= ndr_push_struct_blob(&blob
, global
->db_rec
, &global_blob
,
883 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_globalB
);
884 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
885 status
= ndr_map_error2ntstatus(ndr_err
);
886 DEBUG(1,("smbXsrv_session_global_store: key '%s' ndr_push - %s\n",
887 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
889 TALLOC_FREE(global
->db_rec
);
893 val
= make_tdb_data(blob
.data
, blob
.length
);
894 status
= dbwrap_record_store(global
->db_rec
, val
, TDB_REPLACE
);
895 if (!NT_STATUS_IS_OK(status
)) {
896 DEBUG(1,("smbXsrv_session_global_store: key '%s' store - %s\n",
897 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
899 TALLOC_FREE(global
->db_rec
);
904 DEBUG(10,("smbXsrv_session_global_store: key '%s' stored\n",
905 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
)));
906 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
909 TALLOC_FREE(global
->db_rec
);
914 struct smb2srv_session_close_previous_state
{
915 struct tevent_context
*ev
;
916 struct smbXsrv_connection
*connection
;
917 struct dom_sid
*current_sid
;
918 uint64_t current_session_id
;
919 struct db_record
*db_rec
;
922 static void smb2srv_session_close_previous_check(struct tevent_req
*req
);
923 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
);
925 struct tevent_req
*smb2srv_session_close_previous_send(TALLOC_CTX
*mem_ctx
,
926 struct tevent_context
*ev
,
927 struct smbXsrv_connection
*conn
,
928 struct auth_session_info
*session_info
,
929 uint64_t previous_session_id
,
930 uint64_t current_session_id
)
932 struct tevent_req
*req
;
933 struct smb2srv_session_close_previous_state
*state
;
934 uint32_t global_id
= previous_session_id
& UINT32_MAX
;
935 uint64_t global_zeros
= previous_session_id
& 0xFFFFFFFF00000000LLU
;
936 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
937 struct security_token
*current_token
= NULL
;
938 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
941 req
= tevent_req_create(mem_ctx
, &state
,
942 struct smb2srv_session_close_previous_state
);
947 state
->connection
= conn
;
948 state
->current_session_id
= current_session_id
;
950 if (global_zeros
!= 0) {
951 tevent_req_done(req
);
952 return tevent_req_post(req
, ev
);
955 if (session_info
== NULL
) {
956 tevent_req_done(req
);
957 return tevent_req_post(req
, ev
);
959 current_token
= session_info
->security_token
;
961 if (current_token
->num_sids
> PRIMARY_USER_SID_INDEX
) {
962 state
->current_sid
= ¤t_token
->sids
[PRIMARY_USER_SID_INDEX
];
965 if (state
->current_sid
== NULL
) {
966 tevent_req_done(req
);
967 return tevent_req_post(req
, ev
);
970 if (!security_token_has_nt_authenticated_users(current_token
)) {
972 tevent_req_done(req
);
973 return tevent_req_post(req
, ev
);
976 key
= smbXsrv_session_global_id_to_key(global_id
, key_buf
);
978 state
->db_rec
= dbwrap_fetch_locked(table
->global
.db_ctx
,
980 if (state
->db_rec
== NULL
) {
981 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
982 return tevent_req_post(req
, ev
);
985 smb2srv_session_close_previous_check(req
);
986 if (!tevent_req_is_in_progress(req
)) {
987 return tevent_req_post(req
, ev
);
993 static void smb2srv_session_close_previous_check(struct tevent_req
*req
)
995 struct smb2srv_session_close_previous_state
*state
=
997 struct smb2srv_session_close_previous_state
);
998 struct smbXsrv_connection
*conn
= state
->connection
;
1000 struct security_token
*previous_token
= NULL
;
1001 struct smbXsrv_session_global0
*global
= NULL
;
1002 enum ndr_err_code ndr_err
;
1003 struct smbXsrv_session_close0 close_info0
;
1004 struct smbXsrv_session_closeB close_blob
;
1005 struct tevent_req
*subreq
= NULL
;
1007 bool is_free
= false;
1009 smbXsrv_session_global_verify_record(state
->db_rec
,
1016 TALLOC_FREE(state
->db_rec
);
1017 tevent_req_done(req
);
1021 if (global
->auth_session_info
== NULL
) {
1022 TALLOC_FREE(state
->db_rec
);
1023 tevent_req_done(req
);
1027 previous_token
= global
->auth_session_info
->security_token
;
1029 if (!security_token_is_sid(previous_token
, state
->current_sid
)) {
1030 TALLOC_FREE(state
->db_rec
);
1031 tevent_req_done(req
);
1035 subreq
= dbwrap_record_watch_send(state
, state
->ev
,
1036 state
->db_rec
, conn
->msg_ctx
);
1037 if (tevent_req_nomem(subreq
, req
)) {
1038 TALLOC_FREE(state
->db_rec
);
1041 tevent_req_set_callback(subreq
,
1042 smb2srv_session_close_previous_modified
,
1045 close_info0
.old_session_global_id
= global
->session_global_id
;
1046 close_info0
.old_session_wire_id
= global
->session_wire_id
;
1047 close_info0
.old_creation_time
= global
->creation_time
;
1048 close_info0
.new_session_wire_id
= state
->current_session_id
;
1050 ZERO_STRUCT(close_blob
);
1051 close_blob
.version
= smbXsrv_version_global_current();
1052 close_blob
.info
.info0
= &close_info0
;
1054 ndr_err
= ndr_push_struct_blob(&blob
, state
, &close_blob
,
1055 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_closeB
);
1056 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1057 TALLOC_FREE(state
->db_rec
);
1058 status
= ndr_map_error2ntstatus(ndr_err
);
1059 DEBUG(1,("smb2srv_session_close_previous_check: "
1060 "old_session[%llu] new_session[%llu] ndr_push - %s\n",
1061 (unsigned long long)close_info0
.old_session_wire_id
,
1062 (unsigned long long)close_info0
.new_session_wire_id
,
1063 nt_errstr(status
)));
1064 tevent_req_nterror(req
, status
);
1068 status
= messaging_send(conn
->msg_ctx
,
1069 global
->channels
[0].server_id
,
1070 MSG_SMBXSRV_SESSION_CLOSE
, &blob
);
1071 TALLOC_FREE(state
->db_rec
);
1072 if (tevent_req_nterror(req
, status
)) {
1076 TALLOC_FREE(global
);
1080 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
)
1082 struct tevent_req
*req
=
1083 tevent_req_callback_data(subreq
,
1085 struct smb2srv_session_close_previous_state
*state
=
1086 tevent_req_data(req
,
1087 struct smb2srv_session_close_previous_state
);
1090 status
= dbwrap_record_watch_recv(subreq
, state
, &state
->db_rec
);
1091 TALLOC_FREE(subreq
);
1092 if (tevent_req_nterror(req
, status
)) {
1096 smb2srv_session_close_previous_check(req
);
1099 NTSTATUS
smb2srv_session_close_previous_recv(struct tevent_req
*req
)
1103 if (tevent_req_is_nterror(req
, &status
)) {
1104 tevent_req_received(req
);
1108 tevent_req_received(req
);
1109 return NT_STATUS_OK
;
1112 static NTSTATUS
smbXsrv_session_clear_and_logoff(struct smbXsrv_session
*session
)
1115 struct smbXsrv_connection
*xconn
= NULL
;
1117 if (session
->client
!= NULL
) {
1118 xconn
= session
->client
->connections
;
1121 for (; xconn
!= NULL
; xconn
= xconn
->next
) {
1122 struct smbd_smb2_request
*preq
;
1124 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1125 if (preq
->session
!= session
) {
1129 preq
->session
= NULL
;
1131 * If we no longer have a session we can't
1132 * sign or encrypt replies.
1134 preq
->do_signing
= false;
1135 preq
->do_encryption
= false;
1136 preq
->preauth
= NULL
;
1140 status
= smbXsrv_session_logoff(session
);
1144 static int smbXsrv_session_destructor(struct smbXsrv_session
*session
)
1148 status
= smbXsrv_session_clear_and_logoff(session
);
1149 if (!NT_STATUS_IS_OK(status
)) {
1150 DEBUG(0, ("smbXsrv_session_destructor: "
1151 "smbXsrv_session_logoff() failed: %s\n",
1152 nt_errstr(status
)));
1155 TALLOC_FREE(session
->global
);
1160 NTSTATUS
smbXsrv_session_create(struct smbXsrv_connection
*conn
,
1162 struct smbXsrv_session
**_session
)
1164 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1165 struct db_record
*local_rec
= NULL
;
1166 struct smbXsrv_session
*session
= NULL
;
1169 struct smbXsrv_session_global0
*global
= NULL
;
1170 struct smbXsrv_channel_global0
*channels
= NULL
;
1173 if (table
->local
.num_sessions
>= table
->local
.max_sessions
) {
1174 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1177 session
= talloc_zero(table
, struct smbXsrv_session
);
1178 if (session
== NULL
) {
1179 return NT_STATUS_NO_MEMORY
;
1181 session
->table
= table
;
1182 session
->idle_time
= now
;
1183 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
1184 session
->client
= conn
->client
;
1186 if (conn
->protocol
>= PROTOCOL_SMB3_10
) {
1187 session
->preauth
= talloc(session
, struct smbXsrv_preauth
);
1188 if (session
->preauth
== NULL
) {
1189 TALLOC_FREE(session
);
1190 return NT_STATUS_NO_MEMORY
;
1192 *session
->preauth
= conn
->smb2
.preauth
;
1195 status
= smbXsrv_session_global_allocate(table
->global
.db_ctx
,
1198 if (!NT_STATUS_IS_OK(status
)) {
1199 TALLOC_FREE(session
);
1202 session
->global
= global
;
1204 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1205 uint64_t id
= global
->session_global_id
;
1206 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
1209 global
->connection_dialect
= conn
->smb2
.server
.dialect
;
1211 global
->session_wire_id
= id
;
1213 status
= smb2srv_tcon_table_init(session
);
1214 if (!NT_STATUS_IS_OK(status
)) {
1215 TALLOC_FREE(session
);
1219 session
->local_id
= global
->session_global_id
;
1221 key
= smbXsrv_session_local_id_to_key(session
->local_id
, key_buf
);
1223 local_rec
= dbwrap_fetch_locked(table
->local
.db_ctx
,
1225 if (local_rec
== NULL
) {
1226 TALLOC_FREE(session
);
1227 return NT_STATUS_NO_MEMORY
;
1230 val
= dbwrap_record_get_value(local_rec
);
1231 if (val
.dsize
!= 0) {
1232 TALLOC_FREE(session
);
1233 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1237 status
= smb1srv_session_local_allocate_id(table
->local
.db_ctx
,
1238 table
->local
.lowest_id
,
1239 table
->local
.highest_id
,
1242 &session
->local_id
);
1243 if (!NT_STATUS_IS_OK(status
)) {
1244 TALLOC_FREE(session
);
1248 global
->session_wire_id
= session
->local_id
;
1251 global
->creation_time
= now
;
1252 global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1254 global
->num_channels
= 1;
1255 channels
= talloc_zero_array(global
,
1256 struct smbXsrv_channel_global0
,
1257 global
->num_channels
);
1258 if (channels
== NULL
) {
1259 TALLOC_FREE(session
);
1260 return NT_STATUS_NO_MEMORY
;
1262 global
->channels
= channels
;
1264 channels
[0].server_id
= messaging_server_id(conn
->msg_ctx
);
1265 channels
[0].local_address
= tsocket_address_string(conn
->local_address
,
1267 if (channels
[0].local_address
== NULL
) {
1268 TALLOC_FREE(session
);
1269 return NT_STATUS_NO_MEMORY
;
1271 channels
[0].remote_address
= tsocket_address_string(conn
->remote_address
,
1273 if (channels
[0].remote_address
== NULL
) {
1274 TALLOC_FREE(session
);
1275 return NT_STATUS_NO_MEMORY
;
1277 channels
[0].remote_name
= talloc_strdup(channels
, conn
->remote_hostname
);
1278 if (channels
[0].remote_name
== NULL
) {
1279 TALLOC_FREE(session
);
1280 return NT_STATUS_NO_MEMORY
;
1282 channels
[0].signing_key
= data_blob_null
;
1283 channels
[0].connection
= conn
;
1286 val
= make_tdb_data((uint8_t const *)&ptr
, sizeof(ptr
));
1287 status
= dbwrap_record_store(local_rec
, val
, TDB_REPLACE
);
1288 TALLOC_FREE(local_rec
);
1289 if (!NT_STATUS_IS_OK(status
)) {
1290 TALLOC_FREE(session
);
1293 table
->local
.num_sessions
+= 1;
1295 talloc_set_destructor(session
, smbXsrv_session_destructor
);
1297 status
= smbXsrv_session_global_store(global
);
1298 if (!NT_STATUS_IS_OK(status
)) {
1299 DEBUG(0,("smbXsrv_session_create: "
1300 "global_id (0x%08x) store failed - %s\n",
1301 session
->global
->session_global_id
,
1302 nt_errstr(status
)));
1303 TALLOC_FREE(session
);
1308 struct smbXsrv_sessionB session_blob
;
1310 ZERO_STRUCT(session_blob
);
1311 session_blob
.version
= SMBXSRV_VERSION_0
;
1312 session_blob
.info
.info0
= session
;
1314 DEBUG(10,("smbXsrv_session_create: global_id (0x%08x) stored\n",
1315 session
->global
->session_global_id
));
1316 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1319 *_session
= session
;
1320 return NT_STATUS_OK
;
1323 NTSTATUS
smbXsrv_session_update(struct smbXsrv_session
*session
)
1325 struct smbXsrv_session_table
*table
= session
->table
;
1327 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
1330 if (session
->global
->db_rec
!= NULL
) {
1331 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1332 "Called with db_rec != NULL'\n",
1333 session
->global
->session_global_id
));
1334 return NT_STATUS_INTERNAL_ERROR
;
1337 key
= smbXsrv_session_global_id_to_key(
1338 session
->global
->session_global_id
,
1341 session
->global
->db_rec
= dbwrap_fetch_locked(table
->global
.db_ctx
,
1342 session
->global
, key
);
1343 if (session
->global
->db_rec
== NULL
) {
1344 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1345 "Failed to lock global key '%s'\n",
1346 session
->global
->session_global_id
,
1347 hex_encode_talloc(talloc_tos(), key
.dptr
,
1349 return NT_STATUS_INTERNAL_DB_ERROR
;
1352 status
= smbXsrv_session_global_store(session
->global
);
1353 if (!NT_STATUS_IS_OK(status
)) {
1354 DEBUG(0,("smbXsrv_session_update: "
1355 "global_id (0x%08x) store failed - %s\n",
1356 session
->global
->session_global_id
,
1357 nt_errstr(status
)));
1362 struct smbXsrv_sessionB session_blob
;
1364 ZERO_STRUCT(session_blob
);
1365 session_blob
.version
= SMBXSRV_VERSION_0
;
1366 session_blob
.info
.info0
= session
;
1368 DEBUG(10,("smbXsrv_session_update: global_id (0x%08x) stored\n",
1369 session
->global
->session_global_id
));
1370 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1373 return NT_STATUS_OK
;
1376 NTSTATUS
smbXsrv_session_find_channel(const struct smbXsrv_session
*session
,
1377 const struct smbXsrv_connection
*conn
,
1378 struct smbXsrv_channel_global0
**_c
)
1382 for (i
=0; i
< session
->global
->num_channels
; i
++) {
1383 struct smbXsrv_channel_global0
*c
= &session
->global
->channels
[i
];
1385 if (c
->connection
== conn
) {
1387 return NT_STATUS_OK
;
1391 return NT_STATUS_USER_SESSION_DELETED
;
1394 struct smb2srv_session_shutdown_state
{
1395 struct tevent_queue
*wait_queue
;
1398 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
);
1400 struct tevent_req
*smb2srv_session_shutdown_send(TALLOC_CTX
*mem_ctx
,
1401 struct tevent_context
*ev
,
1402 struct smbXsrv_session
*session
,
1403 struct smbd_smb2_request
*current_req
)
1405 struct tevent_req
*req
;
1406 struct smb2srv_session_shutdown_state
*state
;
1407 struct tevent_req
*subreq
;
1408 struct smbXsrv_connection
*xconn
= NULL
;
1412 * Make sure that no new request will be able to use this session.
1414 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1416 req
= tevent_req_create(mem_ctx
, &state
,
1417 struct smb2srv_session_shutdown_state
);
1422 state
->wait_queue
= tevent_queue_create(state
, "smb2srv_session_shutdown_queue");
1423 if (tevent_req_nomem(state
->wait_queue
, req
)) {
1424 return tevent_req_post(req
, ev
);
1427 for (xconn
= session
->client
->connections
; xconn
!= NULL
; xconn
= xconn
->next
) {
1428 struct smbd_smb2_request
*preq
;
1430 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1431 if (preq
== current_req
) {
1432 /* Can't cancel current request. */
1435 if (preq
->session
!= session
) {
1436 /* Request on different session. */
1440 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
1441 preq
->session
= NULL
;
1443 * If we no longer have a session we can't
1444 * sign or encrypt replies.
1446 preq
->do_signing
= false;
1447 preq
->do_encryption
= false;
1448 preq
->preauth
= NULL
;
1450 if (preq
->subreq
!= NULL
) {
1451 tevent_req_cancel(preq
->subreq
);
1457 * Never cancel anything in a compound
1458 * request. Way too hard to deal with
1461 if (!preq
->compound_related
&& preq
->subreq
!= NULL
) {
1462 tevent_req_cancel(preq
->subreq
);
1466 * Now wait until the request is finished.
1468 * We don't set a callback, as we just want to block the
1469 * wait queue and the talloc_free() of the request will
1470 * remove the item from the wait queue.
1472 subreq
= tevent_queue_wait_send(preq
, ev
, state
->wait_queue
);
1473 if (tevent_req_nomem(subreq
, req
)) {
1474 return tevent_req_post(req
, ev
);
1479 len
= tevent_queue_length(state
->wait_queue
);
1481 tevent_req_done(req
);
1482 return tevent_req_post(req
, ev
);
1486 * Now we add our own waiter to the end of the queue,
1487 * this way we get notified when all pending requests are finished
1488 * and send to the socket.
1490 subreq
= tevent_queue_wait_send(state
, ev
, state
->wait_queue
);
1491 if (tevent_req_nomem(subreq
, req
)) {
1492 return tevent_req_post(req
, ev
);
1494 tevent_req_set_callback(subreq
, smb2srv_session_shutdown_wait_done
, req
);
1499 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
)
1501 struct tevent_req
*req
=
1502 tevent_req_callback_data(subreq
,
1505 tevent_queue_wait_recv(subreq
);
1506 TALLOC_FREE(subreq
);
1508 tevent_req_done(req
);
1511 NTSTATUS
smb2srv_session_shutdown_recv(struct tevent_req
*req
)
1513 return tevent_req_simple_recv_ntstatus(req
);
1516 NTSTATUS
smbXsrv_session_logoff(struct smbXsrv_session
*session
)
1518 struct smbXsrv_session_table
*table
;
1519 struct db_record
*local_rec
= NULL
;
1520 struct db_record
*global_rec
= NULL
;
1521 struct smbd_server_connection
*sconn
= NULL
;
1523 NTSTATUS error
= NT_STATUS_OK
;
1525 if (session
->table
== NULL
) {
1526 return NT_STATUS_OK
;
1529 table
= session
->table
;
1530 session
->table
= NULL
;
1532 sconn
= session
->client
->sconn
;
1533 session
->client
= NULL
;
1534 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1536 global_rec
= session
->global
->db_rec
;
1537 session
->global
->db_rec
= NULL
;
1538 if (global_rec
== NULL
) {
1539 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
1542 key
= smbXsrv_session_global_id_to_key(
1543 session
->global
->session_global_id
,
1546 global_rec
= dbwrap_fetch_locked(table
->global
.db_ctx
,
1547 session
->global
, key
);
1548 if (global_rec
== NULL
) {
1549 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1550 "Failed to lock global key '%s'\n",
1551 session
->global
->session_global_id
,
1552 hex_encode_talloc(global_rec
, key
.dptr
,
1554 error
= NT_STATUS_INTERNAL_ERROR
;
1558 if (global_rec
!= NULL
) {
1559 status
= dbwrap_record_delete(global_rec
);
1560 if (!NT_STATUS_IS_OK(status
)) {
1561 TDB_DATA key
= dbwrap_record_get_key(global_rec
);
1563 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1564 "failed to delete global key '%s': %s\n",
1565 session
->global
->session_global_id
,
1566 hex_encode_talloc(global_rec
, key
.dptr
,
1568 nt_errstr(status
)));
1572 TALLOC_FREE(global_rec
);
1574 local_rec
= session
->db_rec
;
1575 if (local_rec
== NULL
) {
1576 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
1579 key
= smbXsrv_session_local_id_to_key(session
->local_id
,
1582 local_rec
= dbwrap_fetch_locked(table
->local
.db_ctx
,
1584 if (local_rec
== NULL
) {
1585 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1586 "Failed to lock local key '%s'\n",
1587 session
->global
->session_global_id
,
1588 hex_encode_talloc(local_rec
, key
.dptr
,
1590 error
= NT_STATUS_INTERNAL_ERROR
;
1594 if (local_rec
!= NULL
) {
1595 status
= dbwrap_record_delete(local_rec
);
1596 if (!NT_STATUS_IS_OK(status
)) {
1597 TDB_DATA key
= dbwrap_record_get_key(local_rec
);
1599 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1600 "failed to delete local key '%s': %s\n",
1601 session
->global
->session_global_id
,
1602 hex_encode_talloc(local_rec
, key
.dptr
,
1604 nt_errstr(status
)));
1607 table
->local
.num_sessions
-= 1;
1609 if (session
->db_rec
== NULL
) {
1610 TALLOC_FREE(local_rec
);
1612 session
->db_rec
= NULL
;
1614 if (session
->compat
) {
1615 file_close_user(sconn
, session
->compat
->vuid
);
1618 if (session
->tcon_table
!= NULL
) {
1620 * Note: We only have a tcon_table for SMB2.
1622 status
= smb2srv_tcon_disconnect_all(session
);
1623 if (!NT_STATUS_IS_OK(status
)) {
1624 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1625 "smb2srv_tcon_disconnect_all() failed: %s\n",
1626 session
->global
->session_global_id
,
1627 nt_errstr(status
)));
1632 if (session
->compat
) {
1633 invalidate_vuid(sconn
, session
->compat
->vuid
);
1634 session
->compat
= NULL
;
1640 struct smbXsrv_session_logoff_all_state
{
1641 NTSTATUS first_status
;
1645 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1646 void *private_data
);
1648 NTSTATUS
smbXsrv_session_logoff_all(struct smbXsrv_connection
*conn
)
1650 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1651 struct smbXsrv_session_logoff_all_state state
;
1655 if (table
== NULL
) {
1656 DEBUG(10, ("smbXsrv_session_logoff_all: "
1657 "empty session_table, nothing to do.\n"));
1658 return NT_STATUS_OK
;
1663 status
= dbwrap_traverse(table
->local
.db_ctx
,
1664 smbXsrv_session_logoff_all_callback
,
1666 if (!NT_STATUS_IS_OK(status
)) {
1667 DEBUG(0, ("smbXsrv_session_logoff_all: "
1668 "dbwrap_traverse() failed: %s\n",
1669 nt_errstr(status
)));
1673 if (!NT_STATUS_IS_OK(state
.first_status
)) {
1674 DEBUG(0, ("smbXsrv_session_logoff_all: "
1675 "count[%d] errors[%d] first[%s]\n",
1676 count
, state
.errors
,
1677 nt_errstr(state
.first_status
)));
1678 return state
.first_status
;
1681 return NT_STATUS_OK
;
1684 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1687 struct smbXsrv_session_logoff_all_state
*state
=
1688 (struct smbXsrv_session_logoff_all_state
*)private_data
;
1691 struct smbXsrv_session
*session
= NULL
;
1694 val
= dbwrap_record_get_value(local_rec
);
1695 if (val
.dsize
!= sizeof(ptr
)) {
1696 status
= NT_STATUS_INTERNAL_ERROR
;
1697 if (NT_STATUS_IS_OK(state
->first_status
)) {
1698 state
->first_status
= status
;
1704 memcpy(&ptr
, val
.dptr
, val
.dsize
);
1705 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
1707 session
->db_rec
= local_rec
;
1709 status
= smbXsrv_session_clear_and_logoff(session
);
1710 if (!NT_STATUS_IS_OK(status
)) {
1711 if (NT_STATUS_IS_OK(state
->first_status
)) {
1712 state
->first_status
= status
;
1721 NTSTATUS
smb1srv_session_table_init(struct smbXsrv_connection
*conn
)
1724 * Allow a range from 1..65534 with 65534 values.
1726 return smbXsrv_session_table_init(conn
, 1, UINT16_MAX
- 1,
1730 NTSTATUS
smb1srv_session_lookup(struct smbXsrv_connection
*conn
,
1731 uint16_t vuid
, NTTIME now
,
1732 struct smbXsrv_session
**session
)
1734 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1735 uint32_t local_id
= vuid
;
1737 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
1741 NTSTATUS
smb2srv_session_table_init(struct smbXsrv_connection
*conn
)
1744 * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
1746 return smbXsrv_session_table_init(conn
, 1, UINT32_MAX
- 1,
1750 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
1751 uint64_t session_id
, NTTIME now
,
1752 struct smbXsrv_session
**session
)
1754 uint32_t local_id
= session_id
& UINT32_MAX
;
1755 uint64_t local_zeros
= session_id
& 0xFFFFFFFF00000000LLU
;
1757 if (local_zeros
!= 0) {
1758 return NT_STATUS_USER_SESSION_DELETED
;
1761 return smbXsrv_session_local_lookup(table
, NULL
, local_id
, now
,
1765 NTSTATUS
smb2srv_session_lookup(struct smbXsrv_connection
*conn
,
1766 uint64_t session_id
, NTTIME now
,
1767 struct smbXsrv_session
**session
)
1769 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1770 return smb2srv_session_lookup_raw(table
, session_id
, now
, session
);
1773 struct smbXsrv_session_global_traverse_state
{
1774 int (*fn
)(struct smbXsrv_session_global0
*, void *);
1778 static int smbXsrv_session_global_traverse_fn(struct db_record
*rec
, void *data
)
1781 struct smbXsrv_session_global_traverse_state
*state
=
1782 (struct smbXsrv_session_global_traverse_state
*)data
;
1783 TDB_DATA key
= dbwrap_record_get_key(rec
);
1784 TDB_DATA val
= dbwrap_record_get_value(rec
);
1785 DATA_BLOB blob
= data_blob_const(val
.dptr
, val
.dsize
);
1786 struct smbXsrv_session_globalB global_blob
;
1787 enum ndr_err_code ndr_err
;
1788 TALLOC_CTX
*frame
= talloc_stackframe();
1790 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
1791 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
1792 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1793 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1794 "key '%s' ndr_pull_struct_blob - %s\n",
1795 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1796 ndr_errstr(ndr_err
)));
1800 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
1801 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1802 "key '%s' unsuported version - %d\n",
1803 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1804 (int)global_blob
.version
));
1808 global_blob
.info
.info0
->db_rec
= rec
;
1809 ret
= state
->fn(global_blob
.info
.info0
, state
->private_data
);
1815 NTSTATUS
smbXsrv_session_global_traverse(
1816 int (*fn
)(struct smbXsrv_session_global0
*, void *),
1822 struct smbXsrv_session_global_traverse_state state
= {
1824 .private_data
= private_data
,
1828 status
= smbXsrv_session_global_init();
1829 if (!NT_STATUS_IS_OK(status
)) {
1831 DEBUG(0, ("Failed to initialize session_global: %s\n",
1832 nt_errstr(status
)));
1836 status
= dbwrap_traverse_read(smbXsrv_session_global_db_ctx
,
1837 smbXsrv_session_global_traverse_fn
,