2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2011-2012
5 Copyright (C) Michael Adam 2012
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "dbwrap/dbwrap.h"
27 #include "dbwrap/dbwrap_rbt.h"
28 #include "dbwrap/dbwrap_open.h"
29 #include "dbwrap/dbwrap_watch.h"
32 #include "auth/gensec/gensec.h"
33 #include "../lib/tsocket/tsocket.h"
34 #include "../libcli/security/security.h"
36 #include "lib/util/util_tdb.h"
37 #include "librpc/gen_ndr/ndr_smbXsrv.h"
39 #include "lib/util/tevent_ntstatus.h"
41 struct smbXsrv_session_table
{
43 struct db_context
*db_ctx
;
46 uint32_t max_sessions
;
47 uint32_t num_sessions
;
50 struct db_context
*db_ctx
;
54 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
55 uint64_t session_id
, NTTIME now
,
56 struct smbXsrv_session
**session
);
58 static struct db_context
*smbXsrv_session_global_db_ctx
= NULL
;
60 NTSTATUS
smbXsrv_session_global_init(void)
62 char *global_path
= NULL
;
63 struct db_context
*db_ctx
= NULL
;
65 if (smbXsrv_session_global_db_ctx
!= NULL
) {
70 * This contains secret information like session keys!
72 global_path
= lock_path("smbXsrv_session_global.tdb");
73 if (global_path
== NULL
) {
74 return NT_STATUS_NO_MEMORY
;
77 db_ctx
= db_open(NULL
, global_path
,
81 TDB_INCOMPATIBLE_HASH
,
82 O_RDWR
| O_CREAT
, 0600,
85 TALLOC_FREE(global_path
);
89 status
= map_nt_error_from_unix_common(errno
);
94 smbXsrv_session_global_db_ctx
= db_ctx
;
101 * We need to store the keys in big endian so that dbwrap_rbt's memcmp
102 * has the same result as integer comparison between the uint32_t
105 * TODO: implement string based key
108 #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
110 static TDB_DATA
smbXsrv_session_global_id_to_key(uint32_t id
,
115 RSIVAL(key_buf
, 0, id
);
117 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
);
123 static NTSTATUS
smbXsrv_session_global_key_to_id(TDB_DATA key
, uint32_t *id
)
126 return NT_STATUS_INVALID_PARAMETER
;
129 if (key
.dsize
!= SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
) {
130 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
133 *id
= RIVAL(key
.dptr
, 0);
139 #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
141 static TDB_DATA
smbXsrv_session_local_id_to_key(uint32_t id
,
146 RSIVAL(key_buf
, 0, id
);
148 key
= make_tdb_data(key_buf
, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
);
153 static NTSTATUS
smbXsrv_session_local_key_to_id(TDB_DATA key
, uint32_t *id
)
156 return NT_STATUS_INVALID_PARAMETER
;
159 if (key
.dsize
!= SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
) {
160 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
163 *id
= RIVAL(key
.dptr
, 0);
168 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
);
170 static NTSTATUS
smbXsrv_session_table_init(struct smbXsrv_connection
*conn
,
173 uint32_t max_sessions
)
175 struct smbXsrv_client
*client
= conn
->client
;
176 struct smbXsrv_session_table
*table
;
178 struct tevent_req
*subreq
;
181 if (lowest_id
> highest_id
) {
182 return NT_STATUS_INTERNAL_ERROR
;
185 max_range
= highest_id
;
186 max_range
-= lowest_id
;
189 if (max_sessions
> max_range
) {
190 return NT_STATUS_INTERNAL_ERROR
;
193 table
= talloc_zero(client
, struct smbXsrv_session_table
);
195 return NT_STATUS_NO_MEMORY
;
198 table
->local
.db_ctx
= db_open_rbt(table
);
199 if (table
->local
.db_ctx
== NULL
) {
201 return NT_STATUS_NO_MEMORY
;
203 table
->local
.lowest_id
= lowest_id
;
204 table
->local
.highest_id
= highest_id
;
205 table
->local
.max_sessions
= max_sessions
;
207 status
= smbXsrv_session_global_init();
208 if (!NT_STATUS_IS_OK(status
)) {
213 table
->global
.db_ctx
= smbXsrv_session_global_db_ctx
;
215 dbwrap_watch_db(table
->global
.db_ctx
, client
->msg_ctx
);
217 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
218 MSG_SMBXSRV_SESSION_CLOSE
);
219 if (subreq
== NULL
) {
221 return NT_STATUS_NO_MEMORY
;
223 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
225 client
->session_table
= table
;
229 static void smbXsrv_session_close_loop(struct tevent_req
*subreq
)
231 struct smbXsrv_client
*client
=
232 tevent_req_callback_data(subreq
,
233 struct smbXsrv_client
);
234 struct smbXsrv_session_table
*table
= client
->session_table
;
236 struct messaging_rec
*rec
= NULL
;
237 struct smbXsrv_session_closeB close_blob
;
238 enum ndr_err_code ndr_err
;
239 struct smbXsrv_session_close0
*close_info0
= NULL
;
240 struct smbXsrv_session
*session
= NULL
;
242 struct timeval tv
= timeval_current();
243 NTTIME now
= timeval_to_nttime(&tv
);
245 ret
= messaging_read_recv(subreq
, talloc_tos(), &rec
);
251 ndr_err
= ndr_pull_struct_blob(&rec
->buf
, rec
, &close_blob
,
252 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_closeB
);
253 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
254 status
= ndr_map_error2ntstatus(ndr_err
);
255 DEBUG(1,("smbXsrv_session_close_loop: "
256 "ndr_pull_struct_blob - %s\n",
261 DEBUG(10,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
263 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
266 if (close_blob
.version
!= SMBXSRV_VERSION_0
) {
267 DEBUG(0,("smbXsrv_session_close_loop: "
268 "ignore invalid version %u\n", close_blob
.version
));
269 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
273 close_info0
= close_blob
.info
.info0
;
274 if (close_info0
== NULL
) {
275 DEBUG(0,("smbXsrv_session_close_loop: "
276 "ignore NULL info %u\n", close_blob
.version
));
277 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
281 status
= smb2srv_session_lookup_raw(client
->session_table
,
282 close_info0
->old_session_wire_id
,
284 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_SESSION_DELETED
)) {
285 DEBUG(4,("smbXsrv_session_close_loop: "
286 "old_session_wire_id %llu not found\n",
287 (unsigned long long)close_info0
->old_session_wire_id
));
289 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
293 if (!NT_STATUS_IS_OK(status
) &&
294 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
) &&
295 !NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
296 DEBUG(1,("smbXsrv_session_close_loop: "
297 "old_session_wire_id %llu - %s\n",
298 (unsigned long long)close_info0
->old_session_wire_id
,
301 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
306 if (session
->global
->session_global_id
!= close_info0
->old_session_global_id
) {
307 DEBUG(1,("smbXsrv_session_close_loop: "
308 "old_session_wire_id %llu - global %u != %u\n",
309 (unsigned long long)close_info0
->old_session_wire_id
,
310 session
->global
->session_global_id
,
311 close_info0
->old_session_global_id
));
313 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
318 if (session
->global
->creation_time
!= close_info0
->old_creation_time
) {
319 DEBUG(1,("smbXsrv_session_close_loop: "
320 "old_session_wire_id %llu - "
321 "creation %s (%llu) != %s (%llu)\n",
322 (unsigned long long)close_info0
->old_session_wire_id
,
323 nt_time_string(rec
, session
->global
->creation_time
),
324 (unsigned long long)session
->global
->creation_time
,
325 nt_time_string(rec
, close_info0
->old_creation_time
),
326 (unsigned long long)close_info0
->old_creation_time
));
328 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
334 * TODO: cancel all outstanding requests on the session
336 status
= smbXsrv_session_logoff(session
);
337 if (!NT_STATUS_IS_OK(status
)) {
338 DEBUG(0, ("smbXsrv_session_close_loop: "
339 "smbXsrv_session_logoff(%llu) failed: %s\n",
340 (unsigned long long)session
->global
->session_wire_id
,
343 NDR_PRINT_DEBUG(smbXsrv_session_closeB
, &close_blob
);
346 TALLOC_FREE(session
);
351 subreq
= messaging_read_send(table
, client
->ev_ctx
, client
->msg_ctx
,
352 MSG_SMBXSRV_SESSION_CLOSE
);
353 if (subreq
== NULL
) {
355 r
= "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
356 exit_server_cleanly(r
);
359 tevent_req_set_callback(subreq
, smbXsrv_session_close_loop
, client
);
362 struct smb1srv_session_local_allocate_state
{
363 const uint32_t lowest_id
;
364 const uint32_t highest_id
;
370 static int smb1srv_session_local_allocate_traverse(struct db_record
*rec
,
373 struct smb1srv_session_local_allocate_state
*state
=
374 (struct smb1srv_session_local_allocate_state
*)private_data
;
375 TDB_DATA key
= dbwrap_record_get_key(rec
);
379 status
= smbXsrv_session_local_key_to_id(key
, &id
);
380 if (!NT_STATUS_IS_OK(status
)) {
381 state
->status
= status
;
385 if (id
<= state
->last_id
) {
386 state
->status
= NT_STATUS_INTERNAL_DB_CORRUPTION
;
391 if (id
> state
->useable_id
) {
392 state
->status
= NT_STATUS_OK
;
396 if (state
->useable_id
== state
->highest_id
) {
397 state
->status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
401 state
->useable_id
+=1;
405 static NTSTATUS
smb1srv_session_local_allocate_id(struct db_context
*db
,
409 struct db_record
**_rec
,
412 struct smb1srv_session_local_allocate_state state
= {
413 .lowest_id
= lowest_id
,
414 .highest_id
= highest_id
,
416 .useable_id
= lowest_id
,
417 .status
= NT_STATUS_INTERNAL_ERROR
,
427 if (lowest_id
> highest_id
) {
428 return NT_STATUS_INSUFFICIENT_RESOURCES
;
432 * first we try randomly
434 range
= (highest_id
- lowest_id
) + 1;
436 for (i
= 0; i
< (range
/ 2); i
++) {
438 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
441 struct db_record
*rec
= NULL
;
443 id
= generate_random() % range
;
446 if (id
< lowest_id
) {
449 if (id
> highest_id
) {
453 key
= smbXsrv_session_local_id_to_key(id
, key_buf
);
455 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
457 return NT_STATUS_INSUFFICIENT_RESOURCES
;
460 val
= dbwrap_record_get_value(rec
);
461 if (val
.dsize
!= 0) {
472 * if the range is almost full,
473 * we traverse the whole table
474 * (this relies on sorted behavior of dbwrap_rbt)
476 status
= dbwrap_traverse_read(db
, smb1srv_session_local_allocate_traverse
,
478 if (NT_STATUS_IS_OK(status
)) {
479 if (NT_STATUS_IS_OK(state
.status
)) {
480 return NT_STATUS_INTERNAL_ERROR
;
483 if (!NT_STATUS_EQUAL(state
.status
, NT_STATUS_INTERNAL_ERROR
)) {
487 if (state
.useable_id
<= state
.highest_id
) {
488 state
.status
= NT_STATUS_OK
;
490 return NT_STATUS_INSUFFICIENT_RESOURCES
;
492 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_INTERNAL_DB_CORRUPTION
)) {
494 * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
496 * If we get anything else it is an error, because it
497 * means we did not manage to find a free slot in
500 return NT_STATUS_INSUFFICIENT_RESOURCES
;
503 if (NT_STATUS_IS_OK(state
.status
)) {
505 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
508 struct db_record
*rec
= NULL
;
510 id
= state
.useable_id
;
512 key
= smbXsrv_session_local_id_to_key(id
, key_buf
);
514 rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
516 return NT_STATUS_INSUFFICIENT_RESOURCES
;
519 val
= dbwrap_record_get_value(rec
);
520 if (val
.dsize
!= 0) {
522 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
533 struct smbXsrv_session_local_fetch_state
{
534 struct smbXsrv_session
*session
;
538 static void smbXsrv_session_local_fetch_parser(TDB_DATA key
, TDB_DATA data
,
541 struct smbXsrv_session_local_fetch_state
*state
=
542 (struct smbXsrv_session_local_fetch_state
*)private_data
;
545 if (data
.dsize
!= sizeof(ptr
)) {
546 state
->status
= NT_STATUS_INTERNAL_DB_ERROR
;
550 memcpy(&ptr
, data
.dptr
, data
.dsize
);
551 state
->session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
552 state
->status
= NT_STATUS_OK
;
555 static NTSTATUS
smbXsrv_session_local_lookup(struct smbXsrv_session_table
*table
,
556 uint32_t session_local_id
,
558 struct smbXsrv_session
**_session
)
560 struct smbXsrv_session_local_fetch_state state
= {
562 .status
= NT_STATUS_INTERNAL_ERROR
,
564 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
570 if (session_local_id
== 0) {
571 return NT_STATUS_USER_SESSION_DELETED
;
575 /* this might happen before the end of negprot */
576 return NT_STATUS_USER_SESSION_DELETED
;
579 if (table
->local
.db_ctx
== NULL
) {
580 return NT_STATUS_INTERNAL_ERROR
;
583 key
= smbXsrv_session_local_id_to_key(session_local_id
, key_buf
);
585 status
= dbwrap_parse_record(table
->local
.db_ctx
, key
,
586 smbXsrv_session_local_fetch_parser
,
588 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
589 return NT_STATUS_USER_SESSION_DELETED
;
590 } else if (!NT_STATUS_IS_OK(status
)) {
593 if (!NT_STATUS_IS_OK(state
.status
)) {
597 if (NT_STATUS_EQUAL(state
.session
->status
, NT_STATUS_USER_SESSION_DELETED
)) {
598 return NT_STATUS_USER_SESSION_DELETED
;
601 state
.session
->idle_time
= now
;
603 if (!NT_STATUS_IS_OK(state
.session
->status
)) {
604 *_session
= state
.session
;
605 return state
.session
->status
;
608 if (now
> state
.session
->global
->expiration_time
) {
609 state
.session
->status
= NT_STATUS_NETWORK_SESSION_EXPIRED
;
612 *_session
= state
.session
;
613 return state
.session
->status
;
616 static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0
*global
)
621 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
625 struct smbXsrv_session_global0
**_g
);
627 static NTSTATUS
smbXsrv_session_global_allocate(struct db_context
*db
,
629 struct smbXsrv_session_global0
**_global
)
632 struct smbXsrv_session_global0
*global
= NULL
;
633 uint32_t last_free
= 0;
634 const uint32_t min_tries
= 3;
638 global
= talloc_zero(mem_ctx
, struct smbXsrv_session_global0
);
639 if (global
== NULL
) {
640 return NT_STATUS_NO_MEMORY
;
642 talloc_set_destructor(global
, smbXsrv_session_global_destructor
);
645 * Here we just randomly try the whole 32-bit space
647 * We use just 32-bit, because we want to reuse the
650 for (i
= 0; i
< UINT32_MAX
; i
++) {
651 bool is_free
= false;
652 bool was_free
= false;
654 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
657 if (i
>= min_tries
&& last_free
!= 0) {
660 id
= generate_random();
665 if (id
== UINT32_MAX
) {
669 key
= smbXsrv_session_global_id_to_key(id
, key_buf
);
671 global
->db_rec
= dbwrap_fetch_locked(db
, mem_ctx
, key
);
672 if (global
->db_rec
== NULL
) {
674 return NT_STATUS_INSUFFICIENT_RESOURCES
;
677 smbXsrv_session_global_verify_record(global
->db_rec
,
683 TALLOC_FREE(global
->db_rec
);
687 if (!was_free
&& i
< min_tries
) {
689 * The session_id is free now,
690 * but was not free before.
692 * This happens if a smbd crashed
693 * and did not cleanup the record.
695 * If this is one of our first tries,
696 * then we try to find a real free one.
698 if (last_free
== 0) {
701 TALLOC_FREE(global
->db_rec
);
705 global
->session_global_id
= id
;
711 /* should not be reached */
713 return NT_STATUS_INTERNAL_ERROR
;
716 static void smbXsrv_session_global_verify_record(struct db_record
*db_rec
,
720 struct smbXsrv_session_global0
**_g
)
725 struct smbXsrv_session_globalB global_blob
;
726 enum ndr_err_code ndr_err
;
727 struct smbXsrv_session_global0
*global
= NULL
;
729 TALLOC_CTX
*frame
= talloc_stackframe();
740 key
= dbwrap_record_get_key(db_rec
);
742 val
= dbwrap_record_get_value(db_rec
);
743 if (val
.dsize
== 0) {
752 blob
= data_blob_const(val
.dptr
, val
.dsize
);
754 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
755 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
756 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
757 NTSTATUS status
= ndr_map_error2ntstatus(ndr_err
);
758 DEBUG(1,("smbXsrv_session_global_verify_record: "
759 "key '%s' ndr_pull_struct_blob - %s\n",
760 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
766 DEBUG(10,("smbXsrv_session_global_verify_record\n"));
768 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
771 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
772 DEBUG(0,("smbXsrv_session_global_verify_record: "
773 "key '%s' use unsupported version %u\n",
774 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
775 global_blob
.version
));
776 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
781 global
= global_blob
.info
.info0
;
783 exists
= serverid_exists(&global
->channels
[0].server_id
);
785 struct server_id_buf idbuf
;
786 DEBUG(2,("smbXsrv_session_global_verify_record: "
787 "key '%s' server_id %s does not exist.\n",
788 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
789 server_id_str_buf(global
->channels
[0].server_id
,
792 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
795 dbwrap_record_delete(db_rec
);
801 *_g
= talloc_move(mem_ctx
, &global
);
806 static NTSTATUS
smbXsrv_session_global_store(struct smbXsrv_session_global0
*global
)
808 struct smbXsrv_session_globalB global_blob
;
809 DATA_BLOB blob
= data_blob_null
;
813 enum ndr_err_code ndr_err
;
816 * TODO: if we use other versions than '0'
817 * we would add glue code here, that would be able to
818 * store the information in the old format.
821 if (global
->db_rec
== NULL
) {
822 return NT_STATUS_INTERNAL_ERROR
;
825 key
= dbwrap_record_get_key(global
->db_rec
);
826 val
= dbwrap_record_get_value(global
->db_rec
);
828 ZERO_STRUCT(global_blob
);
829 global_blob
.version
= smbXsrv_version_global_current();
830 if (val
.dsize
>= 8) {
831 global_blob
.seqnum
= IVAL(val
.dptr
, 4);
833 global_blob
.seqnum
+= 1;
834 global_blob
.info
.info0
= global
;
836 ndr_err
= ndr_push_struct_blob(&blob
, global
->db_rec
, &global_blob
,
837 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_globalB
);
838 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
839 status
= ndr_map_error2ntstatus(ndr_err
);
840 DEBUG(1,("smbXsrv_session_global_store: key '%s' ndr_push - %s\n",
841 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
843 TALLOC_FREE(global
->db_rec
);
847 val
= make_tdb_data(blob
.data
, blob
.length
);
848 status
= dbwrap_record_store(global
->db_rec
, val
, TDB_REPLACE
);
849 if (!NT_STATUS_IS_OK(status
)) {
850 DEBUG(1,("smbXsrv_session_global_store: key '%s' store - %s\n",
851 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
),
853 TALLOC_FREE(global
->db_rec
);
858 DEBUG(10,("smbXsrv_session_global_store: key '%s' stored\n",
859 hex_encode_talloc(global
->db_rec
, key
.dptr
, key
.dsize
)));
860 NDR_PRINT_DEBUG(smbXsrv_session_globalB
, &global_blob
);
863 TALLOC_FREE(global
->db_rec
);
868 struct smb2srv_session_close_previous_state
{
869 struct tevent_context
*ev
;
870 struct smbXsrv_connection
*connection
;
871 struct dom_sid
*current_sid
;
872 uint64_t current_session_id
;
873 struct db_record
*db_rec
;
876 static void smb2srv_session_close_previous_check(struct tevent_req
*req
);
877 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
);
879 struct tevent_req
*smb2srv_session_close_previous_send(TALLOC_CTX
*mem_ctx
,
880 struct tevent_context
*ev
,
881 struct smbXsrv_connection
*conn
,
882 struct auth_session_info
*session_info
,
883 uint64_t previous_session_id
,
884 uint64_t current_session_id
)
886 struct tevent_req
*req
;
887 struct smb2srv_session_close_previous_state
*state
;
888 uint32_t global_id
= previous_session_id
& UINT32_MAX
;
889 uint64_t global_zeros
= previous_session_id
& 0xFFFFFFFF00000000LLU
;
890 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
891 struct security_token
*current_token
= NULL
;
892 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
895 req
= tevent_req_create(mem_ctx
, &state
,
896 struct smb2srv_session_close_previous_state
);
901 state
->connection
= conn
;
902 state
->current_session_id
= current_session_id
;
904 if (global_zeros
!= 0) {
905 tevent_req_done(req
);
906 return tevent_req_post(req
, ev
);
909 if (session_info
== NULL
) {
910 tevent_req_done(req
);
911 return tevent_req_post(req
, ev
);
913 current_token
= session_info
->security_token
;
915 if (current_token
->num_sids
> PRIMARY_USER_SID_INDEX
) {
916 state
->current_sid
= ¤t_token
->sids
[PRIMARY_USER_SID_INDEX
];
919 if (state
->current_sid
== NULL
) {
920 tevent_req_done(req
);
921 return tevent_req_post(req
, ev
);
924 if (!security_token_has_nt_authenticated_users(current_token
)) {
926 tevent_req_done(req
);
927 return tevent_req_post(req
, ev
);
930 key
= smbXsrv_session_global_id_to_key(global_id
, key_buf
);
932 state
->db_rec
= dbwrap_fetch_locked(table
->global
.db_ctx
,
934 if (state
->db_rec
== NULL
) {
935 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
936 return tevent_req_post(req
, ev
);
939 smb2srv_session_close_previous_check(req
);
940 if (!tevent_req_is_in_progress(req
)) {
941 return tevent_req_post(req
, ev
);
947 static void smb2srv_session_close_previous_check(struct tevent_req
*req
)
949 struct smb2srv_session_close_previous_state
*state
=
951 struct smb2srv_session_close_previous_state
);
952 struct smbXsrv_connection
*conn
= state
->connection
;
954 struct security_token
*previous_token
= NULL
;
955 struct smbXsrv_session_global0
*global
= NULL
;
956 enum ndr_err_code ndr_err
;
957 struct smbXsrv_session_close0 close_info0
;
958 struct smbXsrv_session_closeB close_blob
;
959 struct tevent_req
*subreq
= NULL
;
961 bool is_free
= false;
963 smbXsrv_session_global_verify_record(state
->db_rec
,
970 TALLOC_FREE(state
->db_rec
);
971 tevent_req_done(req
);
975 if (global
->auth_session_info
== NULL
) {
976 TALLOC_FREE(state
->db_rec
);
977 tevent_req_done(req
);
981 previous_token
= global
->auth_session_info
->security_token
;
983 if (!security_token_is_sid(previous_token
, state
->current_sid
)) {
984 TALLOC_FREE(state
->db_rec
);
985 tevent_req_done(req
);
989 subreq
= dbwrap_record_watch_send(state
, state
->ev
,
990 state
->db_rec
, conn
->msg_ctx
);
991 if (tevent_req_nomem(subreq
, req
)) {
992 TALLOC_FREE(state
->db_rec
);
995 tevent_req_set_callback(subreq
,
996 smb2srv_session_close_previous_modified
,
999 close_info0
.old_session_global_id
= global
->session_global_id
;
1000 close_info0
.old_session_wire_id
= global
->session_wire_id
;
1001 close_info0
.old_creation_time
= global
->creation_time
;
1002 close_info0
.new_session_wire_id
= state
->current_session_id
;
1004 ZERO_STRUCT(close_blob
);
1005 close_blob
.version
= smbXsrv_version_global_current();
1006 close_blob
.info
.info0
= &close_info0
;
1008 ndr_err
= ndr_push_struct_blob(&blob
, state
, &close_blob
,
1009 (ndr_push_flags_fn_t
)ndr_push_smbXsrv_session_closeB
);
1010 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1011 TALLOC_FREE(state
->db_rec
);
1012 status
= ndr_map_error2ntstatus(ndr_err
);
1013 DEBUG(1,("smb2srv_session_close_previous_check: "
1014 "old_session[%llu] new_session[%llu] ndr_push - %s\n",
1015 (unsigned long long)close_info0
.old_session_wire_id
,
1016 (unsigned long long)close_info0
.new_session_wire_id
,
1017 nt_errstr(status
)));
1018 tevent_req_nterror(req
, status
);
1022 status
= messaging_send(conn
->msg_ctx
,
1023 global
->channels
[0].server_id
,
1024 MSG_SMBXSRV_SESSION_CLOSE
, &blob
);
1025 TALLOC_FREE(state
->db_rec
);
1026 if (tevent_req_nterror(req
, status
)) {
1030 TALLOC_FREE(global
);
1034 static void smb2srv_session_close_previous_modified(struct tevent_req
*subreq
)
1036 struct tevent_req
*req
=
1037 tevent_req_callback_data(subreq
,
1039 struct smb2srv_session_close_previous_state
*state
=
1040 tevent_req_data(req
,
1041 struct smb2srv_session_close_previous_state
);
1044 status
= dbwrap_record_watch_recv(subreq
, state
, &state
->db_rec
);
1045 TALLOC_FREE(subreq
);
1046 if (tevent_req_nterror(req
, status
)) {
1050 smb2srv_session_close_previous_check(req
);
1053 NTSTATUS
smb2srv_session_close_previous_recv(struct tevent_req
*req
)
1057 if (tevent_req_is_nterror(req
, &status
)) {
1058 tevent_req_received(req
);
1062 tevent_req_received(req
);
1063 return NT_STATUS_OK
;
1066 static int smbXsrv_session_destructor(struct smbXsrv_session
*session
)
1069 struct smbXsrv_connection
*xconn
= NULL
;
1071 if (session
->client
!= NULL
) {
1072 xconn
= session
->client
->connections
;
1075 for (; xconn
!= NULL
; xconn
= xconn
->next
) {
1076 struct smbd_smb2_request
*preq
;
1078 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1079 if (preq
->session
!= session
) {
1083 preq
->session
= NULL
;
1085 * If we no longer have a session we can't
1086 * sign or encrypt replies.
1088 preq
->do_signing
= false;
1089 preq
->do_encryption
= false;
1093 status
= smbXsrv_session_logoff(session
);
1094 if (!NT_STATUS_IS_OK(status
)) {
1095 DEBUG(0, ("smbXsrv_session_destructor: "
1096 "smbXsrv_session_logoff() failed: %s\n",
1097 nt_errstr(status
)));
1100 TALLOC_FREE(session
->global
);
1105 NTSTATUS
smbXsrv_session_create(struct smbXsrv_connection
*conn
,
1107 struct smbXsrv_session
**_session
)
1109 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1110 struct db_record
*local_rec
= NULL
;
1111 struct smbXsrv_session
*session
= NULL
;
1114 struct smbXsrv_session_global0
*global
= NULL
;
1115 struct smbXsrv_channel_global0
*channels
= NULL
;
1118 if (table
->local
.num_sessions
>= table
->local
.max_sessions
) {
1119 return NT_STATUS_INSUFFICIENT_RESOURCES
;
1122 session
= talloc_zero(table
, struct smbXsrv_session
);
1123 if (session
== NULL
) {
1124 return NT_STATUS_NO_MEMORY
;
1126 session
->table
= table
;
1127 session
->idle_time
= now
;
1128 session
->status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
1129 session
->client
= conn
->client
;
1131 status
= smbXsrv_session_global_allocate(table
->global
.db_ctx
,
1134 if (!NT_STATUS_IS_OK(status
)) {
1135 TALLOC_FREE(session
);
1138 session
->global
= global
;
1140 if (conn
->protocol
>= PROTOCOL_SMB2_02
) {
1141 uint64_t id
= global
->session_global_id
;
1142 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
1145 global
->connection_dialect
= conn
->smb2
.server
.dialect
;
1147 global
->session_wire_id
= id
;
1149 status
= smb2srv_tcon_table_init(session
);
1150 if (!NT_STATUS_IS_OK(status
)) {
1151 TALLOC_FREE(session
);
1155 session
->local_id
= global
->session_global_id
;
1157 key
= smbXsrv_session_local_id_to_key(session
->local_id
, key_buf
);
1159 local_rec
= dbwrap_fetch_locked(table
->local
.db_ctx
,
1161 if (local_rec
== NULL
) {
1162 TALLOC_FREE(session
);
1163 return NT_STATUS_NO_MEMORY
;
1166 val
= dbwrap_record_get_value(local_rec
);
1167 if (val
.dsize
!= 0) {
1168 TALLOC_FREE(session
);
1169 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1173 status
= smb1srv_session_local_allocate_id(table
->local
.db_ctx
,
1174 table
->local
.lowest_id
,
1175 table
->local
.highest_id
,
1178 &session
->local_id
);
1179 if (!NT_STATUS_IS_OK(status
)) {
1180 TALLOC_FREE(session
);
1184 global
->session_wire_id
= session
->local_id
;
1187 global
->creation_time
= now
;
1188 global
->expiration_time
= GENSEC_EXPIRE_TIME_INFINITY
;
1190 global
->num_channels
= 1;
1191 channels
= talloc_zero_array(global
,
1192 struct smbXsrv_channel_global0
,
1193 global
->num_channels
);
1194 if (channels
== NULL
) {
1195 TALLOC_FREE(session
);
1196 return NT_STATUS_NO_MEMORY
;
1198 global
->channels
= channels
;
1200 channels
[0].server_id
= messaging_server_id(conn
->msg_ctx
);
1201 channels
[0].local_address
= tsocket_address_string(conn
->local_address
,
1203 if (channels
[0].local_address
== NULL
) {
1204 TALLOC_FREE(session
);
1205 return NT_STATUS_NO_MEMORY
;
1207 channels
[0].remote_address
= tsocket_address_string(conn
->remote_address
,
1209 if (channels
[0].remote_address
== NULL
) {
1210 TALLOC_FREE(session
);
1211 return NT_STATUS_NO_MEMORY
;
1213 channels
[0].remote_name
= talloc_strdup(channels
, conn
->remote_hostname
);
1214 if (channels
[0].remote_name
== NULL
) {
1215 TALLOC_FREE(session
);
1216 return NT_STATUS_NO_MEMORY
;
1218 channels
[0].signing_key
= data_blob_null
;
1219 channels
[0].connection
= conn
;
1222 val
= make_tdb_data((uint8_t const *)&ptr
, sizeof(ptr
));
1223 status
= dbwrap_record_store(local_rec
, val
, TDB_REPLACE
);
1224 TALLOC_FREE(local_rec
);
1225 if (!NT_STATUS_IS_OK(status
)) {
1226 TALLOC_FREE(session
);
1229 table
->local
.num_sessions
+= 1;
1231 talloc_set_destructor(session
, smbXsrv_session_destructor
);
1233 status
= smbXsrv_session_global_store(global
);
1234 if (!NT_STATUS_IS_OK(status
)) {
1235 DEBUG(0,("smbXsrv_session_create: "
1236 "global_id (0x%08x) store failed - %s\n",
1237 session
->global
->session_global_id
,
1238 nt_errstr(status
)));
1239 TALLOC_FREE(session
);
1244 struct smbXsrv_sessionB session_blob
;
1246 ZERO_STRUCT(session_blob
);
1247 session_blob
.version
= SMBXSRV_VERSION_0
;
1248 session_blob
.info
.info0
= session
;
1250 DEBUG(10,("smbXsrv_session_create: global_id (0x%08x) stored\n",
1251 session
->global
->session_global_id
));
1252 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1255 *_session
= session
;
1256 return NT_STATUS_OK
;
1259 NTSTATUS
smbXsrv_session_update(struct smbXsrv_session
*session
)
1261 struct smbXsrv_session_table
*table
= session
->table
;
1263 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
1266 if (session
->global
->db_rec
!= NULL
) {
1267 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1268 "Called with db_rec != NULL'\n",
1269 session
->global
->session_global_id
));
1270 return NT_STATUS_INTERNAL_ERROR
;
1273 key
= smbXsrv_session_global_id_to_key(
1274 session
->global
->session_global_id
,
1277 session
->global
->db_rec
= dbwrap_fetch_locked(table
->global
.db_ctx
,
1278 session
->global
, key
);
1279 if (session
->global
->db_rec
== NULL
) {
1280 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1281 "Failed to lock global key '%s'\n",
1282 session
->global
->session_global_id
,
1283 hex_encode_talloc(talloc_tos(), key
.dptr
,
1285 return NT_STATUS_INTERNAL_DB_ERROR
;
1288 status
= smbXsrv_session_global_store(session
->global
);
1289 if (!NT_STATUS_IS_OK(status
)) {
1290 DEBUG(0,("smbXsrv_session_update: "
1291 "global_id (0x%08x) store failed - %s\n",
1292 session
->global
->session_global_id
,
1293 nt_errstr(status
)));
1298 struct smbXsrv_sessionB session_blob
;
1300 ZERO_STRUCT(session_blob
);
1301 session_blob
.version
= SMBXSRV_VERSION_0
;
1302 session_blob
.info
.info0
= session
;
1304 DEBUG(10,("smbXsrv_session_update: global_id (0x%08x) stored\n",
1305 session
->global
->session_global_id
));
1306 NDR_PRINT_DEBUG(smbXsrv_sessionB
, &session_blob
);
1309 return NT_STATUS_OK
;
1312 NTSTATUS
smbXsrv_session_find_channel(const struct smbXsrv_session
*session
,
1313 const struct smbXsrv_connection
*conn
,
1314 struct smbXsrv_channel_global0
**_c
)
1318 for (i
=0; i
< session
->global
->num_channels
; i
++) {
1319 struct smbXsrv_channel_global0
*c
= &session
->global
->channels
[i
];
1321 if (c
->connection
== conn
) {
1323 return NT_STATUS_OK
;
1327 return NT_STATUS_USER_SESSION_DELETED
;
1330 NTSTATUS
smbXsrv_session_logoff(struct smbXsrv_session
*session
)
1332 struct smbXsrv_session_table
*table
;
1333 struct db_record
*local_rec
= NULL
;
1334 struct db_record
*global_rec
= NULL
;
1335 struct smbd_server_connection
*sconn
= NULL
;
1337 NTSTATUS error
= NT_STATUS_OK
;
1339 if (session
->table
== NULL
) {
1340 return NT_STATUS_OK
;
1343 table
= session
->table
;
1344 session
->table
= NULL
;
1346 sconn
= session
->client
->sconn
;
1347 session
->client
= NULL
;
1348 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1350 global_rec
= session
->global
->db_rec
;
1351 session
->global
->db_rec
= NULL
;
1352 if (global_rec
== NULL
) {
1353 uint8_t key_buf
[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE
];
1356 key
= smbXsrv_session_global_id_to_key(
1357 session
->global
->session_global_id
,
1360 global_rec
= dbwrap_fetch_locked(table
->global
.db_ctx
,
1361 session
->global
, key
);
1362 if (global_rec
== NULL
) {
1363 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1364 "Failed to lock global key '%s'\n",
1365 session
->global
->session_global_id
,
1366 hex_encode_talloc(global_rec
, key
.dptr
,
1368 error
= NT_STATUS_INTERNAL_ERROR
;
1372 if (global_rec
!= NULL
) {
1373 status
= dbwrap_record_delete(global_rec
);
1374 if (!NT_STATUS_IS_OK(status
)) {
1375 TDB_DATA key
= dbwrap_record_get_key(global_rec
);
1377 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1378 "failed to delete global key '%s': %s\n",
1379 session
->global
->session_global_id
,
1380 hex_encode_talloc(global_rec
, key
.dptr
,
1382 nt_errstr(status
)));
1386 TALLOC_FREE(global_rec
);
1388 local_rec
= session
->db_rec
;
1389 if (local_rec
== NULL
) {
1390 uint8_t key_buf
[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE
];
1393 key
= smbXsrv_session_local_id_to_key(session
->local_id
,
1396 local_rec
= dbwrap_fetch_locked(table
->local
.db_ctx
,
1398 if (local_rec
== NULL
) {
1399 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1400 "Failed to lock local key '%s'\n",
1401 session
->global
->session_global_id
,
1402 hex_encode_talloc(local_rec
, key
.dptr
,
1404 error
= NT_STATUS_INTERNAL_ERROR
;
1408 if (local_rec
!= NULL
) {
1409 status
= dbwrap_record_delete(local_rec
);
1410 if (!NT_STATUS_IS_OK(status
)) {
1411 TDB_DATA key
= dbwrap_record_get_key(local_rec
);
1413 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1414 "failed to delete local key '%s': %s\n",
1415 session
->global
->session_global_id
,
1416 hex_encode_talloc(local_rec
, key
.dptr
,
1418 nt_errstr(status
)));
1421 table
->local
.num_sessions
-= 1;
1423 if (session
->db_rec
== NULL
) {
1424 TALLOC_FREE(local_rec
);
1426 session
->db_rec
= NULL
;
1428 if (session
->compat
) {
1429 file_close_user(sconn
, session
->compat
->vuid
);
1432 if (session
->tcon_table
!= NULL
) {
1434 * Note: We only have a tcon_table for SMB2.
1436 status
= smb2srv_tcon_disconnect_all(session
);
1437 if (!NT_STATUS_IS_OK(status
)) {
1438 DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1439 "smb2srv_tcon_disconnect_all() failed: %s\n",
1440 session
->global
->session_global_id
,
1441 nt_errstr(status
)));
1446 if (session
->compat
) {
1447 invalidate_vuid(sconn
, session
->compat
->vuid
);
1448 session
->compat
= NULL
;
1454 struct smbXsrv_session_logoff_all_state
{
1455 NTSTATUS first_status
;
1459 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1460 void *private_data
);
1462 NTSTATUS
smbXsrv_session_logoff_all(struct smbXsrv_connection
*conn
)
1464 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1465 struct smbXsrv_session_logoff_all_state state
;
1469 if (table
== NULL
) {
1470 DEBUG(10, ("smbXsrv_session_logoff_all: "
1471 "empty session_table, nothing to do.\n"));
1472 return NT_STATUS_OK
;
1477 status
= dbwrap_traverse(table
->local
.db_ctx
,
1478 smbXsrv_session_logoff_all_callback
,
1480 if (!NT_STATUS_IS_OK(status
)) {
1481 DEBUG(0, ("smbXsrv_session_logoff_all: "
1482 "dbwrap_traverse() failed: %s\n",
1483 nt_errstr(status
)));
1487 if (!NT_STATUS_IS_OK(state
.first_status
)) {
1488 DEBUG(0, ("smbXsrv_session_logoff_all: "
1489 "count[%d] errors[%d] first[%s]\n",
1490 count
, state
.errors
,
1491 nt_errstr(state
.first_status
)));
1492 return state
.first_status
;
1495 return NT_STATUS_OK
;
1498 static int smbXsrv_session_logoff_all_callback(struct db_record
*local_rec
,
1501 struct smbXsrv_session_logoff_all_state
*state
=
1502 (struct smbXsrv_session_logoff_all_state
*)private_data
;
1505 struct smbXsrv_session
*session
= NULL
;
1506 struct smbXsrv_connection
*xconn
= NULL
;
1509 val
= dbwrap_record_get_value(local_rec
);
1510 if (val
.dsize
!= sizeof(ptr
)) {
1511 status
= NT_STATUS_INTERNAL_ERROR
;
1512 if (NT_STATUS_IS_OK(state
->first_status
)) {
1513 state
->first_status
= status
;
1519 memcpy(&ptr
, val
.dptr
, val
.dsize
);
1520 session
= talloc_get_type_abort(ptr
, struct smbXsrv_session
);
1522 session
->db_rec
= local_rec
;
1524 if (session
->client
!= NULL
) {
1525 xconn
= session
->client
->connections
;
1527 for (; xconn
!= NULL
; xconn
= xconn
->next
) {
1528 struct smbd_smb2_request
*preq
;
1530 for (preq
= xconn
->smb2
.requests
; preq
!= NULL
; preq
= preq
->next
) {
1531 if (preq
->session
!= session
) {
1535 preq
->session
= NULL
;
1537 * If we no longer have a session we can't
1538 * sign or encrypt replies.
1540 preq
->do_signing
= false;
1541 preq
->do_encryption
= false;
1545 status
= smbXsrv_session_logoff(session
);
1546 if (!NT_STATUS_IS_OK(status
)) {
1547 if (NT_STATUS_IS_OK(state
->first_status
)) {
1548 state
->first_status
= status
;
1557 NTSTATUS
smb1srv_session_table_init(struct smbXsrv_connection
*conn
)
1560 * Allow a range from 1..65534 with 65534 values.
1562 return smbXsrv_session_table_init(conn
, 1, UINT16_MAX
- 1,
1566 NTSTATUS
smb1srv_session_lookup(struct smbXsrv_connection
*conn
,
1567 uint16_t vuid
, NTTIME now
,
1568 struct smbXsrv_session
**session
)
1570 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1571 uint32_t local_id
= vuid
;
1573 return smbXsrv_session_local_lookup(table
, local_id
, now
, session
);
1576 NTSTATUS
smb2srv_session_table_init(struct smbXsrv_connection
*conn
)
1579 * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
1581 return smbXsrv_session_table_init(conn
, 1, UINT32_MAX
- 1,
1585 static NTSTATUS
smb2srv_session_lookup_raw(struct smbXsrv_session_table
*table
,
1586 uint64_t session_id
, NTTIME now
,
1587 struct smbXsrv_session
**session
)
1589 uint32_t local_id
= session_id
& UINT32_MAX
;
1590 uint64_t local_zeros
= session_id
& 0xFFFFFFFF00000000LLU
;
1592 if (local_zeros
!= 0) {
1593 return NT_STATUS_USER_SESSION_DELETED
;
1596 return smbXsrv_session_local_lookup(table
, local_id
, now
, session
);
1599 NTSTATUS
smb2srv_session_lookup(struct smbXsrv_connection
*conn
,
1600 uint64_t session_id
, NTTIME now
,
1601 struct smbXsrv_session
**session
)
1603 struct smbXsrv_session_table
*table
= conn
->client
->session_table
;
1604 return smb2srv_session_lookup_raw(table
, session_id
, now
, session
);
1607 struct smbXsrv_session_global_traverse_state
{
1608 int (*fn
)(struct smbXsrv_session_global0
*, void *);
1612 static int smbXsrv_session_global_traverse_fn(struct db_record
*rec
, void *data
)
1615 struct smbXsrv_session_global_traverse_state
*state
=
1616 (struct smbXsrv_session_global_traverse_state
*)data
;
1617 TDB_DATA key
= dbwrap_record_get_key(rec
);
1618 TDB_DATA val
= dbwrap_record_get_value(rec
);
1619 DATA_BLOB blob
= data_blob_const(val
.dptr
, val
.dsize
);
1620 struct smbXsrv_session_globalB global_blob
;
1621 enum ndr_err_code ndr_err
;
1622 TALLOC_CTX
*frame
= talloc_stackframe();
1624 ndr_err
= ndr_pull_struct_blob(&blob
, frame
, &global_blob
,
1625 (ndr_pull_flags_fn_t
)ndr_pull_smbXsrv_session_globalB
);
1626 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1627 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1628 "key '%s' ndr_pull_struct_blob - %s\n",
1629 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1630 ndr_errstr(ndr_err
)));
1634 if (global_blob
.version
!= SMBXSRV_VERSION_0
) {
1635 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1636 "key '%s' unsuported version - %d\n",
1637 hex_encode_talloc(frame
, key
.dptr
, key
.dsize
),
1638 (int)global_blob
.version
));
1642 global_blob
.info
.info0
->db_rec
= rec
;
1643 ret
= state
->fn(global_blob
.info
.info0
, state
->private_data
);
1649 NTSTATUS
smbXsrv_session_global_traverse(
1650 int (*fn
)(struct smbXsrv_session_global0
*, void *),
1656 struct smbXsrv_session_global_traverse_state state
= {
1658 .private_data
= private_data
,
1662 status
= smbXsrv_session_global_init();
1663 if (!NT_STATUS_IS_OK(status
)) {
1665 DEBUG(0, ("Failed to initialize session_global: %s\n",
1666 nt_errstr(status
)));
1670 status
= dbwrap_traverse_read(smbXsrv_session_global_db_ctx
,
1671 smbXsrv_session_global_traverse_fn
,