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 struct db_context
*smbXsrv_session_global_db_ctx
= NULL
;
56 NTSTATUS
smbXsrv_session_global_init(struct messaging_context
*msg_ctx
)
58 char *global_path
= NULL
;
59 struct db_context
*backend
= NULL
;
60 struct db_context
*db_ctx
= NULL
;
62 if (smbXsrv_session_global_db_ctx
!= NULL
) {
67 * This contains secret information like session keys!
69 global_path
= lock_path("smbXsrv_session_global.tdb");
70 if (global_path
== NULL
) {
71 return NT_STATUS_NO_MEMORY
;
74 backend
= db_open(NULL
, global_path
,
78 TDB_INCOMPATIBLE_HASH
,
79 O_RDWR
| O_CREAT
, 0600,
82 TALLOC_FREE(global_path
);
83 if (backend
== NULL
) {
86 status
= map_nt_error_from_unix_common(errno
);
91 db_ctx
= db_open_watched(NULL
, backend
, server_messaging_context());
94 return NT_STATUS_NO_MEMORY
;
97 smbXsrv_session_global_db_ctx
= db_ctx
;
104 * We need to store the keys in big endian so that dbwrap_rbt's memcmp
105 * has the same result as integer comparison between the uint32_t
108 * TODO: implement string based key
111 #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
113 static TDB_DATA
smbXsrv_session_global_id_to_key(uint32_t id
,
118 RSIVAL(key_buf
, 0, id
);
120 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
);
126 static NTSTATUS
smbXsrv_session_global_key_to_id(TDB_DATA key
, uint32_t *id
)
129 return NT_STATUS_INVALID_PARAMETER
;
132 if (key
.dsize
!= SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
) {
133 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
136 *id
= RIVAL(key
.dptr
, 0);
142 #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
144 static TDB_DATA
smbXsrv_session_local_id_to_key(uint32_t id
,
149 RSIVAL(key_buf
, 0, id
);
151 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
);
156 static NTSTATUS
smbXsrv_session_local_key_to_id(TDB_DATA key
, uint32_t *id
)
159 return NT_STATUS_INVALID_PARAMETER
;
162 if (key
.dsize
!= SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
) {
163 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
166 *id
= RIVAL(key
.dptr
, 0);
171 static struct db_record
*smbXsrv_session_global_fetch_locked(
172 struct db_context
*db
,
177 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
178 struct db_record
*rec
= NULL
;
180 key
= smbXsrv_session_global_id_to_key(id
, key_buf
);
182 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
185 DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id
,
186 hex_encode_talloc(talloc_tos(), key
.dptr
, key
.dsize
));
192 static struct db_record
*smbXsrv_session_local_fetch_locked(
193 struct db_context
*db
,
198 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
199 struct db_record
*rec
= NULL
;
201 key
= smbXsrv_session_local_id_to_key(id
, key_buf
);
203 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
206 DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id
,
207 hex_encode_talloc(talloc_tos(), key
.dptr
, key
.dsize
));
213 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
);
215 static NTSTATUS
smbXsrv_session_table_init(struct smbXsrv_connection
*conn
,
218 uint32_t max_sessions
)
220 struct smbXsrv_client
*client
= conn
->client
;
221 struct smbXsrv_session_table
*table
;
223 struct tevent_req
*subreq
;
226 if (lowest_id
> highest_id
) {
227 return NT_STATUS_INTERNAL_ERROR
;
230 max_range
= highest_id
;
231 max_range
-= lowest_id
;
234 if (max_sessions
> max_range
) {
235 return NT_STATUS_INTERNAL_ERROR
;
238 table
= talloc_zero(client
, struct smbXsrv_session_table
);
240 return NT_STATUS_NO_MEMORY
;
243 table
->local
.db_ctx
= db_open_rbt(table
);
244 if (table
->local
.db_ctx
== NULL
) {
246 return NT_STATUS_NO_MEMORY
;
248 table
->local
.lowest_id
= lowest_id
;
249 table
->local
.highest_id
= highest_id
;
250 table
->local
.max_sessions
= max_sessions
;
252 status
= smbXsrv_session_global_init(client
->msg_ctx
);
253 if (!NT_STATUS_IS_OK(status
)) {
258 table
->global
.db_ctx
= smbXsrv_session_global_db_ctx
;
260 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
261 MSG_SMBXSRV_SESSION_CLOSE
);
262 if (subreq
== NULL
) {
264 return NT_STATUS_NO_MEMORY
;
266 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
268 client
->session_table
= table
;
272 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
);
274 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
)
276 struct smbXsrv_client
*client
=
277 tevent_req_callback_data(subreq
,
278 struct smbXsrv_client
);
279 struct smbXsrv_session_table
*table
= client
->session_table
;
281 struct messaging_rec
*rec
= NULL
;
282 struct smbXsrv_session_closeB close_blob
;
283 enum ndr_err_code ndr_err
;
284 struct smbXsrv_session_close0
*close_info0
= NULL
;
285 struct smbXsrv_session
*session
= NULL
;
287 struct timeval tv
= timeval_current();
288 NTTIME now
= timeval_to_nttime(&tv
);
290 ret
= messaging_read_recv(subreq
, talloc_tos(), &rec
);
296 ndr_err
= ndr_pull_struct_blob(&rec
->buf
, rec
, &close_blob
,
297 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_closeB
);
298 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
299 status
= ndr_map_error2ntstatus(ndr_err
);
300 DEBUG(1,("smbXsrv_session_close_loop: "
301 "ndr_pull_struct_blob - %s\n",
306 DEBUG(10,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
308 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
311 if (close_blob
.version
!= SMBXSRV_VERSION_0
) {
312 DEBUG(0,("smbXsrv_session_close_loop: "
313 "ignore invalid version %u\n", close_blob
.version
));
314 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
318 close_info0
= close_blob
.info
.info0
;
319 if (close_info0
== NULL
) {
320 DEBUG(0,("smbXsrv_session_close_loop: "
321 "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 DEBUG(4,("smbXsrv_session_close_loop: "
331 "old_session_wire_id %llu not found\n",
332 (unsigned long long)close_info0
->old_session_wire_id
));
334 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
338 if (!NT_STATUS_IS_OK(status
) &&
339 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
340 !NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
341 DEBUG(1,("smbXsrv_session_close_loop: "
342 "old_session_wire_id %llu - %s\n",
343 (unsigned long long)close_info0
->old_session_wire_id
,
346 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
351 if (session
->global
->session_global_id
!= close_info0
->old_session_global_id
) {
352 DEBUG(1,("smbXsrv_session_close_loop: "
353 "old_session_wire_id %llu - global %u != %u\n",
354 (unsigned long long)close_info0
->old_session_wire_id
,
355 session
->global
->session_global_id
,
356 close_info0
->old_session_global_id
));
358 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
363 if (session
->global
->creation_time
!= close_info0
->old_creation_time
) {
364 DEBUG(1,("smbXsrv_session_close_loop: "
365 "old_session_wire_id %llu - "
366 "creation %s (%llu) != %s (%llu)\n",
367 (unsigned long long)close_info0
->old_session_wire_id
,
368 nt_time_string(rec
, session
->global
->creation_time
),
369 (unsigned long long)session
->global
->creation_time
,
370 nt_time_string(rec
, close_info0
->old_creation_time
),
371 (unsigned long long)close_info0
->old_creation_time
));
373 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
378 subreq
= smb2srv_session_shutdown_send(session
, client
->ev_ctx
,
380 if (subreq
== NULL
) {
381 status
= NT_STATUS_NO_MEMORY
;
382 DEBUG(0, ("smbXsrv_session_close_loop: "
383 "smb2srv_session_shutdown_send(%llu) failed: %s\n",
384 (unsigned long long)session
->global
->session_wire_id
,
387 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
391 tevent_req_set_callback(subreq
,
392 smbXsrv_session_close_shutdown_done
,
398 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
399 MSG_SMBXSRV_SESSION_CLOSE
);
400 if (subreq
== NULL
) {
402 r
= "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
403 exit_server_cleanly(r
);
406 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
409 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
)
411 struct smbXsrv_session
*session
=
412 tevent_req_callback_data(subreq
,
413 struct smbXsrv_session
);
416 status
= smb2srv_session_shutdown_recv(subreq
);
418 if (!NT_STATUS_IS_OK(status
)) {
419 DEBUG(0, ("smbXsrv_session_close_loop: "
420 "smb2srv_session_shutdown_recv(%llu) failed: %s\n",
421 (unsigned long long)session
->global
->session_wire_id
,
425 status
= smbXsrv_session_logoff(session
);
426 if (!NT_STATUS_IS_OK(status
)) {
427 DEBUG(0, ("smbXsrv_session_close_loop: "
428 "smbXsrv_session_logoff(%llu) failed: %s\n",
429 (unsigned long long)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
);
708 static NTSTATUS
smbXsrv_session_global_allocate(struct db_context
*db
,
710 struct smbXsrv_session_global0
**_global
)
713 struct smbXsrv_session_global0
*global
= NULL
;
714 uint32_t last_free
= 0;
715 const uint32_t min_tries
= 3;
719 global
= talloc_zero(mem_ctx
, struct smbXsrv_session_global0
);
720 if (global
== NULL
) {
721 return NT_STATUS_NO_MEMORY
;
723 talloc_set_destructor(global
, smbXsrv_session_global_destructor
);
726 * Here we just randomly try the whole 32-bit space
728 * We use just 32-bit, because we want to reuse the
731 for (i
= 0; i
< UINT32_MAX
; i
++) {
732 bool is_free
= false;
733 bool was_free
= false;
736 if (i
>= min_tries
&& last_free
!= 0) {
739 id
= generate_random();
744 if (id
== UINT32_MAX
) {
748 global
->db_rec
= smbXsrv_session_global_fetch_locked(db
, id
,
750 if (global
->db_rec
== NULL
) {
752 return NT_STATUS_INSUFFICIENT_RESOURCES
;
755 smbXsrv_session_global_verify_record(global
->db_rec
,
761 TALLOC_FREE(global
->db_rec
);
765 if (!was_free
&& i
< min_tries
) {
767 * The session_id is free now,
768 * but was not free before.
770 * This happens if a smbd crashed
771 * and did not cleanup the record.
773 * If this is one of our first tries,
774 * then we try to find a real free one.
776 if (last_free
== 0) {
779 TALLOC_FREE(global
->db_rec
);
783 global
->session_global_id
= id
;
789 /* should not be reached */
791 return NT_STATUS_INTERNAL_ERROR
;
794 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
798 struct smbXsrv_session_global0
**_g
)
803 struct smbXsrv_session_globalB global_blob
;
804 enum ndr_err_code ndr_err
;
805 struct smbXsrv_session_global0
*global
= NULL
;
807 TALLOC_CTX
*frame
= talloc_stackframe();
818 key
= dbwrap_record_get_key(db_rec
);
820 val
= dbwrap_record_get_value(db_rec
);
821 if (val
.dsize
== 0) {
830 blob
= data_blob_const(val
.dptr
, val
.dsize
);
832 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
833 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
834 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
835 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
836 DEBUG(1,("smbXsrv_session_global_verify_record: "
837 "key '%s' ndr_pull_struct_blob - %s\n",
838 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
848 DEBUG(10,("smbXsrv_session_global_verify_record\n"));
850 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
853 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
854 DEBUG(0,("smbXsrv_session_global_verify_record: "
855 "key '%s' use unsupported version %u\n",
856 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
857 global_blob
.version
));
858 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
867 global
= global_blob
.info
.info0
;
869 exists
= serverid_exists(&global
->channels
[0].server_id
);
871 struct server_id_buf idbuf
;
872 DEBUG(2,("smbXsrv_session_global_verify_record: "
873 "key '%s' server_id %s does not exist.\n",
874 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
875 server_id_str_buf(global
->channels
[0].server_id
,
878 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
881 dbwrap_record_delete(db_rec
);
887 *_g
= talloc_move(mem_ctx
, &global
);
892 static NTSTATUS
smbXsrv_session_global_store(struct smbXsrv_session_global0
*global
)
894 struct smbXsrv_session_globalB global_blob
;
895 DATA_BLOB blob
= data_blob_null
;
899 enum ndr_err_code ndr_err
;
902 * TODO: if we use other versions than '0'
903 * we would add glue code here, that would be able to
904 * store the information in the old format.
907 if (global
->db_rec
== NULL
) {
908 return NT_STATUS_INTERNAL_ERROR
;
911 key
= dbwrap_record_get_key(global
->db_rec
);
912 val
= dbwrap_record_get_value(global
->db_rec
);
914 ZERO_STRUCT(global_blob
);
915 global_blob
.version
= smbXsrv_version_global_current();
916 if (val
.dsize
>= 8) {
917 global_blob
.seqnum
= IVAL(val
.dptr
, 4);
919 global_blob
.seqnum
+= 1;
920 global_blob
.info
.info0
= global
;
922 ndr_err
= ndr_push_struct_blob(&blob
, global
->db_rec
, &global_blob
,
923 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_globalB
);
924 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
925 status
= ndr_map_error2ntstatus(ndr_err
);
926 DEBUG(1,("smbXsrv_session_global_store: key '%s' ndr_push - %s\n",
927 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
929 TALLOC_FREE(global
->db_rec
);
933 val
= make_tdb_data(blob
.data
, blob
.length
);
934 status
= dbwrap_record_store(global
->db_rec
, val
, TDB_REPLACE
);
935 if (!NT_STATUS_IS_OK(status
)) {
936 DEBUG(1,("smbXsrv_session_global_store: key '%s' store - %s\n",
937 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
939 TALLOC_FREE(global
->db_rec
);
944 DEBUG(10,("smbXsrv_session_global_store: key '%s' stored\n",
945 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
)));
946 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
949 TALLOC_FREE(global
->db_rec
);
954 struct smb2srv_session_close_previous_state
{
955 struct tevent_context
*ev
;
956 struct smbXsrv_connection
*connection
;
957 struct dom_sid
*current_sid
;
958 uint64_t current_session_id
;
959 struct db_record
*db_rec
;
962 static void smb2srv_session_close_previous_check(struct tevent_req
*req
);
963 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
);
965 struct tevent_req
*smb2srv_session_close_previous_send(TALLOC_CTX
*mem_ctx
,
966 struct tevent_context
*ev
,
967 struct smbXsrv_connection
*conn
,
968 struct auth_session_info
*session_info
,
969 uint64_t previous_session_id
,
970 uint64_t current_session_id
)
972 struct tevent_req
*req
;
973 struct smb2srv_session_close_previous_state
*state
;
974 uint32_t global_id
= previous_session_id
& UINT32_MAX
;
975 uint64_t global_zeros
= previous_session_id
& 0xFFFFFFFF00000000LLU
;
976 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
977 struct security_token
*current_token
= NULL
;
979 req
= tevent_req_create(mem_ctx
, &state
,
980 struct smb2srv_session_close_previous_state
);
985 state
->connection
= conn
;
986 state
->current_session_id
= current_session_id
;
988 if (global_zeros
!= 0) {
989 tevent_req_done(req
);
990 return tevent_req_post(req
, ev
);
993 if (session_info
== NULL
) {
994 tevent_req_done(req
);
995 return tevent_req_post(req
, ev
);
997 current_token
= session_info
->security_token
;
999 if (current_token
->num_sids
> PRIMARY_USER_SID_INDEX
) {
1000 state
->current_sid
= ¤t_token
->sids
[PRIMARY_USER_SID_INDEX
];
1003 if (state
->current_sid
== NULL
) {
1004 tevent_req_done(req
);
1005 return tevent_req_post(req
, ev
);
1008 if (!security_token_has_nt_authenticated_users(current_token
)) {
1010 tevent_req_done(req
);
1011 return tevent_req_post(req
, ev
);
1014 state
->db_rec
= smbXsrv_session_global_fetch_locked(
1015 table
->global
.db_ctx
,
1017 state
/* TALLOC_CTX */);
1018 if (state
->db_rec
== NULL
) {
1019 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1020 return tevent_req_post(req
, ev
);
1023 smb2srv_session_close_previous_check(req
);
1024 if (!tevent_req_is_in_progress(req
)) {
1025 return tevent_req_post(req
, ev
);
1031 static void smb2srv_session_close_previous_check(struct tevent_req
*req
)
1033 struct smb2srv_session_close_previous_state
*state
=
1034 tevent_req_data(req
,
1035 struct smb2srv_session_close_previous_state
);
1036 struct smbXsrv_connection
*conn
= state
->connection
;
1038 struct security_token
*previous_token
= NULL
;
1039 struct smbXsrv_session_global0
*global
= NULL
;
1040 enum ndr_err_code ndr_err
;
1041 struct smbXsrv_session_close0 close_info0
;
1042 struct smbXsrv_session_closeB close_blob
;
1043 struct tevent_req
*subreq
= NULL
;
1045 bool is_free
= false;
1047 smbXsrv_session_global_verify_record(state
->db_rec
,
1054 TALLOC_FREE(state
->db_rec
);
1055 tevent_req_done(req
);
1059 if (global
->auth_session_info
== NULL
) {
1060 TALLOC_FREE(state
->db_rec
);
1061 tevent_req_done(req
);
1065 previous_token
= global
->auth_session_info
->security_token
;
1067 if (!security_token_is_sid(previous_token
, state
->current_sid
)) {
1068 TALLOC_FREE(state
->db_rec
);
1069 tevent_req_done(req
);
1073 subreq
= dbwrap_watched_watch_send(state
, state
->ev
, state
->db_rec
,
1074 (struct server_id
){0});
1075 if (tevent_req_nomem(subreq
, req
)) {
1076 TALLOC_FREE(state
->db_rec
);
1079 tevent_req_set_callback(subreq
,
1080 smb2srv_session_close_previous_modified
,
1083 close_info0
.old_session_global_id
= global
->session_global_id
;
1084 close_info0
.old_session_wire_id
= global
->session_wire_id
;
1085 close_info0
.old_creation_time
= global
->creation_time
;
1086 close_info0
.new_session_wire_id
= state
->current_session_id
;
1088 ZERO_STRUCT(close_blob
);
1089 close_blob
.version
= smbXsrv_version_global_current();
1090 close_blob
.info
.info0
= &close_info0
;
1092 ndr_err
= ndr_push_struct_blob(&blob
, state
, &close_blob
,
1093 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_closeB
);
1094 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1095 TALLOC_FREE(state
->db_rec
);
1096 status
= ndr_map_error2ntstatus(ndr_err
);
1097 DEBUG(1,("smb2srv_session_close_previous_check: "
1098 "old_session[%llu] new_session[%llu] ndr_push - %s\n",
1099 (unsigned long long)close_info0
.old_session_wire_id
,
1100 (unsigned long long)close_info0
.new_session_wire_id
,
1101 nt_errstr(status
)));
1102 tevent_req_nterror(req
, status
);
1106 status
= messaging_send(conn
->msg_ctx
,
1107 global
->channels
[0].server_id
,
1108 MSG_SMBXSRV_SESSION_CLOSE
, &blob
);
1109 TALLOC_FREE(state
->db_rec
);
1110 if (tevent_req_nterror(req
, status
)) {
1114 TALLOC_FREE(global
);
1118 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
)
1120 struct tevent_req
*req
=
1121 tevent_req_callback_data(subreq
,
1123 struct smb2srv_session_close_previous_state
*state
=
1124 tevent_req_data(req
,
1125 struct smb2srv_session_close_previous_state
);
1128 status
= dbwrap_watched_watch_recv(subreq
, state
, &state
->db_rec
, NULL
,
1130 TALLOC_FREE(subreq
);
1131 if (tevent_req_nterror(req
, status
)) {
1135 smb2srv_session_close_previous_check(req
);
1138 NTSTATUS
smb2srv_session_close_previous_recv(struct tevent_req
*req
)
1142 if (tevent_req_is_nterror(req
, &status
)) {
1143 tevent_req_received(req
);
1147 tevent_req_received(req
);
1148 return NT_STATUS_OK
;
1151 static NTSTATUS
smbXsrv_session_clear_and_logoff(struct smbXsrv_session
*session
)
1154 struct smbXsrv_connection
*xconn
= NULL
;
1156 if (session
->client
!= NULL
) {
1157 xconn
= session
->client
->connections
;
1160 for (; xconn
!= NULL
; xconn
= xconn
->next
) {
1161 struct smbd_smb2_request
*preq
;
1163 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1164 if (preq
->session
!= session
) {
1168 preq
->session
= NULL
;
1170 * If we no longer have a session we can't
1171 * sign or encrypt replies.
1173 preq
->do_signing
= false;
1174 preq
->do_encryption
= false;
1175 preq
->preauth
= NULL
;
1179 status
= smbXsrv_session_logoff(session
);
1183 static int smbXsrv_session_destructor(struct smbXsrv_session
*session
)
1187 status
= smbXsrv_session_clear_and_logoff(session
);
1188 if (!NT_STATUS_IS_OK(status
)) {
1189 DEBUG(0, ("smbXsrv_session_destructor: "
1190 "smbXsrv_session_logoff() failed: %s\n",
1191 nt_errstr(status
)));
1194 TALLOC_FREE(session
->global
);
1199 NTSTATUS
smbXsrv_session_create(struct smbXsrv_connection
*conn
,
1201 struct smbXsrv_session
**_session
)
1203 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1204 struct db_record
*local_rec
= NULL
;
1205 struct smbXsrv_session
*session
= NULL
;
1208 struct smbXsrv_session_global0
*global
= NULL
;
1209 struct smbXsrv_channel_global0
*channel
= NULL
;
1212 if (table
->local
.num_sessions
>= table
->local
.max_sessions
) {
1213 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1216 session
= talloc_zero(table
, struct smbXsrv_session
);
1217 if (session
== NULL
) {
1218 return NT_STATUS_NO_MEMORY
;
1220 session
->table
= table
;
1221 session
->idle_time
= now
;
1222 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
1223 session
->client
= conn
->client
;
1225 status
= smbXsrv_session_global_allocate(table
->global
.db_ctx
,
1228 if (!NT_STATUS_IS_OK(status
)) {
1229 TALLOC_FREE(session
);
1232 session
->global
= global
;
1234 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1235 uint64_t id
= global
->session_global_id
;
1237 global
->connection_dialect
= conn
->smb2
.server
.dialect
;
1239 global
->session_wire_id
= id
;
1241 status
= smb2srv_tcon_table_init(session
);
1242 if (!NT_STATUS_IS_OK(status
)) {
1243 TALLOC_FREE(session
);
1247 session
->local_id
= global
->session_global_id
;
1249 local_rec
= smbXsrv_session_local_fetch_locked(
1250 table
->local
.db_ctx
,
1252 session
/* TALLOC_CTX */);
1253 if (local_rec
== NULL
) {
1254 TALLOC_FREE(session
);
1255 return NT_STATUS_NO_MEMORY
;
1258 val
= dbwrap_record_get_value(local_rec
);
1259 if (val
.dsize
!= 0) {
1260 TALLOC_FREE(session
);
1261 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1265 status
= smb1srv_session_local_allocate_id(table
->local
.db_ctx
,
1266 table
->local
.lowest_id
,
1267 table
->local
.highest_id
,
1270 &session
->local_id
);
1271 if (!NT_STATUS_IS_OK(status
)) {
1272 TALLOC_FREE(session
);
1276 global
->session_wire_id
= session
->local_id
;
1279 global
->creation_time
= now
;
1280 global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1282 status
= smbXsrv_session_add_channel(session
, conn
, &channel
);
1283 if (!NT_STATUS_IS_OK(status
)) {
1284 TALLOC_FREE(session
);
1289 val
= make_tdb_data((uint8_t const *)&ptr
, sizeof(ptr
));
1290 status
= dbwrap_record_store(local_rec
, val
, TDB_REPLACE
);
1291 TALLOC_FREE(local_rec
);
1292 if (!NT_STATUS_IS_OK(status
)) {
1293 TALLOC_FREE(session
);
1296 table
->local
.num_sessions
+= 1;
1298 talloc_set_destructor(session
, smbXsrv_session_destructor
);
1300 status
= smbXsrv_session_global_store(global
);
1301 if (!NT_STATUS_IS_OK(status
)) {
1302 DEBUG(0,("smbXsrv_session_create: "
1303 "global_id (0x%08x) store failed - %s\n",
1304 session
->global
->session_global_id
,
1305 nt_errstr(status
)));
1306 TALLOC_FREE(session
);
1311 struct smbXsrv_sessionB session_blob
;
1313 ZERO_STRUCT(session_blob
);
1314 session_blob
.version
= SMBXSRV_VERSION_0
;
1315 session_blob
.info
.info0
= session
;
1317 DEBUG(10,("smbXsrv_session_create: global_id (0x%08x) stored\n",
1318 session
->global
->session_global_id
));
1319 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1322 *_session
= session
;
1323 return NT_STATUS_OK
;
1326 NTSTATUS
smbXsrv_session_add_channel(struct smbXsrv_session
*session
,
1327 struct smbXsrv_connection
*conn
,
1328 struct smbXsrv_channel_global0
**_c
)
1330 struct smbXsrv_session_global0
*global
= session
->global
;
1331 struct smbXsrv_channel_global0
*c
= NULL
;
1333 if (global
->num_channels
> 31) {
1335 * Windows 2012 and 2012R2 allow up to 32 channels
1337 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1340 c
= talloc_realloc(global
,
1342 struct smbXsrv_channel_global0
,
1343 global
->num_channels
+ 1);
1345 return NT_STATUS_NO_MEMORY
;
1347 global
->channels
= c
;
1349 c
= &global
->channels
[global
->num_channels
];
1352 c
->server_id
= messaging_server_id(conn
->msg_ctx
);
1353 c
->local_address
= tsocket_address_string(conn
->local_address
,
1355 if (c
->local_address
== NULL
) {
1356 return NT_STATUS_NO_MEMORY
;
1358 c
->remote_address
= tsocket_address_string(conn
->remote_address
,
1360 if (c
->remote_address
== NULL
) {
1361 return NT_STATUS_NO_MEMORY
;
1363 c
->remote_name
= talloc_strdup(global
->channels
,
1364 conn
->remote_hostname
);
1365 if (c
->remote_name
== NULL
) {
1366 return NT_STATUS_NO_MEMORY
;
1368 c
->connection
= conn
;
1370 global
->num_channels
+= 1;
1373 return NT_STATUS_OK
;
1376 NTSTATUS
smbXsrv_session_update(struct smbXsrv_session
*session
)
1378 struct smbXsrv_session_table
*table
= session
->table
;
1381 if (session
->global
->db_rec
!= NULL
) {
1382 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1383 "Called with db_rec != NULL'\n",
1384 session
->global
->session_global_id
));
1385 return NT_STATUS_INTERNAL_ERROR
;
1388 session
->global
->db_rec
= smbXsrv_session_global_fetch_locked(
1389 table
->global
.db_ctx
,
1390 session
->global
->session_global_id
,
1391 session
->global
/* TALLOC_CTX */);
1392 if (session
->global
->db_rec
== NULL
) {
1393 return NT_STATUS_INTERNAL_DB_ERROR
;
1396 status
= smbXsrv_session_global_store(session
->global
);
1397 if (!NT_STATUS_IS_OK(status
)) {
1398 DEBUG(0,("smbXsrv_session_update: "
1399 "global_id (0x%08x) store failed - %s\n",
1400 session
->global
->session_global_id
,
1401 nt_errstr(status
)));
1406 struct smbXsrv_sessionB session_blob
;
1408 ZERO_STRUCT(session_blob
);
1409 session_blob
.version
= SMBXSRV_VERSION_0
;
1410 session_blob
.info
.info0
= session
;
1412 DEBUG(10,("smbXsrv_session_update: global_id (0x%08x) stored\n",
1413 session
->global
->session_global_id
));
1414 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1417 return NT_STATUS_OK
;
1420 NTSTATUS
smbXsrv_session_find_channel(const struct smbXsrv_session
*session
,
1421 const struct smbXsrv_connection
*conn
,
1422 struct smbXsrv_channel_global0
**_c
)
1426 for (i
=0; i
< session
->global
->num_channels
; i
++) {
1427 struct smbXsrv_channel_global0
*c
= &session
->global
->channels
[i
];
1429 if (c
->connection
== conn
) {
1431 return NT_STATUS_OK
;
1435 return NT_STATUS_USER_SESSION_DELETED
;
1438 NTSTATUS
smbXsrv_session_find_auth(const struct smbXsrv_session
*session
,
1439 const struct smbXsrv_connection
*conn
,
1441 struct smbXsrv_session_auth0
**_a
)
1443 struct smbXsrv_session_auth0
*a
;
1445 for (a
= session
->pending_auth
; a
!= NULL
; a
= a
->next
) {
1446 if (a
->connection
== conn
) {
1451 return NT_STATUS_OK
;
1455 return NT_STATUS_USER_SESSION_DELETED
;
1458 static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0
*a
)
1460 if (a
->session
== NULL
) {
1464 DLIST_REMOVE(a
->session
->pending_auth
, a
);
1469 NTSTATUS
smbXsrv_session_create_auth(struct smbXsrv_session
*session
,
1470 struct smbXsrv_connection
*conn
,
1473 uint8_t in_security_mode
,
1474 struct smbXsrv_session_auth0
**_a
)
1476 struct smbXsrv_session_auth0
*a
;
1479 status
= smbXsrv_session_find_auth(session
, conn
, 0, &a
);
1480 if (NT_STATUS_IS_OK(status
)) {
1481 return NT_STATUS_INTERNAL_ERROR
;
1484 a
= talloc_zero(session
, struct smbXsrv_session_auth0
);
1486 return NT_STATUS_NO_MEMORY
;
1488 a
->session
= session
;
1489 a
->connection
= conn
;
1490 a
->in_flags
= in_flags
;
1491 a
->in_security_mode
= in_security_mode
;
1492 a
->creation_time
= now
;
1495 if (conn
->protocol
>= PROTOCOL_SMB3_10
) {
1496 a
->preauth
= talloc(a
, struct smbXsrv_preauth
);
1497 if (a
->preauth
== NULL
) {
1498 TALLOC_FREE(session
);
1499 return NT_STATUS_NO_MEMORY
;
1501 *a
->preauth
= conn
->smb2
.preauth
;
1504 talloc_set_destructor(a
, smbXsrv_session_auth0_destructor
);
1505 DLIST_ADD_END(session
->pending_auth
, a
);
1508 return NT_STATUS_OK
;
1511 struct smb2srv_session_shutdown_state
{
1512 struct tevent_queue
*wait_queue
;
1515 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
);
1517 struct tevent_req
*smb2srv_session_shutdown_send(TALLOC_CTX
*mem_ctx
,
1518 struct tevent_context
*ev
,
1519 struct smbXsrv_session
*session
,
1520 struct smbd_smb2_request
*current_req
)
1522 struct tevent_req
*req
;
1523 struct smb2srv_session_shutdown_state
*state
;
1524 struct tevent_req
*subreq
;
1525 struct smbXsrv_connection
*xconn
= NULL
;
1529 * Make sure that no new request will be able to use this session.
1531 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1533 req
= tevent_req_create(mem_ctx
, &state
,
1534 struct smb2srv_session_shutdown_state
);
1539 state
->wait_queue
= tevent_queue_create(state
, "smb2srv_session_shutdown_queue");
1540 if (tevent_req_nomem(state
->wait_queue
, req
)) {
1541 return tevent_req_post(req
, ev
);
1544 for (xconn
= session
->client
->connections
; xconn
!= NULL
; xconn
= xconn
->next
) {
1545 struct smbd_smb2_request
*preq
;
1547 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1548 if (preq
== current_req
) {
1549 /* Can't cancel current request. */
1552 if (preq
->session
!= session
) {
1553 /* Request on different session. */
1557 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
1558 preq
->session
= NULL
;
1560 * If we no longer have a session we can't
1561 * sign or encrypt replies.
1563 preq
->do_signing
= false;
1564 preq
->do_encryption
= false;
1565 preq
->preauth
= NULL
;
1567 if (preq
->subreq
!= NULL
) {
1568 tevent_req_cancel(preq
->subreq
);
1574 * Never cancel anything in a compound
1575 * request. Way too hard to deal with
1578 if (!preq
->compound_related
&& preq
->subreq
!= NULL
) {
1579 tevent_req_cancel(preq
->subreq
);
1583 * Now wait until the request is finished.
1585 * We don't set a callback, as we just want to block the
1586 * wait queue and the talloc_free() of the request will
1587 * remove the item from the wait queue.
1589 subreq
= tevent_queue_wait_send(preq
, ev
, state
->wait_queue
);
1590 if (tevent_req_nomem(subreq
, req
)) {
1591 return tevent_req_post(req
, ev
);
1596 len
= tevent_queue_length(state
->wait_queue
);
1598 tevent_req_done(req
);
1599 return tevent_req_post(req
, ev
);
1603 * Now we add our own waiter to the end of the queue,
1604 * this way we get notified when all pending requests are finished
1605 * and send to the socket.
1607 subreq
= tevent_queue_wait_send(state
, ev
, state
->wait_queue
);
1608 if (tevent_req_nomem(subreq
, req
)) {
1609 return tevent_req_post(req
, ev
);
1611 tevent_req_set_callback(subreq
, smb2srv_session_shutdown_wait_done
, req
);
1616 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
)
1618 struct tevent_req
*req
=
1619 tevent_req_callback_data(subreq
,
1622 tevent_queue_wait_recv(subreq
);
1623 TALLOC_FREE(subreq
);
1625 tevent_req_done(req
);
1628 NTSTATUS
smb2srv_session_shutdown_recv(struct tevent_req
*req
)
1630 return tevent_req_simple_recv_ntstatus(req
);
1633 NTSTATUS
smbXsrv_session_logoff(struct smbXsrv_session
*session
)
1635 struct smbXsrv_session_table
*table
;
1636 struct db_record
*local_rec
= NULL
;
1637 struct db_record
*global_rec
= NULL
;
1638 struct smbd_server_connection
*sconn
= NULL
;
1640 NTSTATUS error
= NT_STATUS_OK
;
1642 if (session
->table
== NULL
) {
1643 return NT_STATUS_OK
;
1646 table
= session
->table
;
1647 session
->table
= NULL
;
1649 sconn
= session
->client
->sconn
;
1650 session
->client
= NULL
;
1651 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1653 global_rec
= session
->global
->db_rec
;
1654 session
->global
->db_rec
= NULL
;
1655 if (global_rec
== NULL
) {
1656 global_rec
= smbXsrv_session_global_fetch_locked(
1657 table
->global
.db_ctx
,
1658 session
->global
->session_global_id
,
1659 session
->global
/* TALLOC_CTX */);
1660 if (global_rec
== NULL
) {
1661 error
= NT_STATUS_INTERNAL_ERROR
;
1665 if (global_rec
!= NULL
) {
1666 status
= dbwrap_record_delete(global_rec
);
1667 if (!NT_STATUS_IS_OK(status
)) {
1668 TDB_DATA key
= dbwrap_record_get_key(global_rec
);
1670 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1671 "failed to delete global key '%s': %s\n",
1672 session
->global
->session_global_id
,
1673 hex_encode_talloc(global_rec
, key
.dptr
,
1675 nt_errstr(status
)));
1679 TALLOC_FREE(global_rec
);
1681 local_rec
= session
->db_rec
;
1682 if (local_rec
== NULL
) {
1683 local_rec
= smbXsrv_session_local_fetch_locked(
1684 table
->local
.db_ctx
,
1686 session
/* TALLOC_CTX */);
1687 if (local_rec
== NULL
) {
1688 error
= NT_STATUS_INTERNAL_ERROR
;
1692 if (local_rec
!= NULL
) {
1693 status
= dbwrap_record_delete(local_rec
);
1694 if (!NT_STATUS_IS_OK(status
)) {
1695 TDB_DATA key
= dbwrap_record_get_key(local_rec
);
1697 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1698 "failed to delete local key '%s': %s\n",
1699 session
->global
->session_global_id
,
1700 hex_encode_talloc(local_rec
, key
.dptr
,
1702 nt_errstr(status
)));
1705 table
->local
.num_sessions
-= 1;
1707 if (session
->db_rec
== NULL
) {
1708 TALLOC_FREE(local_rec
);
1710 session
->db_rec
= NULL
;
1712 if (session
->compat
) {
1713 file_close_user(sconn
, session
->compat
->vuid
);
1716 if (session
->tcon_table
!= NULL
) {
1718 * Note: We only have a tcon_table for SMB2.
1720 status
= smb2srv_tcon_disconnect_all(session
);
1721 if (!NT_STATUS_IS_OK(status
)) {
1722 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1723 "smb2srv_tcon_disconnect_all() failed: %s\n",
1724 session
->global
->session_global_id
,
1725 nt_errstr(status
)));
1730 if (session
->compat
) {
1731 invalidate_vuid(sconn
, session
->compat
->vuid
);
1732 session
->compat
= NULL
;
1738 struct smbXsrv_session_logoff_all_state
{
1739 NTSTATUS first_status
;
1743 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1744 void *private_data
);
1746 NTSTATUS
smbXsrv_session_logoff_all(struct smbXsrv_connection
*conn
)
1748 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1749 struct smbXsrv_session_logoff_all_state state
;
1753 if (table
== NULL
) {
1754 DEBUG(10, ("smbXsrv_session_logoff_all: "
1755 "empty session_table, nothing to do.\n"));
1756 return NT_STATUS_OK
;
1761 status
= dbwrap_traverse(table
->local
.db_ctx
,
1762 smbXsrv_session_logoff_all_callback
,
1764 if (!NT_STATUS_IS_OK(status
)) {
1765 DEBUG(0, ("smbXsrv_session_logoff_all: "
1766 "dbwrap_traverse() failed: %s\n",
1767 nt_errstr(status
)));
1771 if (!NT_STATUS_IS_OK(state
.first_status
)) {
1772 DEBUG(0, ("smbXsrv_session_logoff_all: "
1773 "count[%d] errors[%d] first[%s]\n",
1774 count
, state
.errors
,
1775 nt_errstr(state
.first_status
)));
1776 return state
.first_status
;
1779 return NT_STATUS_OK
;
1782 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1785 struct smbXsrv_session_logoff_all_state
*state
=
1786 (struct smbXsrv_session_logoff_all_state
*)private_data
;
1789 struct smbXsrv_session
*session
= NULL
;
1792 val
= dbwrap_record_get_value(local_rec
);
1793 if (val
.dsize
!= sizeof(ptr
)) {
1794 status
= NT_STATUS_INTERNAL_ERROR
;
1795 if (NT_STATUS_IS_OK(state
->first_status
)) {
1796 state
->first_status
= status
;
1802 memcpy(&ptr
, val
.dptr
, val
.dsize
);
1803 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
1805 session
->db_rec
= local_rec
;
1807 status
= smbXsrv_session_clear_and_logoff(session
);
1808 if (!NT_STATUS_IS_OK(status
)) {
1809 if (NT_STATUS_IS_OK(state
->first_status
)) {
1810 state
->first_status
= status
;
1819 NTSTATUS
smb1srv_session_table_init(struct smbXsrv_connection
*conn
)
1822 * Allow a range from 1..65534 with 65534 values.
1824 return smbXsrv_session_table_init(conn
, 1, UINT16_MAX
- 1,
1828 NTSTATUS
smb1srv_session_lookup(struct smbXsrv_connection
*conn
,
1829 uint16_t vuid
, NTTIME now
,
1830 struct smbXsrv_session
**session
)
1832 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1833 uint32_t local_id
= vuid
;
1835 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
1839 NTSTATUS
smb2srv_session_table_init(struct smbXsrv_connection
*conn
)
1842 * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
1844 return smbXsrv_session_table_init(conn
, 1, UINT32_MAX
- 1,
1848 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
1849 /* conn: optional */
1850 struct smbXsrv_connection
*conn
,
1851 uint64_t session_id
, NTTIME now
,
1852 struct smbXsrv_session
**session
)
1854 uint32_t local_id
= session_id
& UINT32_MAX
;
1855 uint64_t local_zeros
= session_id
& 0xFFFFFFFF00000000LLU
;
1857 if (local_zeros
!= 0) {
1858 return NT_STATUS_USER_SESSION_DELETED
;
1861 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
1865 NTSTATUS
smb2srv_session_lookup_conn(struct smbXsrv_connection
*conn
,
1866 uint64_t session_id
, NTTIME now
,
1867 struct smbXsrv_session
**session
)
1869 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1870 return smb2srv_session_lookup_raw(table
, conn
, session_id
, now
,
1874 NTSTATUS
smb2srv_session_lookup_client(struct smbXsrv_client
*client
,
1875 uint64_t session_id
, NTTIME now
,
1876 struct smbXsrv_session
**session
)
1878 struct smbXsrv_session_table
*table
= client
->session_table
;
1879 return smb2srv_session_lookup_raw(table
, NULL
, session_id
, now
,
1883 struct smbXsrv_session_global_traverse_state
{
1884 int (*fn
)(struct smbXsrv_session_global0
*, void *);
1888 static int smbXsrv_session_global_traverse_fn(struct db_record
*rec
, void *data
)
1891 struct smbXsrv_session_global_traverse_state
*state
=
1892 (struct smbXsrv_session_global_traverse_state
*)data
;
1893 TDB_DATA key
= dbwrap_record_get_key(rec
);
1894 TDB_DATA val
= dbwrap_record_get_value(rec
);
1895 DATA_BLOB blob
= data_blob_const(val
.dptr
, val
.dsize
);
1896 struct smbXsrv_session_globalB global_blob
;
1897 enum ndr_err_code ndr_err
;
1898 TALLOC_CTX
*frame
= talloc_stackframe();
1900 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
1901 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
1902 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1903 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1904 "key '%s' ndr_pull_struct_blob - %s\n",
1905 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1906 ndr_errstr(ndr_err
)));
1910 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
1911 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1912 "key '%s' unsuported version - %d\n",
1913 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1914 (int)global_blob
.version
));
1918 global_blob
.info
.info0
->db_rec
= rec
;
1919 ret
= state
->fn(global_blob
.info
.info0
, state
->private_data
);
1925 NTSTATUS
smbXsrv_session_global_traverse(
1926 int (*fn
)(struct smbXsrv_session_global0
*, void *),
1932 struct smbXsrv_session_global_traverse_state state
= {
1934 .private_data
= private_data
,
1938 status
= smbXsrv_session_global_init(NULL
);
1939 if (!NT_STATUS_IS_OK(status
)) {
1941 DEBUG(0, ("Failed to initialize session_global: %s\n",
1942 nt_errstr(status
)));
1946 status
= dbwrap_traverse_read(smbXsrv_session_global_db_ctx
,
1947 smbXsrv_session_global_traverse_fn
,