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(void)
58 char *global_path
= NULL
;
59 struct db_context
*db_ctx
= NULL
;
61 if (smbXsrv_session_global_db_ctx
!= NULL
) {
66 * This contains secret information like session keys!
68 global_path
= lock_path("smbXsrv_session_global.tdb");
69 if (global_path
== NULL
) {
70 return NT_STATUS_NO_MEMORY
;
73 db_ctx
= db_open(NULL
, global_path
,
77 TDB_INCOMPATIBLE_HASH
,
78 O_RDWR
| O_CREAT
, 0600,
81 TALLOC_FREE(global_path
);
85 status
= map_nt_error_from_unix_common(errno
);
90 smbXsrv_session_global_db_ctx
= db_ctx
;
97 * We need to store the keys in big endian so that dbwrap_rbt's memcmp
98 * has the same result as integer comparison between the uint32_t
101 * TODO: implement string based key
104 #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
106 static TDB_DATA
smbXsrv_session_global_id_to_key(uint32_t id
,
111 RSIVAL(key_buf
, 0, id
);
113 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
);
119 static NTSTATUS
smbXsrv_session_global_key_to_id(TDB_DATA key
, uint32_t *id
)
122 return NT_STATUS_INVALID_PARAMETER
;
125 if (key
.dsize
!= SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
) {
126 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
129 *id
= RIVAL(key
.dptr
, 0);
135 #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
137 static TDB_DATA
smbXsrv_session_local_id_to_key(uint32_t id
,
142 RSIVAL(key_buf
, 0, id
);
144 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
);
149 static NTSTATUS
smbXsrv_session_local_key_to_id(TDB_DATA key
, uint32_t *id
)
152 return NT_STATUS_INVALID_PARAMETER
;
155 if (key
.dsize
!= SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
) {
156 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
159 *id
= RIVAL(key
.dptr
, 0);
164 static struct db_record
*smbXsrv_session_global_fetch_locked(
165 struct db_context
*db
,
170 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
171 struct db_record
*rec
= NULL
;
173 key
= smbXsrv_session_global_id_to_key(id
, key_buf
);
175 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
178 DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id
,
179 hex_encode_talloc(talloc_tos(), key
.dptr
, key
.dsize
));
185 static struct db_record
*smbXsrv_session_local_fetch_locked(
186 struct db_context
*db
,
191 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
192 struct db_record
*rec
= NULL
;
194 key
= smbXsrv_session_local_id_to_key(id
, key_buf
);
196 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
199 DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id
,
200 hex_encode_talloc(talloc_tos(), key
.dptr
, key
.dsize
));
206 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
);
208 static NTSTATUS
smbXsrv_session_table_init(struct smbXsrv_connection
*conn
,
211 uint32_t max_sessions
)
213 struct smbXsrv_client
*client
= conn
->client
;
214 struct smbXsrv_session_table
*table
;
216 struct tevent_req
*subreq
;
219 if (lowest_id
> highest_id
) {
220 return NT_STATUS_INTERNAL_ERROR
;
223 max_range
= highest_id
;
224 max_range
-= lowest_id
;
227 if (max_sessions
> max_range
) {
228 return NT_STATUS_INTERNAL_ERROR
;
231 table
= talloc_zero(client
, struct smbXsrv_session_table
);
233 return NT_STATUS_NO_MEMORY
;
236 table
->local
.db_ctx
= db_open_rbt(table
);
237 if (table
->local
.db_ctx
== NULL
) {
239 return NT_STATUS_NO_MEMORY
;
241 table
->local
.lowest_id
= lowest_id
;
242 table
->local
.highest_id
= highest_id
;
243 table
->local
.max_sessions
= max_sessions
;
245 status
= smbXsrv_session_global_init();
246 if (!NT_STATUS_IS_OK(status
)) {
251 table
->global
.db_ctx
= smbXsrv_session_global_db_ctx
;
253 dbwrap_watch_db(table
->global
.db_ctx
, client
->msg_ctx
);
255 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
256 MSG_SMBXSRV_SESSION_CLOSE
);
257 if (subreq
== NULL
) {
259 return NT_STATUS_NO_MEMORY
;
261 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
263 client
->session_table
= table
;
267 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
);
269 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
)
271 struct smbXsrv_client
*client
=
272 tevent_req_callback_data(subreq
,
273 struct smbXsrv_client
);
274 struct smbXsrv_session_table
*table
= client
->session_table
;
276 struct messaging_rec
*rec
= NULL
;
277 struct smbXsrv_session_closeB close_blob
;
278 enum ndr_err_code ndr_err
;
279 struct smbXsrv_session_close0
*close_info0
= NULL
;
280 struct smbXsrv_session
*session
= NULL
;
282 struct timeval tv
= timeval_current();
283 NTTIME now
= timeval_to_nttime(&tv
);
285 ret
= messaging_read_recv(subreq
, talloc_tos(), &rec
);
291 ndr_err
= ndr_pull_struct_blob(&rec
->buf
, rec
, &close_blob
,
292 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_closeB
);
293 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
294 status
= ndr_map_error2ntstatus(ndr_err
);
295 DEBUG(1,("smbXsrv_session_close_loop: "
296 "ndr_pull_struct_blob - %s\n",
301 DEBUG(10,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
303 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
306 if (close_blob
.version
!= SMBXSRV_VERSION_0
) {
307 DEBUG(0,("smbXsrv_session_close_loop: "
308 "ignore invalid version %u\n", close_blob
.version
));
309 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
313 close_info0
= close_blob
.info
.info0
;
314 if (close_info0
== NULL
) {
315 DEBUG(0,("smbXsrv_session_close_loop: "
316 "ignore NULL info %u\n", close_blob
.version
));
317 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
321 status
= smb2srv_session_lookup_client(client
,
322 close_info0
->old_session_wire_id
,
324 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_SESSION_DELETED
)) {
325 DEBUG(4,("smbXsrv_session_close_loop: "
326 "old_session_wire_id %llu not found\n",
327 (unsigned long long)close_info0
->old_session_wire_id
));
329 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
333 if (!NT_STATUS_IS_OK(status
) &&
334 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
335 !NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
336 DEBUG(1,("smbXsrv_session_close_loop: "
337 "old_session_wire_id %llu - %s\n",
338 (unsigned long long)close_info0
->old_session_wire_id
,
341 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
346 if (session
->global
->session_global_id
!= close_info0
->old_session_global_id
) {
347 DEBUG(1,("smbXsrv_session_close_loop: "
348 "old_session_wire_id %llu - global %u != %u\n",
349 (unsigned long long)close_info0
->old_session_wire_id
,
350 session
->global
->session_global_id
,
351 close_info0
->old_session_global_id
));
353 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
358 if (session
->global
->creation_time
!= close_info0
->old_creation_time
) {
359 DEBUG(1,("smbXsrv_session_close_loop: "
360 "old_session_wire_id %llu - "
361 "creation %s (%llu) != %s (%llu)\n",
362 (unsigned long long)close_info0
->old_session_wire_id
,
363 nt_time_string(rec
, session
->global
->creation_time
),
364 (unsigned long long)session
->global
->creation_time
,
365 nt_time_string(rec
, close_info0
->old_creation_time
),
366 (unsigned long long)close_info0
->old_creation_time
));
368 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
373 subreq
= smb2srv_session_shutdown_send(session
, client
->ev_ctx
,
375 if (subreq
== NULL
) {
376 status
= NT_STATUS_NO_MEMORY
;
377 DEBUG(0, ("smbXsrv_session_close_loop: "
378 "smb2srv_session_shutdown_send(%llu) failed: %s\n",
379 (unsigned long long)session
->global
->session_wire_id
,
382 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
386 tevent_req_set_callback(subreq
,
387 smbXsrv_session_close_shutdown_done
,
393 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
394 MSG_SMBXSRV_SESSION_CLOSE
);
395 if (subreq
== NULL
) {
397 r
= "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
398 exit_server_cleanly(r
);
401 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
404 static void smbXsrv_session_close_shutdown_done(struct tevent_req
*subreq
)
406 struct smbXsrv_session
*session
=
407 tevent_req_callback_data(subreq
,
408 struct smbXsrv_session
);
411 status
= smb2srv_session_shutdown_recv(subreq
);
413 if (!NT_STATUS_IS_OK(status
)) {
414 DEBUG(0, ("smbXsrv_session_close_loop: "
415 "smb2srv_session_shutdown_recv(%llu) failed: %s\n",
416 (unsigned long long)session
->global
->session_wire_id
,
420 status
= smbXsrv_session_logoff(session
);
421 if (!NT_STATUS_IS_OK(status
)) {
422 DEBUG(0, ("smbXsrv_session_close_loop: "
423 "smbXsrv_session_logoff(%llu) failed: %s\n",
424 (unsigned long long)session
->global
->session_wire_id
,
428 TALLOC_FREE(session
);
431 struct smb1srv_session_local_allocate_state
{
432 const uint32_t lowest_id
;
433 const uint32_t highest_id
;
439 static int smb1srv_session_local_allocate_traverse(struct db_record
*rec
,
442 struct smb1srv_session_local_allocate_state
*state
=
443 (struct smb1srv_session_local_allocate_state
*)private_data
;
444 TDB_DATA key
= dbwrap_record_get_key(rec
);
448 status
= smbXsrv_session_local_key_to_id(key
, &id
);
449 if (!NT_STATUS_IS_OK(status
)) {
450 state
->status
= status
;
454 if (id
<= state
->last_id
) {
455 state
->status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
460 if (id
> state
->useable_id
) {
461 state
->status
= NT_STATUS_OK
;
465 if (state
->useable_id
== state
->highest_id
) {
466 state
->status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
470 state
->useable_id
+=1;
474 static NTSTATUS
smb1srv_session_local_allocate_id(struct db_context
*db
,
478 struct db_record
**_rec
,
481 struct smb1srv_session_local_allocate_state state
= {
482 .lowest_id
= lowest_id
,
483 .highest_id
= highest_id
,
485 .useable_id
= lowest_id
,
486 .status
= NT_STATUS_INTERNAL_ERROR
,
496 if (lowest_id
> highest_id
) {
497 return NT_STATUS_INSUFFICIENT_RESOURCES
;
501 * first we try randomly
503 range
= (highest_id
- lowest_id
) + 1;
505 for (i
= 0; i
< (range
/ 2); i
++) {
508 struct db_record
*rec
= NULL
;
510 id
= generate_random() % range
;
513 if (id
< lowest_id
) {
516 if (id
> highest_id
) {
520 rec
= smbXsrv_session_local_fetch_locked(db
, id
, mem_ctx
);
522 return NT_STATUS_INSUFFICIENT_RESOURCES
;
525 val
= dbwrap_record_get_value(rec
);
526 if (val
.dsize
!= 0) {
537 * if the range is almost full,
538 * we traverse the whole table
539 * (this relies on sorted behavior of dbwrap_rbt)
541 status
= dbwrap_traverse_read(db
, smb1srv_session_local_allocate_traverse
,
543 if (NT_STATUS_IS_OK(status
)) {
544 if (NT_STATUS_IS_OK(state
.status
)) {
545 return NT_STATUS_INTERNAL_ERROR
;
548 if (!NT_STATUS_EQUAL(state
.status
, NT_STATUS_INTERNAL_ERROR
)) {
552 if (state
.useable_id
<= state
.highest_id
) {
553 state
.status
= NT_STATUS_OK
;
555 return NT_STATUS_INSUFFICIENT_RESOURCES
;
557 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_INTERNAL_DB_CORRUPTION
)) {
559 * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
561 * If we get anything else it is an error, because it
562 * means we did not manage to find a free slot in
565 return NT_STATUS_INSUFFICIENT_RESOURCES
;
568 if (NT_STATUS_IS_OK(state
.status
)) {
571 struct db_record
*rec
= NULL
;
573 id
= state
.useable_id
;
575 rec
= smbXsrv_session_local_fetch_locked(db
, id
, mem_ctx
);
577 return NT_STATUS_INSUFFICIENT_RESOURCES
;
580 val
= dbwrap_record_get_value(rec
);
581 if (val
.dsize
!= 0) {
583 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
594 struct smbXsrv_session_local_fetch_state
{
595 struct smbXsrv_session
*session
;
599 static void smbXsrv_session_local_fetch_parser(TDB_DATA key
, TDB_DATA data
,
602 struct smbXsrv_session_local_fetch_state
*state
=
603 (struct smbXsrv_session_local_fetch_state
*)private_data
;
606 if (data
.dsize
!= sizeof(ptr
)) {
607 state
->status
= NT_STATUS_INTERNAL_DB_ERROR
;
611 memcpy(&ptr
, data
.dptr
, data
.dsize
);
612 state
->session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
613 state
->status
= NT_STATUS_OK
;
616 static NTSTATUS
smbXsrv_session_local_lookup(struct smbXsrv_session_table
*table
,
618 struct smbXsrv_connection
*conn
,
619 uint32_t session_local_id
,
621 struct smbXsrv_session
**_session
)
623 struct smbXsrv_session_local_fetch_state state
= {
625 .status
= NT_STATUS_INTERNAL_ERROR
,
627 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
633 if (session_local_id
== 0) {
634 return NT_STATUS_USER_SESSION_DELETED
;
638 /* this might happen before the end of negprot */
639 return NT_STATUS_USER_SESSION_DELETED
;
642 if (table
->local
.db_ctx
== NULL
) {
643 return NT_STATUS_INTERNAL_ERROR
;
646 key
= smbXsrv_session_local_id_to_key(session_local_id
, key_buf
);
648 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
649 smbXsrv_session_local_fetch_parser
,
651 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
652 return NT_STATUS_USER_SESSION_DELETED
;
653 } else if (!NT_STATUS_IS_OK(status
)) {
656 if (!NT_STATUS_IS_OK(state
.status
)) {
660 if (NT_STATUS_EQUAL(state
.session
->status
, NT_STATUS_USER_SESSION_DELETED
)) {
661 return NT_STATUS_USER_SESSION_DELETED
;
665 * If a connection is specified check if the session is
666 * valid on the channel.
669 struct smbXsrv_channel_global0
*c
= NULL
;
671 status
= smbXsrv_session_find_channel(state
.session
, conn
, &c
);
672 if (!NT_STATUS_IS_OK(status
)) {
677 state
.session
->idle_time
= now
;
679 if (!NT_STATUS_IS_OK(state
.session
->status
)) {
680 *_session
= state
.session
;
681 return state
.session
->status
;
684 if (now
> state
.session
->global
->expiration_time
) {
685 state
.session
->status
= NT_STATUS_NETWORK_SESSION_EXPIRED
;
688 *_session
= state
.session
;
689 return state
.session
->status
;
692 static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0
*global
)
697 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
701 struct smbXsrv_session_global0
**_g
);
703 static NTSTATUS
smbXsrv_session_global_allocate(struct db_context
*db
,
705 struct smbXsrv_session_global0
**_global
)
708 struct smbXsrv_session_global0
*global
= NULL
;
709 uint32_t last_free
= 0;
710 const uint32_t min_tries
= 3;
714 global
= talloc_zero(mem_ctx
, struct smbXsrv_session_global0
);
715 if (global
== NULL
) {
716 return NT_STATUS_NO_MEMORY
;
718 talloc_set_destructor(global
, smbXsrv_session_global_destructor
);
721 * Here we just randomly try the whole 32-bit space
723 * We use just 32-bit, because we want to reuse the
726 for (i
= 0; i
< UINT32_MAX
; i
++) {
727 bool is_free
= false;
728 bool was_free
= false;
731 if (i
>= min_tries
&& last_free
!= 0) {
734 id
= generate_random();
739 if (id
== UINT32_MAX
) {
743 global
->db_rec
= smbXsrv_session_global_fetch_locked(db
, id
,
745 if (global
->db_rec
== NULL
) {
747 return NT_STATUS_INSUFFICIENT_RESOURCES
;
750 smbXsrv_session_global_verify_record(global
->db_rec
,
756 TALLOC_FREE(global
->db_rec
);
760 if (!was_free
&& i
< min_tries
) {
762 * The session_id is free now,
763 * but was not free before.
765 * This happens if a smbd crashed
766 * and did not cleanup the record.
768 * If this is one of our first tries,
769 * then we try to find a real free one.
771 if (last_free
== 0) {
774 TALLOC_FREE(global
->db_rec
);
778 global
->session_global_id
= id
;
784 /* should not be reached */
786 return NT_STATUS_INTERNAL_ERROR
;
789 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
793 struct smbXsrv_session_global0
**_g
)
798 struct smbXsrv_session_globalB global_blob
;
799 enum ndr_err_code ndr_err
;
800 struct smbXsrv_session_global0
*global
= NULL
;
802 TALLOC_CTX
*frame
= talloc_stackframe();
813 key
= dbwrap_record_get_key(db_rec
);
815 val
= dbwrap_record_get_value(db_rec
);
816 if (val
.dsize
== 0) {
825 blob
= data_blob_const(val
.dptr
, val
.dsize
);
827 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
828 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
829 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
830 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
831 DEBUG(1,("smbXsrv_session_global_verify_record: "
832 "key '%s' ndr_pull_struct_blob - %s\n",
833 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
843 DEBUG(10,("smbXsrv_session_global_verify_record\n"));
845 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
848 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
849 DEBUG(0,("smbXsrv_session_global_verify_record: "
850 "key '%s' use unsupported version %u\n",
851 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
852 global_blob
.version
));
853 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
862 global
= global_blob
.info
.info0
;
864 exists
= serverid_exists(&global
->channels
[0].server_id
);
866 struct server_id_buf idbuf
;
867 DEBUG(2,("smbXsrv_session_global_verify_record: "
868 "key '%s' server_id %s does not exist.\n",
869 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
870 server_id_str_buf(global
->channels
[0].server_id
,
873 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
876 dbwrap_record_delete(db_rec
);
882 *_g
= talloc_move(mem_ctx
, &global
);
887 static NTSTATUS
smbXsrv_session_global_store(struct smbXsrv_session_global0
*global
)
889 struct smbXsrv_session_globalB global_blob
;
890 DATA_BLOB blob
= data_blob_null
;
894 enum ndr_err_code ndr_err
;
897 * TODO: if we use other versions than '0'
898 * we would add glue code here, that would be able to
899 * store the information in the old format.
902 if (global
->db_rec
== NULL
) {
903 return NT_STATUS_INTERNAL_ERROR
;
906 key
= dbwrap_record_get_key(global
->db_rec
);
907 val
= dbwrap_record_get_value(global
->db_rec
);
909 ZERO_STRUCT(global_blob
);
910 global_blob
.version
= smbXsrv_version_global_current();
911 if (val
.dsize
>= 8) {
912 global_blob
.seqnum
= IVAL(val
.dptr
, 4);
914 global_blob
.seqnum
+= 1;
915 global_blob
.info
.info0
= global
;
917 ndr_err
= ndr_push_struct_blob(&blob
, global
->db_rec
, &global_blob
,
918 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_globalB
);
919 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
920 status
= ndr_map_error2ntstatus(ndr_err
);
921 DEBUG(1,("smbXsrv_session_global_store: key '%s' ndr_push - %s\n",
922 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
924 TALLOC_FREE(global
->db_rec
);
928 val
= make_tdb_data(blob
.data
, blob
.length
);
929 status
= dbwrap_record_store(global
->db_rec
, val
, TDB_REPLACE
);
930 if (!NT_STATUS_IS_OK(status
)) {
931 DEBUG(1,("smbXsrv_session_global_store: key '%s' store - %s\n",
932 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
934 TALLOC_FREE(global
->db_rec
);
939 DEBUG(10,("smbXsrv_session_global_store: key '%s' stored\n",
940 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
)));
941 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
944 TALLOC_FREE(global
->db_rec
);
949 struct smb2srv_session_close_previous_state
{
950 struct tevent_context
*ev
;
951 struct smbXsrv_connection
*connection
;
952 struct dom_sid
*current_sid
;
953 uint64_t current_session_id
;
954 struct db_record
*db_rec
;
957 static void smb2srv_session_close_previous_check(struct tevent_req
*req
);
958 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
);
960 struct tevent_req
*smb2srv_session_close_previous_send(TALLOC_CTX
*mem_ctx
,
961 struct tevent_context
*ev
,
962 struct smbXsrv_connection
*conn
,
963 struct auth_session_info
*session_info
,
964 uint64_t previous_session_id
,
965 uint64_t current_session_id
)
967 struct tevent_req
*req
;
968 struct smb2srv_session_close_previous_state
*state
;
969 uint32_t global_id
= previous_session_id
& UINT32_MAX
;
970 uint64_t global_zeros
= previous_session_id
& 0xFFFFFFFF00000000LLU
;
971 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
972 struct security_token
*current_token
= NULL
;
974 req
= tevent_req_create(mem_ctx
, &state
,
975 struct smb2srv_session_close_previous_state
);
980 state
->connection
= conn
;
981 state
->current_session_id
= current_session_id
;
983 if (global_zeros
!= 0) {
984 tevent_req_done(req
);
985 return tevent_req_post(req
, ev
);
988 if (session_info
== NULL
) {
989 tevent_req_done(req
);
990 return tevent_req_post(req
, ev
);
992 current_token
= session_info
->security_token
;
994 if (current_token
->num_sids
> PRIMARY_USER_SID_INDEX
) {
995 state
->current_sid
= ¤t_token
->sids
[PRIMARY_USER_SID_INDEX
];
998 if (state
->current_sid
== NULL
) {
999 tevent_req_done(req
);
1000 return tevent_req_post(req
, ev
);
1003 if (!security_token_has_nt_authenticated_users(current_token
)) {
1005 tevent_req_done(req
);
1006 return tevent_req_post(req
, ev
);
1009 state
->db_rec
= smbXsrv_session_global_fetch_locked(
1010 table
->global
.db_ctx
,
1012 state
/* TALLOC_CTX */);
1013 if (state
->db_rec
== NULL
) {
1014 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
1015 return tevent_req_post(req
, ev
);
1018 smb2srv_session_close_previous_check(req
);
1019 if (!tevent_req_is_in_progress(req
)) {
1020 return tevent_req_post(req
, ev
);
1026 static void smb2srv_session_close_previous_check(struct tevent_req
*req
)
1028 struct smb2srv_session_close_previous_state
*state
=
1029 tevent_req_data(req
,
1030 struct smb2srv_session_close_previous_state
);
1031 struct smbXsrv_connection
*conn
= state
->connection
;
1033 struct security_token
*previous_token
= NULL
;
1034 struct smbXsrv_session_global0
*global
= NULL
;
1035 enum ndr_err_code ndr_err
;
1036 struct smbXsrv_session_close0 close_info0
;
1037 struct smbXsrv_session_closeB close_blob
;
1038 struct tevent_req
*subreq
= NULL
;
1040 bool is_free
= false;
1042 smbXsrv_session_global_verify_record(state
->db_rec
,
1049 TALLOC_FREE(state
->db_rec
);
1050 tevent_req_done(req
);
1054 if (global
->auth_session_info
== NULL
) {
1055 TALLOC_FREE(state
->db_rec
);
1056 tevent_req_done(req
);
1060 previous_token
= global
->auth_session_info
->security_token
;
1062 if (!security_token_is_sid(previous_token
, state
->current_sid
)) {
1063 TALLOC_FREE(state
->db_rec
);
1064 tevent_req_done(req
);
1068 subreq
= dbwrap_record_watch_send(state
, state
->ev
,
1069 state
->db_rec
, conn
->msg_ctx
);
1070 if (tevent_req_nomem(subreq
, req
)) {
1071 TALLOC_FREE(state
->db_rec
);
1074 tevent_req_set_callback(subreq
,
1075 smb2srv_session_close_previous_modified
,
1078 close_info0
.old_session_global_id
= global
->session_global_id
;
1079 close_info0
.old_session_wire_id
= global
->session_wire_id
;
1080 close_info0
.old_creation_time
= global
->creation_time
;
1081 close_info0
.new_session_wire_id
= state
->current_session_id
;
1083 ZERO_STRUCT(close_blob
);
1084 close_blob
.version
= smbXsrv_version_global_current();
1085 close_blob
.info
.info0
= &close_info0
;
1087 ndr_err
= ndr_push_struct_blob(&blob
, state
, &close_blob
,
1088 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_closeB
);
1089 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1090 TALLOC_FREE(state
->db_rec
);
1091 status
= ndr_map_error2ntstatus(ndr_err
);
1092 DEBUG(1,("smb2srv_session_close_previous_check: "
1093 "old_session[%llu] new_session[%llu] ndr_push - %s\n",
1094 (unsigned long long)close_info0
.old_session_wire_id
,
1095 (unsigned long long)close_info0
.new_session_wire_id
,
1096 nt_errstr(status
)));
1097 tevent_req_nterror(req
, status
);
1101 status
= messaging_send(conn
->msg_ctx
,
1102 global
->channels
[0].server_id
,
1103 MSG_SMBXSRV_SESSION_CLOSE
, &blob
);
1104 TALLOC_FREE(state
->db_rec
);
1105 if (tevent_req_nterror(req
, status
)) {
1109 TALLOC_FREE(global
);
1113 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
)
1115 struct tevent_req
*req
=
1116 tevent_req_callback_data(subreq
,
1118 struct smb2srv_session_close_previous_state
*state
=
1119 tevent_req_data(req
,
1120 struct smb2srv_session_close_previous_state
);
1123 status
= dbwrap_record_watch_recv(subreq
, state
, &state
->db_rec
);
1124 TALLOC_FREE(subreq
);
1125 if (tevent_req_nterror(req
, status
)) {
1129 smb2srv_session_close_previous_check(req
);
1132 NTSTATUS
smb2srv_session_close_previous_recv(struct tevent_req
*req
)
1136 if (tevent_req_is_nterror(req
, &status
)) {
1137 tevent_req_received(req
);
1141 tevent_req_received(req
);
1142 return NT_STATUS_OK
;
1145 static NTSTATUS
smbXsrv_session_clear_and_logoff(struct smbXsrv_session
*session
)
1148 struct smbXsrv_connection
*xconn
= NULL
;
1150 if (session
->client
!= NULL
) {
1151 xconn
= session
->client
->connections
;
1154 for (; xconn
!= NULL
; xconn
= xconn
->next
) {
1155 struct smbd_smb2_request
*preq
;
1157 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1158 if (preq
->session
!= session
) {
1162 preq
->session
= NULL
;
1164 * If we no longer have a session we can't
1165 * sign or encrypt replies.
1167 preq
->do_signing
= false;
1168 preq
->do_encryption
= false;
1169 preq
->preauth
= NULL
;
1173 status
= smbXsrv_session_logoff(session
);
1177 static int smbXsrv_session_destructor(struct smbXsrv_session
*session
)
1181 status
= smbXsrv_session_clear_and_logoff(session
);
1182 if (!NT_STATUS_IS_OK(status
)) {
1183 DEBUG(0, ("smbXsrv_session_destructor: "
1184 "smbXsrv_session_logoff() failed: %s\n",
1185 nt_errstr(status
)));
1188 TALLOC_FREE(session
->global
);
1193 NTSTATUS
smbXsrv_session_create(struct smbXsrv_connection
*conn
,
1195 struct smbXsrv_session
**_session
)
1197 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1198 struct db_record
*local_rec
= NULL
;
1199 struct smbXsrv_session
*session
= NULL
;
1202 struct smbXsrv_session_global0
*global
= NULL
;
1203 struct smbXsrv_channel_global0
*channel
= NULL
;
1206 if (table
->local
.num_sessions
>= table
->local
.max_sessions
) {
1207 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1210 session
= talloc_zero(table
, struct smbXsrv_session
);
1211 if (session
== NULL
) {
1212 return NT_STATUS_NO_MEMORY
;
1214 session
->table
= table
;
1215 session
->idle_time
= now
;
1216 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
1217 session
->client
= conn
->client
;
1219 status
= smbXsrv_session_global_allocate(table
->global
.db_ctx
,
1222 if (!NT_STATUS_IS_OK(status
)) {
1223 TALLOC_FREE(session
);
1226 session
->global
= global
;
1228 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1229 uint64_t id
= global
->session_global_id
;
1231 global
->connection_dialect
= conn
->smb2
.server
.dialect
;
1233 global
->session_wire_id
= id
;
1235 status
= smb2srv_tcon_table_init(session
);
1236 if (!NT_STATUS_IS_OK(status
)) {
1237 TALLOC_FREE(session
);
1241 session
->local_id
= global
->session_global_id
;
1243 local_rec
= smbXsrv_session_local_fetch_locked(
1244 table
->local
.db_ctx
,
1246 session
/* TALLOC_CTX */);
1247 if (local_rec
== NULL
) {
1248 TALLOC_FREE(session
);
1249 return NT_STATUS_NO_MEMORY
;
1252 val
= dbwrap_record_get_value(local_rec
);
1253 if (val
.dsize
!= 0) {
1254 TALLOC_FREE(session
);
1255 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1259 status
= smb1srv_session_local_allocate_id(table
->local
.db_ctx
,
1260 table
->local
.lowest_id
,
1261 table
->local
.highest_id
,
1264 &session
->local_id
);
1265 if (!NT_STATUS_IS_OK(status
)) {
1266 TALLOC_FREE(session
);
1270 global
->session_wire_id
= session
->local_id
;
1273 global
->creation_time
= now
;
1274 global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1276 status
= smbXsrv_session_add_channel(session
, conn
, &channel
);
1277 if (!NT_STATUS_IS_OK(status
)) {
1278 TALLOC_FREE(session
);
1283 val
= make_tdb_data((uint8_t const *)&ptr
, sizeof(ptr
));
1284 status
= dbwrap_record_store(local_rec
, val
, TDB_REPLACE
);
1285 TALLOC_FREE(local_rec
);
1286 if (!NT_STATUS_IS_OK(status
)) {
1287 TALLOC_FREE(session
);
1290 table
->local
.num_sessions
+= 1;
1292 talloc_set_destructor(session
, smbXsrv_session_destructor
);
1294 status
= smbXsrv_session_global_store(global
);
1295 if (!NT_STATUS_IS_OK(status
)) {
1296 DEBUG(0,("smbXsrv_session_create: "
1297 "global_id (0x%08x) store failed - %s\n",
1298 session
->global
->session_global_id
,
1299 nt_errstr(status
)));
1300 TALLOC_FREE(session
);
1305 struct smbXsrv_sessionB session_blob
;
1307 ZERO_STRUCT(session_blob
);
1308 session_blob
.version
= SMBXSRV_VERSION_0
;
1309 session_blob
.info
.info0
= session
;
1311 DEBUG(10,("smbXsrv_session_create: global_id (0x%08x) stored\n",
1312 session
->global
->session_global_id
));
1313 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1316 *_session
= session
;
1317 return NT_STATUS_OK
;
1320 NTSTATUS
smbXsrv_session_add_channel(struct smbXsrv_session
*session
,
1321 struct smbXsrv_connection
*conn
,
1322 struct smbXsrv_channel_global0
**_c
)
1324 struct smbXsrv_session_global0
*global
= session
->global
;
1325 struct smbXsrv_channel_global0
*c
= NULL
;
1327 if (global
->num_channels
> 31) {
1329 * Windows 2012 and 2012R2 allow up to 32 channels
1331 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1334 c
= talloc_realloc(global
,
1336 struct smbXsrv_channel_global0
,
1337 global
->num_channels
+ 1);
1339 return NT_STATUS_NO_MEMORY
;
1341 global
->channels
= c
;
1343 c
= &global
->channels
[global
->num_channels
];
1346 c
->server_id
= messaging_server_id(conn
->msg_ctx
);
1347 c
->local_address
= tsocket_address_string(conn
->local_address
,
1349 if (c
->local_address
== NULL
) {
1350 return NT_STATUS_NO_MEMORY
;
1352 c
->remote_address
= tsocket_address_string(conn
->remote_address
,
1354 if (c
->remote_address
== NULL
) {
1355 return NT_STATUS_NO_MEMORY
;
1357 c
->remote_name
= talloc_strdup(global
->channels
,
1358 conn
->remote_hostname
);
1359 if (c
->remote_name
== NULL
) {
1360 return NT_STATUS_NO_MEMORY
;
1362 c
->connection
= conn
;
1364 global
->num_channels
+= 1;
1367 return NT_STATUS_OK
;
1370 NTSTATUS
smbXsrv_session_update(struct smbXsrv_session
*session
)
1372 struct smbXsrv_session_table
*table
= session
->table
;
1375 if (session
->global
->db_rec
!= NULL
) {
1376 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1377 "Called with db_rec != NULL'\n",
1378 session
->global
->session_global_id
));
1379 return NT_STATUS_INTERNAL_ERROR
;
1382 session
->global
->db_rec
= smbXsrv_session_global_fetch_locked(
1383 table
->global
.db_ctx
,
1384 session
->global
->session_global_id
,
1385 session
->global
/* TALLOC_CTX */);
1386 if (session
->global
->db_rec
== NULL
) {
1387 return NT_STATUS_INTERNAL_DB_ERROR
;
1390 status
= smbXsrv_session_global_store(session
->global
);
1391 if (!NT_STATUS_IS_OK(status
)) {
1392 DEBUG(0,("smbXsrv_session_update: "
1393 "global_id (0x%08x) store failed - %s\n",
1394 session
->global
->session_global_id
,
1395 nt_errstr(status
)));
1400 struct smbXsrv_sessionB session_blob
;
1402 ZERO_STRUCT(session_blob
);
1403 session_blob
.version
= SMBXSRV_VERSION_0
;
1404 session_blob
.info
.info0
= session
;
1406 DEBUG(10,("smbXsrv_session_update: global_id (0x%08x) stored\n",
1407 session
->global
->session_global_id
));
1408 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1411 return NT_STATUS_OK
;
1414 NTSTATUS
smbXsrv_session_find_channel(const struct smbXsrv_session
*session
,
1415 const struct smbXsrv_connection
*conn
,
1416 struct smbXsrv_channel_global0
**_c
)
1420 for (i
=0; i
< session
->global
->num_channels
; i
++) {
1421 struct smbXsrv_channel_global0
*c
= &session
->global
->channels
[i
];
1423 if (c
->connection
== conn
) {
1425 return NT_STATUS_OK
;
1429 return NT_STATUS_USER_SESSION_DELETED
;
1432 NTSTATUS
smbXsrv_session_find_auth(const struct smbXsrv_session
*session
,
1433 const struct smbXsrv_connection
*conn
,
1435 struct smbXsrv_session_auth0
**_a
)
1437 struct smbXsrv_session_auth0
*a
;
1439 for (a
= session
->pending_auth
; a
!= NULL
; a
= a
->next
) {
1440 if (a
->connection
== conn
) {
1445 return NT_STATUS_OK
;
1449 return NT_STATUS_USER_SESSION_DELETED
;
1452 static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0
*a
)
1454 if (a
->session
== NULL
) {
1458 DLIST_REMOVE(a
->session
->pending_auth
, a
);
1463 NTSTATUS
smbXsrv_session_create_auth(struct smbXsrv_session
*session
,
1464 struct smbXsrv_connection
*conn
,
1467 uint8_t in_security_mode
,
1468 struct smbXsrv_session_auth0
**_a
)
1470 struct smbXsrv_session_auth0
*a
;
1473 status
= smbXsrv_session_find_auth(session
, conn
, 0, &a
);
1474 if (NT_STATUS_IS_OK(status
)) {
1475 return NT_STATUS_INTERNAL_ERROR
;
1478 a
= talloc_zero(session
, struct smbXsrv_session_auth0
);
1480 return NT_STATUS_NO_MEMORY
;
1482 a
->session
= session
;
1483 a
->connection
= conn
;
1484 a
->in_flags
= in_flags
;
1485 a
->in_security_mode
= in_security_mode
;
1486 a
->creation_time
= now
;
1489 if (conn
->protocol
>= PROTOCOL_SMB3_10
) {
1490 a
->preauth
= talloc(a
, struct smbXsrv_preauth
);
1491 if (a
->preauth
== NULL
) {
1492 TALLOC_FREE(session
);
1493 return NT_STATUS_NO_MEMORY
;
1495 *a
->preauth
= conn
->smb2
.preauth
;
1498 talloc_set_destructor(a
, smbXsrv_session_auth0_destructor
);
1499 DLIST_ADD_END(session
->pending_auth
, a
);
1502 return NT_STATUS_OK
;
1505 struct smb2srv_session_shutdown_state
{
1506 struct tevent_queue
*wait_queue
;
1509 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
);
1511 struct tevent_req
*smb2srv_session_shutdown_send(TALLOC_CTX
*mem_ctx
,
1512 struct tevent_context
*ev
,
1513 struct smbXsrv_session
*session
,
1514 struct smbd_smb2_request
*current_req
)
1516 struct tevent_req
*req
;
1517 struct smb2srv_session_shutdown_state
*state
;
1518 struct tevent_req
*subreq
;
1519 struct smbXsrv_connection
*xconn
= NULL
;
1523 * Make sure that no new request will be able to use this session.
1525 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1527 req
= tevent_req_create(mem_ctx
, &state
,
1528 struct smb2srv_session_shutdown_state
);
1533 state
->wait_queue
= tevent_queue_create(state
, "smb2srv_session_shutdown_queue");
1534 if (tevent_req_nomem(state
->wait_queue
, req
)) {
1535 return tevent_req_post(req
, ev
);
1538 for (xconn
= session
->client
->connections
; xconn
!= NULL
; xconn
= xconn
->next
) {
1539 struct smbd_smb2_request
*preq
;
1541 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1542 if (preq
== current_req
) {
1543 /* Can't cancel current request. */
1546 if (preq
->session
!= session
) {
1547 /* Request on different session. */
1551 if (!NT_STATUS_IS_OK(xconn
->transport
.status
)) {
1552 preq
->session
= NULL
;
1554 * If we no longer have a session we can't
1555 * sign or encrypt replies.
1557 preq
->do_signing
= false;
1558 preq
->do_encryption
= false;
1559 preq
->preauth
= NULL
;
1561 if (preq
->subreq
!= NULL
) {
1562 tevent_req_cancel(preq
->subreq
);
1568 * Never cancel anything in a compound
1569 * request. Way too hard to deal with
1572 if (!preq
->compound_related
&& preq
->subreq
!= NULL
) {
1573 tevent_req_cancel(preq
->subreq
);
1577 * Now wait until the request is finished.
1579 * We don't set a callback, as we just want to block the
1580 * wait queue and the talloc_free() of the request will
1581 * remove the item from the wait queue.
1583 subreq
= tevent_queue_wait_send(preq
, ev
, state
->wait_queue
);
1584 if (tevent_req_nomem(subreq
, req
)) {
1585 return tevent_req_post(req
, ev
);
1590 len
= tevent_queue_length(state
->wait_queue
);
1592 tevent_req_done(req
);
1593 return tevent_req_post(req
, ev
);
1597 * Now we add our own waiter to the end of the queue,
1598 * this way we get notified when all pending requests are finished
1599 * and send to the socket.
1601 subreq
= tevent_queue_wait_send(state
, ev
, state
->wait_queue
);
1602 if (tevent_req_nomem(subreq
, req
)) {
1603 return tevent_req_post(req
, ev
);
1605 tevent_req_set_callback(subreq
, smb2srv_session_shutdown_wait_done
, req
);
1610 static void smb2srv_session_shutdown_wait_done(struct tevent_req
*subreq
)
1612 struct tevent_req
*req
=
1613 tevent_req_callback_data(subreq
,
1616 tevent_queue_wait_recv(subreq
);
1617 TALLOC_FREE(subreq
);
1619 tevent_req_done(req
);
1622 NTSTATUS
smb2srv_session_shutdown_recv(struct tevent_req
*req
)
1624 return tevent_req_simple_recv_ntstatus(req
);
1627 NTSTATUS
smbXsrv_session_logoff(struct smbXsrv_session
*session
)
1629 struct smbXsrv_session_table
*table
;
1630 struct db_record
*local_rec
= NULL
;
1631 struct db_record
*global_rec
= NULL
;
1632 struct smbd_server_connection
*sconn
= NULL
;
1634 NTSTATUS error
= NT_STATUS_OK
;
1636 if (session
->table
== NULL
) {
1637 return NT_STATUS_OK
;
1640 table
= session
->table
;
1641 session
->table
= NULL
;
1643 sconn
= session
->client
->sconn
;
1644 session
->client
= NULL
;
1645 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1647 global_rec
= session
->global
->db_rec
;
1648 session
->global
->db_rec
= NULL
;
1649 if (global_rec
== NULL
) {
1650 global_rec
= smbXsrv_session_global_fetch_locked(
1651 table
->global
.db_ctx
,
1652 session
->global
->session_global_id
,
1653 session
->global
/* TALLOC_CTX */);
1654 if (global_rec
== NULL
) {
1655 error
= NT_STATUS_INTERNAL_ERROR
;
1659 if (global_rec
!= NULL
) {
1660 status
= dbwrap_record_delete(global_rec
);
1661 if (!NT_STATUS_IS_OK(status
)) {
1662 TDB_DATA key
= dbwrap_record_get_key(global_rec
);
1664 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1665 "failed to delete global key '%s': %s\n",
1666 session
->global
->session_global_id
,
1667 hex_encode_talloc(global_rec
, key
.dptr
,
1669 nt_errstr(status
)));
1673 TALLOC_FREE(global_rec
);
1675 local_rec
= session
->db_rec
;
1676 if (local_rec
== NULL
) {
1677 local_rec
= smbXsrv_session_local_fetch_locked(
1678 table
->local
.db_ctx
,
1680 session
/* TALLOC_CTX */);
1681 if (local_rec
== NULL
) {
1682 error
= NT_STATUS_INTERNAL_ERROR
;
1686 if (local_rec
!= NULL
) {
1687 status
= dbwrap_record_delete(local_rec
);
1688 if (!NT_STATUS_IS_OK(status
)) {
1689 TDB_DATA key
= dbwrap_record_get_key(local_rec
);
1691 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1692 "failed to delete local key '%s': %s\n",
1693 session
->global
->session_global_id
,
1694 hex_encode_talloc(local_rec
, key
.dptr
,
1696 nt_errstr(status
)));
1699 table
->local
.num_sessions
-= 1;
1701 if (session
->db_rec
== NULL
) {
1702 TALLOC_FREE(local_rec
);
1704 session
->db_rec
= NULL
;
1706 if (session
->compat
) {
1707 file_close_user(sconn
, session
->compat
->vuid
);
1710 if (session
->tcon_table
!= NULL
) {
1712 * Note: We only have a tcon_table for SMB2.
1714 status
= smb2srv_tcon_disconnect_all(session
);
1715 if (!NT_STATUS_IS_OK(status
)) {
1716 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1717 "smb2srv_tcon_disconnect_all() failed: %s\n",
1718 session
->global
->session_global_id
,
1719 nt_errstr(status
)));
1724 if (session
->compat
) {
1725 invalidate_vuid(sconn
, session
->compat
->vuid
);
1726 session
->compat
= NULL
;
1732 struct smbXsrv_session_logoff_all_state
{
1733 NTSTATUS first_status
;
1737 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1738 void *private_data
);
1740 NTSTATUS
smbXsrv_session_logoff_all(struct smbXsrv_connection
*conn
)
1742 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1743 struct smbXsrv_session_logoff_all_state state
;
1747 if (table
== NULL
) {
1748 DEBUG(10, ("smbXsrv_session_logoff_all: "
1749 "empty session_table, nothing to do.\n"));
1750 return NT_STATUS_OK
;
1755 status
= dbwrap_traverse(table
->local
.db_ctx
,
1756 smbXsrv_session_logoff_all_callback
,
1758 if (!NT_STATUS_IS_OK(status
)) {
1759 DEBUG(0, ("smbXsrv_session_logoff_all: "
1760 "dbwrap_traverse() failed: %s\n",
1761 nt_errstr(status
)));
1765 if (!NT_STATUS_IS_OK(state
.first_status
)) {
1766 DEBUG(0, ("smbXsrv_session_logoff_all: "
1767 "count[%d] errors[%d] first[%s]\n",
1768 count
, state
.errors
,
1769 nt_errstr(state
.first_status
)));
1770 return state
.first_status
;
1773 return NT_STATUS_OK
;
1776 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1779 struct smbXsrv_session_logoff_all_state
*state
=
1780 (struct smbXsrv_session_logoff_all_state
*)private_data
;
1783 struct smbXsrv_session
*session
= NULL
;
1786 val
= dbwrap_record_get_value(local_rec
);
1787 if (val
.dsize
!= sizeof(ptr
)) {
1788 status
= NT_STATUS_INTERNAL_ERROR
;
1789 if (NT_STATUS_IS_OK(state
->first_status
)) {
1790 state
->first_status
= status
;
1796 memcpy(&ptr
, val
.dptr
, val
.dsize
);
1797 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
1799 session
->db_rec
= local_rec
;
1801 status
= smbXsrv_session_clear_and_logoff(session
);
1802 if (!NT_STATUS_IS_OK(status
)) {
1803 if (NT_STATUS_IS_OK(state
->first_status
)) {
1804 state
->first_status
= status
;
1813 NTSTATUS
smb1srv_session_table_init(struct smbXsrv_connection
*conn
)
1816 * Allow a range from 1..65534 with 65534 values.
1818 return smbXsrv_session_table_init(conn
, 1, UINT16_MAX
- 1,
1822 NTSTATUS
smb1srv_session_lookup(struct smbXsrv_connection
*conn
,
1823 uint16_t vuid
, NTTIME now
,
1824 struct smbXsrv_session
**session
)
1826 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1827 uint32_t local_id
= vuid
;
1829 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
1833 NTSTATUS
smb2srv_session_table_init(struct smbXsrv_connection
*conn
)
1836 * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
1838 return smbXsrv_session_table_init(conn
, 1, UINT32_MAX
- 1,
1842 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
1843 /* conn: optional */
1844 struct smbXsrv_connection
*conn
,
1845 uint64_t session_id
, NTTIME now
,
1846 struct smbXsrv_session
**session
)
1848 uint32_t local_id
= session_id
& UINT32_MAX
;
1849 uint64_t local_zeros
= session_id
& 0xFFFFFFFF00000000LLU
;
1851 if (local_zeros
!= 0) {
1852 return NT_STATUS_USER_SESSION_DELETED
;
1855 return smbXsrv_session_local_lookup(table
, conn
, local_id
, now
,
1859 NTSTATUS
smb2srv_session_lookup_conn(struct smbXsrv_connection
*conn
,
1860 uint64_t session_id
, NTTIME now
,
1861 struct smbXsrv_session
**session
)
1863 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1864 return smb2srv_session_lookup_raw(table
, conn
, session_id
, now
,
1868 NTSTATUS
smb2srv_session_lookup_client(struct smbXsrv_client
*client
,
1869 uint64_t session_id
, NTTIME now
,
1870 struct smbXsrv_session
**session
)
1872 struct smbXsrv_session_table
*table
= client
->session_table
;
1873 return smb2srv_session_lookup_raw(table
, NULL
, session_id
, now
,
1877 struct smbXsrv_session_global_traverse_state
{
1878 int (*fn
)(struct smbXsrv_session_global0
*, void *);
1882 static int smbXsrv_session_global_traverse_fn(struct db_record
*rec
, void *data
)
1885 struct smbXsrv_session_global_traverse_state
*state
=
1886 (struct smbXsrv_session_global_traverse_state
*)data
;
1887 TDB_DATA key
= dbwrap_record_get_key(rec
);
1888 TDB_DATA val
= dbwrap_record_get_value(rec
);
1889 DATA_BLOB blob
= data_blob_const(val
.dptr
, val
.dsize
);
1890 struct smbXsrv_session_globalB global_blob
;
1891 enum ndr_err_code ndr_err
;
1892 TALLOC_CTX
*frame
= talloc_stackframe();
1894 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
1895 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
1896 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1897 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1898 "key '%s' ndr_pull_struct_blob - %s\n",
1899 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1900 ndr_errstr(ndr_err
)));
1904 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
1905 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1906 "key '%s' unsuported version - %d\n",
1907 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1908 (int)global_blob
.version
));
1912 global_blob
.info
.info0
->db_rec
= rec
;
1913 ret
= state
->fn(global_blob
.info
.info0
, state
->private_data
);
1919 NTSTATUS
smbXsrv_session_global_traverse(
1920 int (*fn
)(struct smbXsrv_session_global0
*, void *),
1926 struct smbXsrv_session_global_traverse_state state
= {
1928 .private_data
= private_data
,
1932 status
= smbXsrv_session_global_init();
1933 if (!NT_STATUS_IS_OK(status
)) {
1935 DEBUG(0, ("Failed to initialize session_global: %s\n",
1936 nt_errstr(status
)));
1940 status
= dbwrap_traverse_read(smbXsrv_session_global_db_ctx
,
1941 smbXsrv_session_global_traverse_fn
,