2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2011-2012
5 Copyright (C) Michael Adam 2012
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
24 #include "lib/util/server_id.h"
25 #include "smbd/smbd.h"
26 #include "smbd/globals.h"
27 #include "dbwrap/dbwrap.h"
28 #include "dbwrap/dbwrap_rbt.h"
29 #include "dbwrap/dbwrap_open.h"
30 #include "dbwrap/dbwrap_watch.h"
33 #include "auth/gensec/gensec.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "../libcli/security/security.h"
37 #include "lib/util/util_tdb.h"
38 #include "librpc/gen_ndr/ndr_smbXsrv.h"
40 #include "lib/util/tevent_ntstatus.h"
42 struct smbXsrv_session_table
{
44 struct db_context
*db_ctx
;
47 uint32_t max_sessions
;
48 uint32_t num_sessions
;
51 struct db_context
*db_ctx
;
55 static struct db_context
*smbXsrv_session_global_db_ctx
= NULL
;
57 NTSTATUS
smbXsrv_session_global_init(struct messaging_context
*msg_ctx
)
59 char *global_path
= NULL
;
60 struct db_context
*backend
= NULL
;
61 struct db_context
*db_ctx
= NULL
;
63 if (smbXsrv_session_global_db_ctx
!= NULL
) {
68 * This contains secret information like session keys!
70 global_path
= lock_path("smbXsrv_session_global.tdb");
71 if (global_path
== NULL
) {
72 return NT_STATUS_NO_MEMORY
;
75 backend
= db_open(NULL
, global_path
,
79 TDB_INCOMPATIBLE_HASH
,
80 O_RDWR
| O_CREAT
, 0600,
83 TALLOC_FREE(global_path
);
84 if (backend
== NULL
) {
87 status
= map_nt_error_from_unix_common(errno
);
92 db_ctx
= db_open_watched(NULL
, backend
, server_messaging_context());
95 return NT_STATUS_NO_MEMORY
;
98 smbXsrv_session_global_db_ctx
= db_ctx
;
105 * We need to store the keys in big endian so that dbwrap_rbt's memcmp
106 * has the same result as integer comparison between the uint32_t
109 * TODO: implement string based key
112 #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
114 static TDB_DATA
smbXsrv_session_global_id_to_key(uint32_t id
,
119 RSIVAL(key_buf
, 0, id
);
121 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
);
127 static NTSTATUS
smbXsrv_session_global_key_to_id(TDB_DATA key
, uint32_t *id
)
130 return NT_STATUS_INVALID_PARAMETER
;
133 if (key
.dsize
!= SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
) {
134 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
137 *id
= RIVAL(key
.dptr
, 0);
143 #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
145 static TDB_DATA
smbXsrv_session_local_id_to_key(uint32_t id
,
150 RSIVAL(key_buf
, 0, id
);
152 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
);
157 static NTSTATUS
smbXsrv_session_local_key_to_id(TDB_DATA key
, uint32_t *id
)
160 return NT_STATUS_INVALID_PARAMETER
;
163 if (key
.dsize
!= SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
) {
164 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
167 *id
= RIVAL(key
.dptr
, 0);
172 static struct db_record
*smbXsrv_session_global_fetch_locked(
173 struct db_context
*db
,
178 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
179 struct db_record
*rec
= NULL
;
181 key
= smbXsrv_session_global_id_to_key(id
, key_buf
);
183 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
186 DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id
,
187 hex_encode_talloc(talloc_tos(), key
.dptr
, key
.dsize
));
193 static struct db_record
*smbXsrv_session_local_fetch_locked(
194 struct db_context
*db
,
199 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
200 struct db_record
*rec
= NULL
;
202 key
= smbXsrv_session_local_id_to_key(id
, key_buf
);
204 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
207 DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id
,
208 hex_encode_talloc(talloc_tos(), key
.dptr
, key
.dsize
));
214 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
);
216 static NTSTATUS
smbXsrv_session_table_init(struct smbXsrv_connection
*conn
,
219 uint32_t max_sessions
)
221 struct smbXsrv_client
*client
= conn
->client
;
222 struct smbXsrv_session_table
*table
;
224 struct tevent_req
*subreq
;
227 if (lowest_id
> highest_id
) {
228 return NT_STATUS_INTERNAL_ERROR
;
231 max_range
= highest_id
;
232 max_range
-= lowest_id
;
235 if (max_sessions
> max_range
) {
236 return NT_STATUS_INTERNAL_ERROR
;
239 table
= talloc_zero(client
, struct smbXsrv_session_table
);
241 return NT_STATUS_NO_MEMORY
;
244 table
->local
.db_ctx
= db_open_rbt(table
);
245 if (table
->local
.db_ctx
== NULL
) {
247 return NT_STATUS_NO_MEMORY
;
249 table
->local
.lowest_id
= lowest_id
;
250 table
->local
.highest_id
= highest_id
;
251 table
->local
.max_sessions
= max_sessions
;
253 status
= smbXsrv_session_global_init(client
->msg_ctx
);
254 if (!NT_STATUS_IS_OK(status
)) {
259 table
->global
.db_ctx
= smbXsrv_session_global_db_ctx
;
261 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
262 MSG_SMBXSRV_SESSION_CLOSE
);
263 if (subreq
== NULL
) {
265 return NT_STATUS_NO_MEMORY
;
267 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
269 client
->session_table
= table
;
273 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
);
275 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
)
277 struct smbXsrv_client
*client
=
278 tevent_req_callback_data(subreq
,
279 struct smbXsrv_client
);
280 struct smbXsrv_session_table
*table
= client
->session_table
;
282 struct messaging_rec
*rec
= NULL
;
283 struct smbXsrv_session_closeB close_blob
;
284 enum ndr_err_code ndr_err
;
285 struct smbXsrv_session_close0
*close_info0
= NULL
;
286 struct smbXsrv_session
*session
= NULL
;
288 struct timeval tv
= timeval_current();
289 NTTIME now
= timeval_to_nttime(&tv
);
291 ret
= messaging_read_recv(subreq
, talloc_tos(), &rec
);
297 ndr_err
= ndr_pull_struct_blob(&rec
->buf
, rec
, &close_blob
,
298 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_closeB
);
299 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
300 status
= ndr_map_error2ntstatus(ndr_err
);
301 DEBUG(1,("smbXsrv_session_close_loop: "
302 "ndr_pull_struct_blob - %s\n",
307 DEBUG(10,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
309 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
312 if (close_blob
.version
!= SMBXSRV_VERSION_0
) {
313 DEBUG(0,("smbXsrv_session_close_loop: "
314 "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 DEBUG(0,("smbXsrv_session_close_loop: "
322 "ignore NULL info %u\n", close_blob
.version
));
323 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
327 status
= smb2srv_session_lookup_client(client
,
328 close_info0
->old_session_wire_id
,
330 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_SESSION_DELETED
)) {
331 DEBUG(4,("smbXsrv_session_close_loop: "
332 "old_session_wire_id %llu not found\n",
333 (unsigned long long)close_info0
->old_session_wire_id
));
335 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
339 if (!NT_STATUS_IS_OK(status
) &&
340 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
341 !NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
342 DEBUG(1,("smbXsrv_session_close_loop: "
343 "old_session_wire_id %llu - %s\n",
344 (unsigned long long)close_info0
->old_session_wire_id
,
347 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
352 if (session
->global
->session_global_id
!= close_info0
->old_session_global_id
) {
353 DEBUG(1,("smbXsrv_session_close_loop: "
354 "old_session_wire_id %llu - global %u != %u\n",
355 (unsigned long long)close_info0
->old_session_wire_id
,
356 session
->global
->session_global_id
,
357 close_info0
->old_session_global_id
));
359 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
364 if (session
->global
->creation_time
!= close_info0
->old_creation_time
) {
365 DEBUG(1,("smbXsrv_session_close_loop: "
366 "old_session_wire_id %llu - "
367 "creation %s (%llu) != %s (%llu)\n",
368 (unsigned long long)close_info0
->old_session_wire_id
,
369 nt_time_string(rec
, session
->global
->creation_time
),
370 (unsigned long long)session
->global
->creation_time
,
371 nt_time_string(rec
, close_info0
->old_creation_time
),
372 (unsigned long long)close_info0
->old_creation_time
));
374 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
379 subreq
= smb2srv_session_shutdown_send(session
, client
->ev_ctx
,
381 if (subreq
== NULL
) {
382 status
= NT_STATUS_NO_MEMORY
;
383 DEBUG(0, ("smbXsrv_session_close_loop: "
384 "smb2srv_session_shutdown_send(%llu) failed: %s\n",
385 (unsigned long long)session
->global
->session_wire_id
,
388 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
392 tevent_req_set_callback(subreq
,
393 smbXsrv_session_close_shutdown_done
,
399 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
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 DEBUG(0, ("smbXsrv_session_close_loop: "
421 "smb2srv_session_shutdown_recv(%llu) failed: %s\n",
422 (unsigned long long)session
->global
->session_wire_id
,
426 status
= smbXsrv_session_logoff(session
);
427 if (!NT_STATUS_IS_OK(status
)) {
428 DEBUG(0, ("smbXsrv_session_close_loop: "
429 "smbXsrv_session_logoff(%llu) failed: %s\n",
430 (unsigned long long)session
->global
->session_wire_id
,
434 TALLOC_FREE(session
);
437 struct smb1srv_session_local_allocate_state
{
438 const uint32_t lowest_id
;
439 const uint32_t highest_id
;
445 static int smb1srv_session_local_allocate_traverse(struct db_record
*rec
,
448 struct smb1srv_session_local_allocate_state
*state
=
449 (struct smb1srv_session_local_allocate_state
*)private_data
;
450 TDB_DATA key
= dbwrap_record_get_key(rec
);
454 status
= smbXsrv_session_local_key_to_id(key
, &id
);
455 if (!NT_STATUS_IS_OK(status
)) {
456 state
->status
= status
;
460 if (id
<= state
->last_id
) {
461 state
->status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
466 if (id
> state
->useable_id
) {
467 state
->status
= NT_STATUS_OK
;
471 if (state
->useable_id
== state
->highest_id
) {
472 state
->status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
476 state
->useable_id
+=1;
480 static NTSTATUS
smb1srv_session_local_allocate_id(struct db_context
*db
,
484 struct db_record
**_rec
,
487 struct smb1srv_session_local_allocate_state state
= {
488 .lowest_id
= lowest_id
,
489 .highest_id
= highest_id
,
491 .useable_id
= lowest_id
,
492 .status
= NT_STATUS_INTERNAL_ERROR
,
502 if (lowest_id
> highest_id
) {
503 return NT_STATUS_INSUFFICIENT_RESOURCES
;
507 * first we try randomly
509 range
= (highest_id
- lowest_id
) + 1;
511 for (i
= 0; i
< (range
/ 2); i
++) {
514 struct db_record
*rec
= NULL
;
516 id
= generate_random() % range
;
519 if (id
< lowest_id
) {
522 if (id
> highest_id
) {
526 rec
= smbXsrv_session_local_fetch_locked(db
, id
, mem_ctx
);
528 return NT_STATUS_INSUFFICIENT_RESOURCES
;
531 val
= dbwrap_record_get_value(rec
);
532 if (val
.dsize
!= 0) {
543 * if the range is almost full,
544 * we traverse the whole table
545 * (this relies on sorted behavior of dbwrap_rbt)
547 status
= dbwrap_traverse_read(db
, smb1srv_session_local_allocate_traverse
,
549 if (NT_STATUS_IS_OK(status
)) {
550 if (NT_STATUS_IS_OK(state
.status
)) {
551 return NT_STATUS_INTERNAL_ERROR
;
554 if (!NT_STATUS_EQUAL(state
.status
, NT_STATUS_INTERNAL_ERROR
)) {
558 if (state
.useable_id
<= state
.highest_id
) {
559 state
.status
= NT_STATUS_OK
;
561 return NT_STATUS_INSUFFICIENT_RESOURCES
;
563 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_INTERNAL_DB_CORRUPTION
)) {
565 * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
567 * If we get anything else it is an error, because it
568 * means we did not manage to find a free slot in
571 return NT_STATUS_INSUFFICIENT_RESOURCES
;
574 if (NT_STATUS_IS_OK(state
.status
)) {
577 struct db_record
*rec
= NULL
;
579 id
= state
.useable_id
;
581 rec
= smbXsrv_session_local_fetch_locked(db
, id
, mem_ctx
);
583 return NT_STATUS_INSUFFICIENT_RESOURCES
;
586 val
= dbwrap_record_get_value(rec
);
587 if (val
.dsize
!= 0) {
589 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
600 struct smbXsrv_session_local_fetch_state
{
601 struct smbXsrv_session
*session
;
605 static void smbXsrv_session_local_fetch_parser(TDB_DATA key
, TDB_DATA data
,
608 struct smbXsrv_session_local_fetch_state
*state
=
609 (struct smbXsrv_session_local_fetch_state
*)private_data
;
612 if (data
.dsize
!= sizeof(ptr
)) {
613 state
->status
= NT_STATUS_INTERNAL_DB_ERROR
;
617 memcpy(&ptr
, data
.dptr
, data
.dsize
);
618 state
->session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
619 state
->status
= NT_STATUS_OK
;
622 static NTSTATUS
smbXsrv_session_local_lookup(struct smbXsrv_session_table
*table
,
624 struct smbXsrv_connection
*conn
,
625 uint32_t session_local_id
,
627 struct smbXsrv_session
**_session
)
629 struct smbXsrv_session_local_fetch_state state
= {
631 .status
= NT_STATUS_INTERNAL_ERROR
,
633 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
639 if (session_local_id
== 0) {
640 return NT_STATUS_USER_SESSION_DELETED
;
644 /* this might happen before the end of negprot */
645 return NT_STATUS_USER_SESSION_DELETED
;
648 if (table
->local
.db_ctx
== NULL
) {
649 return NT_STATUS_INTERNAL_ERROR
;
652 key
= smbXsrv_session_local_id_to_key(session_local_id
, key_buf
);
654 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
655 smbXsrv_session_local_fetch_parser
,
657 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
658 return NT_STATUS_USER_SESSION_DELETED
;
659 } else if (!NT_STATUS_IS_OK(status
)) {
662 if (!NT_STATUS_IS_OK(state
.status
)) {
666 if (NT_STATUS_EQUAL(state
.session
->status
, NT_STATUS_USER_SESSION_DELETED
)) {
667 return NT_STATUS_USER_SESSION_DELETED
;
671 * If a connection is specified check if the session is
672 * valid on the channel.
675 struct smbXsrv_channel_global0
*c
= NULL
;
677 status
= smbXsrv_session_find_channel(state
.session
, conn
, &c
);
678 if (!NT_STATUS_IS_OK(status
)) {
683 state
.session
->idle_time
= now
;
685 if (!NT_STATUS_IS_OK(state
.session
->status
)) {
686 *_session
= state
.session
;
687 return state
.session
->status
;
690 if (now
> state
.session
->global
->expiration_time
) {
691 state
.session
->status
= NT_STATUS_NETWORK_SESSION_EXPIRED
;
694 *_session
= state
.session
;
695 return state
.session
->status
;
698 static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0
*global
)
703 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
707 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
)
804 struct smbXsrv_session_globalB global_blob
;
805 enum ndr_err_code ndr_err
;
806 struct smbXsrv_session_global0
*global
= NULL
;
808 TALLOC_CTX
*frame
= talloc_stackframe();
819 key
= dbwrap_record_get_key(db_rec
);
821 val
= dbwrap_record_get_value(db_rec
);
822 if (val
.dsize
== 0) {
831 blob
= data_blob_const(val
.dptr
, val
.dsize
);
833 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
834 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
835 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
836 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
837 DEBUG(1,("smbXsrv_session_global_verify_record: "
838 "key '%s' ndr_pull_struct_blob - %s\n",
839 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
849 DEBUG(10,("smbXsrv_session_global_verify_record\n"));
851 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
854 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
855 DEBUG(0,("smbXsrv_session_global_verify_record: "
856 "key '%s' use unsupported version %u\n",
857 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
858 global_blob
.version
));
859 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
868 global
= global_blob
.info
.info0
;
870 exists
= serverid_exists(&global
->channels
[0].server_id
);
872 struct server_id_buf idbuf
;
873 DEBUG(2,("smbXsrv_session_global_verify_record: "
874 "key '%s' server_id %s does not exist.\n",
875 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
876 server_id_str_buf(global
->channels
[0].server_id
,
879 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
882 dbwrap_record_delete(db_rec
);
888 *_g
= talloc_move(mem_ctx
, &global
);
893 static NTSTATUS
smbXsrv_session_global_store(struct smbXsrv_session_global0
*global
)
895 struct smbXsrv_session_globalB global_blob
;
896 DATA_BLOB blob
= data_blob_null
;
900 enum ndr_err_code ndr_err
;
903 * TODO: if we use other versions than '0'
904 * we would add glue code here, that would be able to
905 * store the information in the old format.
908 if (global
->db_rec
== NULL
) {
909 return NT_STATUS_INTERNAL_ERROR
;
912 key
= dbwrap_record_get_key(global
->db_rec
);
913 val
= dbwrap_record_get_value(global
->db_rec
);
915 ZERO_STRUCT(global_blob
);
916 global_blob
.version
= smbXsrv_version_global_current();
917 if (val
.dsize
>= 8) {
918 global_blob
.seqnum
= IVAL(val
.dptr
, 4);
920 global_blob
.seqnum
+= 1;
921 global_blob
.info
.info0
= global
;
923 ndr_err
= ndr_push_struct_blob(&blob
, global
->db_rec
, &global_blob
,
924 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_globalB
);
925 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
926 status
= ndr_map_error2ntstatus(ndr_err
);
927 DEBUG(1,("smbXsrv_session_global_store: key '%s' ndr_push - %s\n",
928 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
930 TALLOC_FREE(global
->db_rec
);
934 val
= make_tdb_data(blob
.data
, blob
.length
);
935 status
= dbwrap_record_store(global
->db_rec
, val
, TDB_REPLACE
);
936 if (!NT_STATUS_IS_OK(status
)) {
937 DEBUG(1,("smbXsrv_session_global_store: key '%s' store - %s\n",
938 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
940 TALLOC_FREE(global
->db_rec
);
945 DEBUG(10,("smbXsrv_session_global_store: key '%s' stored\n",
946 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
)));
947 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
950 TALLOC_FREE(global
->db_rec
);
955 struct smb2srv_session_close_previous_state
{
956 struct tevent_context
*ev
;
957 struct smbXsrv_connection
*connection
;
958 struct dom_sid
*current_sid
;
959 uint64_t previous_session_id
;
960 uint64_t current_session_id
;
961 struct db_record
*db_rec
;
964 static void smb2srv_session_close_previous_check(struct tevent_req
*req
);
965 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
);
967 struct tevent_req
*smb2srv_session_close_previous_send(TALLOC_CTX
*mem_ctx
,
968 struct tevent_context
*ev
,
969 struct smbXsrv_connection
*conn
,
970 struct auth_session_info
*session_info
,
971 uint64_t previous_session_id
,
972 uint64_t current_session_id
)
974 struct tevent_req
*req
;
975 struct smb2srv_session_close_previous_state
*state
;
976 uint32_t global_id
= previous_session_id
& UINT32_MAX
;
977 uint64_t global_zeros
= previous_session_id
& 0xFFFFFFFF00000000LLU
;
978 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
979 struct security_token
*current_token
= NULL
;
981 req
= tevent_req_create(mem_ctx
, &state
,
982 struct smb2srv_session_close_previous_state
);
987 state
->connection
= conn
;
988 state
->previous_session_id
= previous_session_id
;
989 state
->current_session_id
= current_session_id
;
991 if (global_zeros
!= 0) {
992 tevent_req_done(req
);
993 return tevent_req_post(req
, ev
);
996 if (session_info
== NULL
) {
997 tevent_req_done(req
);
998 return tevent_req_post(req
, ev
);
1000 current_token
= session_info
->security_token
;
1002 if (current_token
->num_sids
> PRIMARY_USER_SID_INDEX
) {
1003 state
->current_sid
= ¤t_token
->sids
[PRIMARY_USER_SID_INDEX
];
1006 if (state
->current_sid
== NULL
) {
1007 tevent_req_done(req
);
1008 return tevent_req_post(req
, ev
);
1011 if (!security_token_has_nt_authenticated_users(current_token
)) {
1013 tevent_req_done(req
);
1014 return tevent_req_post(req
, ev
);
1017 state
->db_rec
= smbXsrv_session_global_fetch_locked(
1018 table
->global
.db_ctx
,
1020 state
/* TALLOC_CTX */);
1021 if (state
->db_rec
== NULL
) {
1022 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1023 return tevent_req_post(req
, ev
);
1026 smb2srv_session_close_previous_check(req
);
1027 if (!tevent_req_is_in_progress(req
)) {
1028 return tevent_req_post(req
, ev
);
1034 static void smb2srv_session_close_previous_check(struct tevent_req
*req
)
1036 struct smb2srv_session_close_previous_state
*state
=
1037 tevent_req_data(req
,
1038 struct smb2srv_session_close_previous_state
);
1039 struct smbXsrv_connection
*conn
= state
->connection
;
1041 struct security_token
*previous_token
= NULL
;
1042 struct smbXsrv_session_global0
*global
= NULL
;
1043 enum ndr_err_code ndr_err
;
1044 struct smbXsrv_session_close0 close_info0
;
1045 struct smbXsrv_session_closeB close_blob
;
1046 struct tevent_req
*subreq
= NULL
;
1048 bool is_free
= false;
1050 smbXsrv_session_global_verify_record(state
->db_rec
,
1057 TALLOC_FREE(state
->db_rec
);
1058 tevent_req_done(req
);
1062 if (global
->auth_session_info
== NULL
) {
1063 TALLOC_FREE(state
->db_rec
);
1064 tevent_req_done(req
);
1068 previous_token
= global
->auth_session_info
->security_token
;
1070 if (!security_token_is_sid(previous_token
, state
->current_sid
)) {
1071 TALLOC_FREE(state
->db_rec
);
1072 tevent_req_done(req
);
1076 subreq
= dbwrap_watched_watch_send(state
, state
->ev
, state
->db_rec
,
1077 (struct server_id
){0});
1078 if (tevent_req_nomem(subreq
, req
)) {
1079 TALLOC_FREE(state
->db_rec
);
1082 tevent_req_set_callback(subreq
,
1083 smb2srv_session_close_previous_modified
,
1086 close_info0
.old_session_global_id
= global
->session_global_id
;
1087 close_info0
.old_session_wire_id
= global
->session_wire_id
;
1088 close_info0
.old_creation_time
= global
->creation_time
;
1089 close_info0
.new_session_wire_id
= state
->current_session_id
;
1091 ZERO_STRUCT(close_blob
);
1092 close_blob
.version
= smbXsrv_version_global_current();
1093 close_blob
.info
.info0
= &close_info0
;
1095 ndr_err
= ndr_push_struct_blob(&blob
, state
, &close_blob
,
1096 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_closeB
);
1097 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1098 TALLOC_FREE(state
->db_rec
);
1099 status
= ndr_map_error2ntstatus(ndr_err
);
1100 DEBUG(1,("smb2srv_session_close_previous_check: "
1101 "old_session[%llu] new_session[%llu] ndr_push - %s\n",
1102 (unsigned long long)close_info0
.old_session_wire_id
,
1103 (unsigned long long)close_info0
.new_session_wire_id
,
1104 nt_errstr(status
)));
1105 tevent_req_nterror(req
, status
);
1109 status
= messaging_send(conn
->msg_ctx
,
1110 global
->channels
[0].server_id
,
1111 MSG_SMBXSRV_SESSION_CLOSE
, &blob
);
1112 TALLOC_FREE(state
->db_rec
);
1113 if (tevent_req_nterror(req
, status
)) {
1117 TALLOC_FREE(global
);
1121 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
)
1123 struct tevent_req
*req
=
1124 tevent_req_callback_data(subreq
,
1126 struct smb2srv_session_close_previous_state
*state
=
1127 tevent_req_data(req
,
1128 struct smb2srv_session_close_previous_state
);
1132 status
= dbwrap_watched_watch_recv(subreq
, NULL
, NULL
);
1133 TALLOC_FREE(subreq
);
1134 if (tevent_req_nterror(req
, status
)) {
1138 global_id
= state
->previous_session_id
& UINT32_MAX
;
1140 state
->db_rec
= smbXsrv_session_global_fetch_locked(
1141 state
->connection
->client
->session_table
->global
.db_ctx
,
1142 global_id
, state
/* TALLOC_CTX */);
1144 smb2srv_session_close_previous_check(req
);
1147 NTSTATUS
smb2srv_session_close_previous_recv(struct tevent_req
*req
)
1151 if (tevent_req_is_nterror(req
, &status
)) {
1152 tevent_req_received(req
);
1156 tevent_req_received(req
);
1157 return NT_STATUS_OK
;
1160 static NTSTATUS
smbXsrv_session_clear_and_logoff(struct smbXsrv_session
*session
)
1163 struct smbXsrv_connection
*xconn
= NULL
;
1165 if (session
->client
!= NULL
) {
1166 xconn
= session
->client
->connections
;
1169 for (; xconn
!= NULL
; xconn
= xconn
->next
) {
1170 struct smbd_smb2_request
*preq
;
1172 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1173 if (preq
->session
!= session
) {
1177 preq
->session
= NULL
;
1179 * If we no longer have a session we can't
1180 * sign or encrypt replies.
1182 preq
->do_signing
= false;
1183 preq
->do_encryption
= false;
1184 preq
->preauth
= NULL
;
1188 status
= smbXsrv_session_logoff(session
);
1192 static int smbXsrv_session_destructor(struct smbXsrv_session
*session
)
1196 status
= smbXsrv_session_clear_and_logoff(session
);
1197 if (!NT_STATUS_IS_OK(status
)) {
1198 DEBUG(0, ("smbXsrv_session_destructor: "
1199 "smbXsrv_session_logoff() failed: %s\n",
1200 nt_errstr(status
)));
1203 TALLOC_FREE(session
->global
);
1208 NTSTATUS
smbXsrv_session_create(struct smbXsrv_connection
*conn
,
1210 struct smbXsrv_session
**_session
)
1212 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1213 struct db_record
*local_rec
= NULL
;
1214 struct smbXsrv_session
*session
= NULL
;
1217 struct smbXsrv_session_global0
*global
= NULL
;
1218 struct smbXsrv_channel_global0
*channel
= NULL
;
1221 if (table
->local
.num_sessions
>= table
->local
.max_sessions
) {
1222 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1225 session
= talloc_zero(table
, struct smbXsrv_session
);
1226 if (session
== NULL
) {
1227 return NT_STATUS_NO_MEMORY
;
1229 session
->table
= table
;
1230 session
->idle_time
= now
;
1231 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
1232 session
->client
= conn
->client
;
1234 status
= smbXsrv_session_global_allocate(table
->global
.db_ctx
,
1237 if (!NT_STATUS_IS_OK(status
)) {
1238 TALLOC_FREE(session
);
1241 session
->global
= global
;
1243 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1244 uint64_t id
= global
->session_global_id
;
1246 global
->connection_dialect
= conn
->smb2
.server
.dialect
;
1248 global
->session_wire_id
= id
;
1250 status
= smb2srv_tcon_table_init(session
);
1251 if (!NT_STATUS_IS_OK(status
)) {
1252 TALLOC_FREE(session
);
1256 session
->local_id
= global
->session_global_id
;
1258 local_rec
= smbXsrv_session_local_fetch_locked(
1259 table
->local
.db_ctx
,
1261 session
/* TALLOC_CTX */);
1262 if (local_rec
== NULL
) {
1263 TALLOC_FREE(session
);
1264 return NT_STATUS_NO_MEMORY
;
1267 val
= dbwrap_record_get_value(local_rec
);
1268 if (val
.dsize
!= 0) {
1269 TALLOC_FREE(session
);
1270 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1274 status
= smb1srv_session_local_allocate_id(table
->local
.db_ctx
,
1275 table
->local
.lowest_id
,
1276 table
->local
.highest_id
,
1279 &session
->local_id
);
1280 if (!NT_STATUS_IS_OK(status
)) {
1281 TALLOC_FREE(session
);
1285 global
->session_wire_id
= session
->local_id
;
1288 global
->creation_time
= now
;
1289 global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1291 status
= smbXsrv_session_add_channel(session
, conn
, &channel
);
1292 if (!NT_STATUS_IS_OK(status
)) {
1293 TALLOC_FREE(session
);
1298 val
= make_tdb_data((uint8_t const *)&ptr
, sizeof(ptr
));
1299 status
= dbwrap_record_store(local_rec
, val
, TDB_REPLACE
);
1300 TALLOC_FREE(local_rec
);
1301 if (!NT_STATUS_IS_OK(status
)) {
1302 TALLOC_FREE(session
);
1305 table
->local
.num_sessions
+= 1;
1307 talloc_set_destructor(session
, smbXsrv_session_destructor
);
1309 status
= smbXsrv_session_global_store(global
);
1310 if (!NT_STATUS_IS_OK(status
)) {
1311 DEBUG(0,("smbXsrv_session_create: "
1312 "global_id (0x%08x) store failed - %s\n",
1313 session
->global
->session_global_id
,
1314 nt_errstr(status
)));
1315 TALLOC_FREE(session
);
1320 struct smbXsrv_sessionB session_blob
;
1322 ZERO_STRUCT(session_blob
);
1323 session_blob
.version
= SMBXSRV_VERSION_0
;
1324 session_blob
.info
.info0
= session
;
1326 DEBUG(10,("smbXsrv_session_create: global_id (0x%08x) stored\n",
1327 session
->global
->session_global_id
));
1328 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1331 *_session
= session
;
1332 return NT_STATUS_OK
;
1335 NTSTATUS
smbXsrv_session_add_channel(struct smbXsrv_session
*session
,
1336 struct smbXsrv_connection
*conn
,
1337 struct smbXsrv_channel_global0
**_c
)
1339 struct smbXsrv_session_global0
*global
= session
->global
;
1340 struct smbXsrv_channel_global0
*c
= NULL
;
1342 if (global
->num_channels
> 31) {
1344 * Windows 2012 and 2012R2 allow up to 32 channels
1346 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1349 c
= talloc_realloc(global
,
1351 struct smbXsrv_channel_global0
,
1352 global
->num_channels
+ 1);
1354 return NT_STATUS_NO_MEMORY
;
1356 global
->channels
= c
;
1358 c
= &global
->channels
[global
->num_channels
];
1361 c
->server_id
= messaging_server_id(conn
->msg_ctx
);
1362 c
->local_address
= tsocket_address_string(conn
->local_address
,
1364 if (c
->local_address
== NULL
) {
1365 return NT_STATUS_NO_MEMORY
;
1367 c
->remote_address
= tsocket_address_string(conn
->remote_address
,
1369 if (c
->remote_address
== NULL
) {
1370 return NT_STATUS_NO_MEMORY
;
1372 c
->remote_name
= talloc_strdup(global
->channels
,
1373 conn
->remote_hostname
);
1374 if (c
->remote_name
== NULL
) {
1375 return NT_STATUS_NO_MEMORY
;
1377 c
->connection
= conn
;
1379 global
->num_channels
+= 1;
1382 return NT_STATUS_OK
;
1385 NTSTATUS
smbXsrv_session_update(struct smbXsrv_session
*session
)
1387 struct smbXsrv_session_table
*table
= session
->table
;
1390 if (session
->global
->db_rec
!= NULL
) {
1391 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1392 "Called with db_rec != NULL'\n",
1393 session
->global
->session_global_id
));
1394 return NT_STATUS_INTERNAL_ERROR
;
1397 session
->global
->db_rec
= smbXsrv_session_global_fetch_locked(
1398 table
->global
.db_ctx
,
1399 session
->global
->session_global_id
,
1400 session
->global
/* TALLOC_CTX */);
1401 if (session
->global
->db_rec
== NULL
) {
1402 return NT_STATUS_INTERNAL_DB_ERROR
;
1405 status
= smbXsrv_session_global_store(session
->global
);
1406 if (!NT_STATUS_IS_OK(status
)) {
1407 DEBUG(0,("smbXsrv_session_update: "
1408 "global_id (0x%08x) store failed - %s\n",
1409 session
->global
->session_global_id
,
1410 nt_errstr(status
)));
1415 struct smbXsrv_sessionB session_blob
;
1417 ZERO_STRUCT(session_blob
);
1418 session_blob
.version
= SMBXSRV_VERSION_0
;
1419 session_blob
.info
.info0
= session
;
1421 DEBUG(10,("smbXsrv_session_update: global_id (0x%08x) stored\n",
1422 session
->global
->session_global_id
));
1423 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1426 return NT_STATUS_OK
;
1429 NTSTATUS
smbXsrv_session_find_channel(const struct smbXsrv_session
*session
,
1430 const struct smbXsrv_connection
*conn
,
1431 struct smbXsrv_channel_global0
**_c
)
1435 for (i
=0; i
< session
->global
->num_channels
; i
++) {
1436 struct smbXsrv_channel_global0
*c
= &session
->global
->channels
[i
];
1438 if (c
->connection
== conn
) {
1440 return NT_STATUS_OK
;
1444 return NT_STATUS_USER_SESSION_DELETED
;
1447 NTSTATUS
smbXsrv_session_find_auth(const struct smbXsrv_session
*session
,
1448 const struct smbXsrv_connection
*conn
,
1450 struct smbXsrv_session_auth0
**_a
)
1452 struct smbXsrv_session_auth0
*a
;
1454 for (a
= session
->pending_auth
; a
!= NULL
; a
= a
->next
) {
1455 if (a
->connection
== conn
) {
1460 return NT_STATUS_OK
;
1464 return NT_STATUS_USER_SESSION_DELETED
;
1467 static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0
*a
)
1469 if (a
->session
== NULL
) {
1473 DLIST_REMOVE(a
->session
->pending_auth
, a
);
1478 NTSTATUS
smbXsrv_session_create_auth(struct smbXsrv_session
*session
,
1479 struct smbXsrv_connection
*conn
,
1482 uint8_t in_security_mode
,
1483 struct smbXsrv_session_auth0
**_a
)
1485 struct smbXsrv_session_auth0
*a
;
1488 status
= smbXsrv_session_find_auth(session
, conn
, 0, &a
);
1489 if (NT_STATUS_IS_OK(status
)) {
1490 return NT_STATUS_INTERNAL_ERROR
;
1493 a
= talloc_zero(session
, struct smbXsrv_session_auth0
);
1495 return NT_STATUS_NO_MEMORY
;
1497 a
->session
= session
;
1498 a
->connection
= conn
;
1499 a
->in_flags
= in_flags
;
1500 a
->in_security_mode
= in_security_mode
;
1501 a
->creation_time
= now
;
1504 if (conn
->protocol
>= PROTOCOL_SMB3_10
) {
1505 a
->preauth
= talloc(a
, struct smbXsrv_preauth
);
1506 if (a
->preauth
== NULL
) {
1507 TALLOC_FREE(session
);
1508 return NT_STATUS_NO_MEMORY
;
1510 *a
->preauth
= conn
->smb2
.preauth
;
1513 talloc_set_destructor(a
, smbXsrv_session_auth0_destructor
);
1514 DLIST_ADD_END(session
->pending_auth
, a
);
1517 return NT_STATUS_OK
;
1520 struct smb2srv_session_shutdown_state
{
1521 struct tevent_queue
*wait_queue
;
1524 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
);
1526 struct tevent_req
*smb2srv_session_shutdown_send(TALLOC_CTX
*mem_ctx
,
1527 struct tevent_context
*ev
,
1528 struct smbXsrv_session
*session
,
1529 struct smbd_smb2_request
*current_req
)
1531 struct tevent_req
*req
;
1532 struct smb2srv_session_shutdown_state
*state
;
1533 struct tevent_req
*subreq
;
1534 struct smbXsrv_connection
*xconn
= NULL
;
1538 * Make sure that no new request will be able to use this session.
1540 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1542 req
= tevent_req_create(mem_ctx
, &state
,
1543 struct smb2srv_session_shutdown_state
);
1548 state
->wait_queue
= tevent_queue_create(state
, "smb2srv_session_shutdown_queue");
1549 if (tevent_req_nomem(state
->wait_queue
, req
)) {
1550 return tevent_req_post(req
, ev
);
1553 for (xconn
= session
->client
->connections
; xconn
!= NULL
; xconn
= xconn
->next
) {
1554 struct smbd_smb2_request
*preq
;
1556 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1557 if (preq
== current_req
) {
1558 /* Can't cancel current request. */
1561 if (preq
->session
!= session
) {
1562 /* Request on different session. */
1566 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
1567 preq
->session
= NULL
;
1569 * If we no longer have a session we can't
1570 * sign or encrypt replies.
1572 preq
->do_signing
= false;
1573 preq
->do_encryption
= false;
1574 preq
->preauth
= NULL
;
1576 if (preq
->subreq
!= NULL
) {
1577 tevent_req_cancel(preq
->subreq
);
1583 * Never cancel anything in a compound
1584 * request. Way too hard to deal with
1587 if (!preq
->compound_related
&& preq
->subreq
!= NULL
) {
1588 tevent_req_cancel(preq
->subreq
);
1592 * Now wait until the request is finished.
1594 * We don't set a callback, as we just want to block the
1595 * wait queue and the talloc_free() of the request will
1596 * remove the item from the wait queue.
1598 subreq
= tevent_queue_wait_send(preq
, ev
, state
->wait_queue
);
1599 if (tevent_req_nomem(subreq
, req
)) {
1600 return tevent_req_post(req
, ev
);
1605 len
= tevent_queue_length(state
->wait_queue
);
1607 tevent_req_done(req
);
1608 return tevent_req_post(req
, ev
);
1612 * Now we add our own waiter to the end of the queue,
1613 * this way we get notified when all pending requests are finished
1614 * and send to the socket.
1616 subreq
= tevent_queue_wait_send(state
, ev
, state
->wait_queue
);
1617 if (tevent_req_nomem(subreq
, req
)) {
1618 return tevent_req_post(req
, ev
);
1620 tevent_req_set_callback(subreq
, smb2srv_session_shutdown_wait_done
, req
);
1625 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
)
1627 struct tevent_req
*req
=
1628 tevent_req_callback_data(subreq
,
1631 tevent_queue_wait_recv(subreq
);
1632 TALLOC_FREE(subreq
);
1634 tevent_req_done(req
);
1637 NTSTATUS
smb2srv_session_shutdown_recv(struct tevent_req
*req
)
1639 return tevent_req_simple_recv_ntstatus(req
);
1642 NTSTATUS
smbXsrv_session_logoff(struct smbXsrv_session
*session
)
1644 struct smbXsrv_session_table
*table
;
1645 struct db_record
*local_rec
= NULL
;
1646 struct db_record
*global_rec
= NULL
;
1647 struct smbd_server_connection
*sconn
= NULL
;
1649 NTSTATUS error
= NT_STATUS_OK
;
1651 if (session
->table
== NULL
) {
1652 return NT_STATUS_OK
;
1655 table
= session
->table
;
1656 session
->table
= NULL
;
1658 sconn
= session
->client
->sconn
;
1659 session
->client
= NULL
;
1660 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1662 global_rec
= session
->global
->db_rec
;
1663 session
->global
->db_rec
= NULL
;
1664 if (global_rec
== NULL
) {
1665 global_rec
= smbXsrv_session_global_fetch_locked(
1666 table
->global
.db_ctx
,
1667 session
->global
->session_global_id
,
1668 session
->global
/* TALLOC_CTX */);
1669 if (global_rec
== NULL
) {
1670 error
= NT_STATUS_INTERNAL_ERROR
;
1674 if (global_rec
!= NULL
) {
1675 status
= dbwrap_record_delete(global_rec
);
1676 if (!NT_STATUS_IS_OK(status
)) {
1677 TDB_DATA key
= dbwrap_record_get_key(global_rec
);
1679 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1680 "failed to delete global key '%s': %s\n",
1681 session
->global
->session_global_id
,
1682 hex_encode_talloc(global_rec
, key
.dptr
,
1684 nt_errstr(status
)));
1688 TALLOC_FREE(global_rec
);
1690 local_rec
= session
->db_rec
;
1691 if (local_rec
== NULL
) {
1692 local_rec
= smbXsrv_session_local_fetch_locked(
1693 table
->local
.db_ctx
,
1695 session
/* TALLOC_CTX */);
1696 if (local_rec
== NULL
) {
1697 error
= NT_STATUS_INTERNAL_ERROR
;
1701 if (local_rec
!= NULL
) {
1702 status
= dbwrap_record_delete(local_rec
);
1703 if (!NT_STATUS_IS_OK(status
)) {
1704 TDB_DATA key
= dbwrap_record_get_key(local_rec
);
1706 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1707 "failed to delete local key '%s': %s\n",
1708 session
->global
->session_global_id
,
1709 hex_encode_talloc(local_rec
, key
.dptr
,
1711 nt_errstr(status
)));
1714 table
->local
.num_sessions
-= 1;
1716 if (session
->db_rec
== NULL
) {
1717 TALLOC_FREE(local_rec
);
1719 session
->db_rec
= NULL
;
1721 if (session
->compat
) {
1722 file_close_user(sconn
, session
->compat
->vuid
);
1725 if (session
->tcon_table
!= NULL
) {
1727 * Note: We only have a tcon_table for SMB2.
1729 status
= smb2srv_tcon_disconnect_all(session
);
1730 if (!NT_STATUS_IS_OK(status
)) {
1731 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1732 "smb2srv_tcon_disconnect_all() failed: %s\n",
1733 session
->global
->session_global_id
,
1734 nt_errstr(status
)));
1739 if (session
->compat
) {
1740 invalidate_vuid(sconn
, session
->compat
->vuid
);
1741 session
->compat
= NULL
;
1747 struct smbXsrv_session_logoff_all_state
{
1748 NTSTATUS first_status
;
1752 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1753 void *private_data
);
1755 NTSTATUS
smbXsrv_session_logoff_all(struct smbXsrv_connection
*conn
)
1757 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1758 struct smbXsrv_session_logoff_all_state state
;
1762 if (table
== NULL
) {
1763 DEBUG(10, ("smbXsrv_session_logoff_all: "
1764 "empty session_table, nothing to do.\n"));
1765 return NT_STATUS_OK
;
1770 status
= dbwrap_traverse(table
->local
.db_ctx
,
1771 smbXsrv_session_logoff_all_callback
,
1773 if (!NT_STATUS_IS_OK(status
)) {
1774 DEBUG(0, ("smbXsrv_session_logoff_all: "
1775 "dbwrap_traverse() failed: %s\n",
1776 nt_errstr(status
)));
1780 if (!NT_STATUS_IS_OK(state
.first_status
)) {
1781 DEBUG(0, ("smbXsrv_session_logoff_all: "
1782 "count[%d] errors[%d] first[%s]\n",
1783 count
, state
.errors
,
1784 nt_errstr(state
.first_status
)));
1785 return state
.first_status
;
1788 return NT_STATUS_OK
;
1791 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1794 struct smbXsrv_session_logoff_all_state
*state
=
1795 (struct smbXsrv_session_logoff_all_state
*)private_data
;
1798 struct smbXsrv_session
*session
= NULL
;
1801 val
= dbwrap_record_get_value(local_rec
);
1802 if (val
.dsize
!= sizeof(ptr
)) {
1803 status
= NT_STATUS_INTERNAL_ERROR
;
1804 if (NT_STATUS_IS_OK(state
->first_status
)) {
1805 state
->first_status
= status
;
1811 memcpy(&ptr
, val
.dptr
, val
.dsize
);
1812 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
1814 session
->db_rec
= local_rec
;
1816 status
= smbXsrv_session_clear_and_logoff(session
);
1817 if (!NT_STATUS_IS_OK(status
)) {
1818 if (NT_STATUS_IS_OK(state
->first_status
)) {
1819 state
->first_status
= status
;
1828 NTSTATUS
smb1srv_session_table_init(struct smbXsrv_connection
*conn
)
1831 * Allow a range from 1..65534 with 65534 values.
1833 return smbXsrv_session_table_init(conn
, 1, UINT16_MAX
- 1,
1837 NTSTATUS
smb1srv_session_lookup(struct smbXsrv_connection
*conn
,
1838 uint16_t vuid
, NTTIME now
,
1839 struct smbXsrv_session
**session
)
1841 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1842 uint32_t local_id
= vuid
;
1844 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
1848 NTSTATUS
smb2srv_session_table_init(struct smbXsrv_connection
*conn
)
1851 * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
1853 return smbXsrv_session_table_init(conn
, 1, UINT32_MAX
- 1,
1857 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
1858 /* conn: optional */
1859 struct smbXsrv_connection
*conn
,
1860 uint64_t session_id
, NTTIME now
,
1861 struct smbXsrv_session
**session
)
1863 uint32_t local_id
= session_id
& UINT32_MAX
;
1864 uint64_t local_zeros
= session_id
& 0xFFFFFFFF00000000LLU
;
1866 if (local_zeros
!= 0) {
1867 return NT_STATUS_USER_SESSION_DELETED
;
1870 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
1874 NTSTATUS
smb2srv_session_lookup_conn(struct smbXsrv_connection
*conn
,
1875 uint64_t session_id
, NTTIME now
,
1876 struct smbXsrv_session
**session
)
1878 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1879 return smb2srv_session_lookup_raw(table
, conn
, session_id
, now
,
1883 NTSTATUS
smb2srv_session_lookup_client(struct smbXsrv_client
*client
,
1884 uint64_t session_id
, NTTIME now
,
1885 struct smbXsrv_session
**session
)
1887 struct smbXsrv_session_table
*table
= client
->session_table
;
1888 return smb2srv_session_lookup_raw(table
, NULL
, session_id
, now
,
1892 struct smbXsrv_session_global_traverse_state
{
1893 int (*fn
)(struct smbXsrv_session_global0
*, void *);
1897 static int smbXsrv_session_global_traverse_fn(struct db_record
*rec
, void *data
)
1900 struct smbXsrv_session_global_traverse_state
*state
=
1901 (struct smbXsrv_session_global_traverse_state
*)data
;
1902 TDB_DATA key
= dbwrap_record_get_key(rec
);
1903 TDB_DATA val
= dbwrap_record_get_value(rec
);
1904 DATA_BLOB blob
= data_blob_const(val
.dptr
, val
.dsize
);
1905 struct smbXsrv_session_globalB global_blob
;
1906 enum ndr_err_code ndr_err
;
1907 TALLOC_CTX
*frame
= talloc_stackframe();
1909 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
1910 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
1911 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1912 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1913 "key '%s' ndr_pull_struct_blob - %s\n",
1914 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1915 ndr_errstr(ndr_err
)));
1919 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
1920 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1921 "key '%s' unsupported version - %d\n",
1922 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1923 (int)global_blob
.version
));
1927 global_blob
.info
.info0
->db_rec
= rec
;
1928 ret
= state
->fn(global_blob
.info
.info0
, state
->private_data
);
1934 NTSTATUS
smbXsrv_session_global_traverse(
1935 int (*fn
)(struct smbXsrv_session_global0
*, void *),
1941 struct smbXsrv_session_global_traverse_state state
= {
1943 .private_data
= private_data
,
1947 status
= smbXsrv_session_global_init(NULL
);
1948 if (!NT_STATUS_IS_OK(status
)) {
1950 DEBUG(0, ("Failed to initialize session_global: %s\n",
1951 nt_errstr(status
)));
1955 status
= dbwrap_traverse_read(smbXsrv_session_global_db_ctx
,
1956 smbXsrv_session_global_traverse_fn
,