Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Stefan Metzmacher 2011-2012
5 : Copyright (C) Michael Adam 2012
6 :
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.
11 :
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.
16 :
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/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "system/filesys.h"
23 : #include <tevent.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"
31 : #include "session.h"
32 : #include "auth.h"
33 : #include "auth/gensec/gensec.h"
34 : #include "../lib/tsocket/tsocket.h"
35 : #include "../libcli/security/security.h"
36 : #include "messages.h"
37 : #include "lib/util/util_tdb.h"
38 : #include "librpc/gen_ndr/ndr_smbXsrv.h"
39 : #include "serverid.h"
40 : #include "lib/util/tevent_ntstatus.h"
41 : #include "lib/global_contexts.h"
42 : #include "source3/include/util_tdb.h"
43 :
44 : struct smbXsrv_session_table {
45 : struct {
46 : struct db_context *db_ctx;
47 : uint32_t lowest_id;
48 : uint32_t highest_id;
49 : uint32_t max_sessions;
50 : uint32_t num_sessions;
51 : } local;
52 : struct {
53 : struct db_context *db_ctx;
54 : } global;
55 : };
56 :
57 : static struct db_context *smbXsrv_session_global_db_ctx = NULL;
58 :
59 30730 : NTSTATUS smbXsrv_session_global_init(struct messaging_context *msg_ctx)
60 : {
61 30730 : char *global_path = NULL;
62 30730 : struct db_context *backend = NULL;
63 30730 : struct db_context *db_ctx = NULL;
64 :
65 30730 : if (smbXsrv_session_global_db_ctx != NULL) {
66 30708 : return NT_STATUS_OK;
67 : }
68 :
69 : /*
70 : * This contains secret information like session keys!
71 : */
72 22 : global_path = lock_path(talloc_tos(), "smbXsrv_session_global.tdb");
73 22 : if (global_path == NULL) {
74 0 : return NT_STATUS_NO_MEMORY;
75 : }
76 :
77 22 : backend = db_open(NULL, global_path,
78 : SMBD_VOLATILE_TDB_HASH_SIZE,
79 : SMBD_VOLATILE_TDB_FLAGS,
80 : O_RDWR | O_CREAT, 0600,
81 : DBWRAP_LOCK_ORDER_1,
82 : DBWRAP_FLAG_NONE);
83 22 : TALLOC_FREE(global_path);
84 22 : if (backend == NULL) {
85 0 : NTSTATUS status;
86 :
87 0 : status = map_nt_error_from_unix_common(errno);
88 :
89 0 : return status;
90 : }
91 :
92 22 : db_ctx = db_open_watched(NULL, &backend, global_messaging_context());
93 22 : if (db_ctx == NULL) {
94 0 : TALLOC_FREE(backend);
95 0 : return NT_STATUS_NO_MEMORY;
96 : }
97 :
98 22 : smbXsrv_session_global_db_ctx = db_ctx;
99 :
100 22 : return NT_STATUS_OK;
101 : }
102 :
103 : /*
104 : * NOTE:
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
107 : * values.
108 : *
109 : * TODO: implement string based key
110 : */
111 :
112 : #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
113 :
114 200712 : static TDB_DATA smbXsrv_session_global_id_to_key(uint32_t id,
115 : uint8_t *key_buf)
116 : {
117 4300 : TDB_DATA key;
118 :
119 200712 : RSIVAL(key_buf, 0, id);
120 :
121 200712 : key = make_tdb_data(key_buf, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE);
122 :
123 200712 : return key;
124 : }
125 :
126 : #if 0
127 : static NTSTATUS smbXsrv_session_global_key_to_id(TDB_DATA key, uint32_t *id)
128 : {
129 : if (id == NULL) {
130 : return NT_STATUS_INVALID_PARAMETER;
131 : }
132 :
133 : if (key.dsize != SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE) {
134 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
135 : }
136 :
137 : *id = RIVAL(key.dptr, 0);
138 :
139 : return NT_STATUS_OK;
140 : }
141 : #endif
142 :
143 : #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
144 :
145 3999559 : static TDB_DATA smbXsrv_session_local_id_to_key(uint32_t id,
146 : uint8_t *key_buf)
147 : {
148 36495 : TDB_DATA key;
149 :
150 3999559 : RSIVAL(key_buf, 0, id);
151 :
152 3999559 : key = make_tdb_data(key_buf, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE);
153 :
154 3999559 : return key;
155 : }
156 :
157 0 : static NTSTATUS smbXsrv_session_local_key_to_id(TDB_DATA key, uint32_t *id)
158 : {
159 0 : if (id == NULL) {
160 0 : return NT_STATUS_INVALID_PARAMETER;
161 : }
162 :
163 0 : if (key.dsize != SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE) {
164 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
165 : }
166 :
167 0 : *id = RIVAL(key.dptr, 0);
168 :
169 0 : return NT_STATUS_OK;
170 : }
171 :
172 200712 : static struct db_record *smbXsrv_session_global_fetch_locked(
173 : struct db_context *db,
174 : uint32_t id,
175 : TALLOC_CTX *mem_ctx)
176 : {
177 4300 : TDB_DATA key;
178 4300 : uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE];
179 200712 : struct db_record *rec = NULL;
180 :
181 200712 : key = smbXsrv_session_global_id_to_key(id, key_buf);
182 :
183 200712 : rec = dbwrap_fetch_locked(db, mem_ctx, key);
184 :
185 200712 : if (rec == NULL) {
186 0 : DBG_DEBUG("Failed to lock global id 0x%08x, key '%s'\n", id,
187 : tdb_data_dbg(key));
188 : }
189 :
190 200712 : return rec;
191 : }
192 :
193 37670 : static struct db_record *smbXsrv_session_local_fetch_locked(
194 : struct db_context *db,
195 : uint32_t id,
196 : TALLOC_CTX *mem_ctx)
197 : {
198 781 : TDB_DATA key;
199 781 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
200 37670 : struct db_record *rec = NULL;
201 :
202 37670 : key = smbXsrv_session_local_id_to_key(id, key_buf);
203 :
204 37670 : rec = dbwrap_fetch_locked(db, mem_ctx, key);
205 :
206 37670 : if (rec == NULL) {
207 0 : DBG_DEBUG("Failed to lock local id 0x%08x, key '%s'\n", id,
208 : tdb_data_dbg(key));
209 : }
210 :
211 37670 : return rec;
212 : }
213 :
214 : static void smbXsrv_session_close_loop(struct tevent_req *subreq);
215 :
216 30688 : static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn,
217 : uint32_t lowest_id,
218 : uint32_t highest_id,
219 : uint32_t max_sessions)
220 : {
221 30688 : struct smbXsrv_client *client = conn->client;
222 834 : struct smbXsrv_session_table *table;
223 834 : NTSTATUS status;
224 834 : struct tevent_req *subreq;
225 834 : uint64_t max_range;
226 :
227 30688 : if (lowest_id > highest_id) {
228 0 : return NT_STATUS_INTERNAL_ERROR;
229 : }
230 :
231 30688 : max_range = highest_id;
232 30688 : max_range -= lowest_id;
233 30688 : max_range += 1;
234 :
235 30688 : if (max_sessions > max_range) {
236 0 : return NT_STATUS_INTERNAL_ERROR;
237 : }
238 :
239 30688 : table = talloc_zero(client, struct smbXsrv_session_table);
240 30688 : if (table == NULL) {
241 0 : return NT_STATUS_NO_MEMORY;
242 : }
243 :
244 30688 : table->local.db_ctx = db_open_rbt(table);
245 30688 : if (table->local.db_ctx == NULL) {
246 0 : TALLOC_FREE(table);
247 0 : return NT_STATUS_NO_MEMORY;
248 : }
249 30688 : table->local.lowest_id = lowest_id;
250 30688 : table->local.highest_id = highest_id;
251 30688 : table->local.max_sessions = max_sessions;
252 :
253 30688 : status = smbXsrv_session_global_init(client->msg_ctx);
254 30688 : if (!NT_STATUS_IS_OK(status)) {
255 0 : TALLOC_FREE(table);
256 0 : return status;
257 : }
258 :
259 30688 : table->global.db_ctx = smbXsrv_session_global_db_ctx;
260 :
261 30688 : subreq = messaging_read_send(table,
262 : client->raw_ev_ctx,
263 : client->msg_ctx,
264 : MSG_SMBXSRV_SESSION_CLOSE);
265 30688 : if (subreq == NULL) {
266 0 : TALLOC_FREE(table);
267 0 : return NT_STATUS_NO_MEMORY;
268 : }
269 30688 : tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
270 :
271 30688 : client->session_table = table;
272 30688 : return NT_STATUS_OK;
273 : }
274 :
275 : static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq);
276 :
277 54 : static void smbXsrv_session_close_loop(struct tevent_req *subreq)
278 : {
279 4 : struct smbXsrv_client *client =
280 54 : tevent_req_callback_data(subreq,
281 : struct smbXsrv_client);
282 54 : struct smbXsrv_session_table *table = client->session_table;
283 4 : int ret;
284 54 : struct messaging_rec *rec = NULL;
285 4 : struct smbXsrv_session_closeB close_blob;
286 4 : enum ndr_err_code ndr_err;
287 54 : struct smbXsrv_session_close0 *close_info0 = NULL;
288 54 : struct smbXsrv_session *session = NULL;
289 4 : NTSTATUS status;
290 54 : struct timeval tv = timeval_current();
291 54 : NTTIME now = timeval_to_nttime(&tv);
292 :
293 54 : ret = messaging_read_recv(subreq, talloc_tos(), &rec);
294 54 : TALLOC_FREE(subreq);
295 54 : if (ret != 0) {
296 0 : goto next;
297 : }
298 :
299 54 : ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &close_blob,
300 : (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_closeB);
301 54 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
302 0 : status = ndr_map_error2ntstatus(ndr_err);
303 0 : DBG_WARNING("smbXsrv_session_close_loop: "
304 : "ndr_pull_struct_blob - %s\n",
305 : nt_errstr(status));
306 0 : goto next;
307 : }
308 :
309 54 : DBG_DEBUG("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n");
310 54 : if (DEBUGLVL(DBGLVL_DEBUG)) {
311 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
312 : }
313 :
314 54 : if (close_blob.version != SMBXSRV_VERSION_0) {
315 0 : DBG_ERR("smbXsrv_session_close_loop: "
316 : "ignore invalid version %u\n", close_blob.version);
317 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
318 0 : goto next;
319 : }
320 :
321 54 : close_info0 = close_blob.info.info0;
322 54 : if (close_info0 == NULL) {
323 0 : DBG_ERR("smbXsrv_session_close_loop: "
324 : "ignore NULL info %u\n", close_blob.version);
325 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
326 0 : goto next;
327 : }
328 :
329 54 : status = smb2srv_session_lookup_client(client,
330 : close_info0->old_session_wire_id,
331 : now, &session);
332 54 : if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
333 0 : DBG_INFO("smbXsrv_session_close_loop: "
334 : "old_session_wire_id %llu not found\n",
335 : (unsigned long long)close_info0->old_session_wire_id);
336 0 : if (DEBUGLVL(DBGLVL_INFO)) {
337 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
338 : }
339 0 : goto next;
340 : }
341 54 : if (!NT_STATUS_IS_OK(status) &&
342 0 : !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
343 0 : !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
344 0 : DBG_WARNING("smbXsrv_session_close_loop: "
345 : "old_session_wire_id %llu - %s\n",
346 : (unsigned long long)close_info0->old_session_wire_id,
347 : nt_errstr(status));
348 0 : if (DEBUGLVL(DBGLVL_WARNING)) {
349 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
350 : }
351 0 : goto next;
352 : }
353 :
354 54 : if (session->global->session_global_id != close_info0->old_session_global_id) {
355 0 : DBG_WARNING("smbXsrv_session_close_loop: "
356 : "old_session_wire_id %llu - global %u != %u\n",
357 : (unsigned long long)close_info0->old_session_wire_id,
358 : session->global->session_global_id,
359 : close_info0->old_session_global_id);
360 0 : if (DEBUGLVL(DBGLVL_WARNING)) {
361 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
362 : }
363 0 : goto next;
364 : }
365 :
366 54 : if (session->global->creation_time != close_info0->old_creation_time) {
367 0 : DBG_WARNING("smbXsrv_session_close_loop: "
368 : "old_session_wire_id %llu - "
369 : "creation %s (%llu) != %s (%llu)\n",
370 : (unsigned long long)close_info0->old_session_wire_id,
371 : nt_time_string(rec, session->global->creation_time),
372 : (unsigned long long)session->global->creation_time,
373 : nt_time_string(rec, close_info0->old_creation_time),
374 : (unsigned long long)close_info0->old_creation_time);
375 0 : if (DEBUGLVL(DBGLVL_WARNING)) {
376 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
377 : }
378 0 : goto next;
379 : }
380 :
381 54 : subreq = smb2srv_session_shutdown_send(session, client->raw_ev_ctx,
382 : session, NULL);
383 54 : if (subreq == NULL) {
384 0 : status = NT_STATUS_NO_MEMORY;
385 0 : DBG_ERR("smbXsrv_session_close_loop: "
386 : "smb2srv_session_shutdown_send(%llu) failed: %s\n",
387 : (unsigned long long)session->global->session_wire_id,
388 : nt_errstr(status));
389 0 : if (DEBUGLVL(DBGLVL_WARNING)) {
390 0 : NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
391 : }
392 0 : goto next;
393 : }
394 54 : tevent_req_set_callback(subreq,
395 : smbXsrv_session_close_shutdown_done,
396 : session);
397 :
398 54 : next:
399 54 : TALLOC_FREE(rec);
400 :
401 54 : subreq = messaging_read_send(table,
402 : client->raw_ev_ctx,
403 : client->msg_ctx,
404 : MSG_SMBXSRV_SESSION_CLOSE);
405 54 : if (subreq == NULL) {
406 0 : const char *r;
407 0 : r = "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
408 0 : exit_server_cleanly(r);
409 : return;
410 : }
411 54 : tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
412 : }
413 :
414 54 : static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq)
415 : {
416 4 : struct smbXsrv_session *session =
417 54 : tevent_req_callback_data(subreq,
418 : struct smbXsrv_session);
419 4 : NTSTATUS status;
420 :
421 54 : status = smb2srv_session_shutdown_recv(subreq);
422 54 : TALLOC_FREE(subreq);
423 54 : if (!NT_STATUS_IS_OK(status)) {
424 0 : DBG_ERR("smbXsrv_session_close_loop: "
425 : "smb2srv_session_shutdown_recv(%llu) failed: %s\n",
426 : (unsigned long long)session->global->session_wire_id,
427 : nt_errstr(status));
428 : }
429 :
430 54 : status = smbXsrv_session_logoff(session);
431 54 : if (!NT_STATUS_IS_OK(status)) {
432 0 : DBG_ERR("smbXsrv_session_close_loop: "
433 : "smbXsrv_session_logoff(%llu) failed: %s\n",
434 : (unsigned long long)session->global->session_wire_id,
435 : nt_errstr(status));
436 : }
437 :
438 54 : TALLOC_FREE(session);
439 54 : }
440 :
441 : struct smb1srv_session_local_allocate_state {
442 : const uint32_t lowest_id;
443 : const uint32_t highest_id;
444 : uint32_t last_id;
445 : uint32_t useable_id;
446 : NTSTATUS status;
447 : };
448 :
449 0 : static int smb1srv_session_local_allocate_traverse(struct db_record *rec,
450 : void *private_data)
451 : {
452 0 : struct smb1srv_session_local_allocate_state *state =
453 : (struct smb1srv_session_local_allocate_state *)private_data;
454 0 : TDB_DATA key = dbwrap_record_get_key(rec);
455 0 : uint32_t id = 0;
456 0 : NTSTATUS status;
457 :
458 0 : status = smbXsrv_session_local_key_to_id(key, &id);
459 0 : if (!NT_STATUS_IS_OK(status)) {
460 0 : state->status = status;
461 0 : return -1;
462 : }
463 :
464 0 : if (id <= state->last_id) {
465 0 : state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
466 0 : return -1;
467 : }
468 0 : state->last_id = id;
469 :
470 0 : if (id > state->useable_id) {
471 0 : state->status = NT_STATUS_OK;
472 0 : return -1;
473 : }
474 :
475 0 : if (state->useable_id == state->highest_id) {
476 0 : state->status = NT_STATUS_INSUFFICIENT_RESOURCES;
477 0 : return -1;
478 : }
479 :
480 0 : state->useable_id +=1;
481 0 : return 0;
482 : }
483 :
484 7622 : static NTSTATUS smb1srv_session_local_allocate_id(struct db_context *db,
485 : uint32_t lowest_id,
486 : uint32_t highest_id,
487 : TALLOC_CTX *mem_ctx,
488 : struct db_record **_rec,
489 : uint32_t *_id)
490 : {
491 7622 : struct smb1srv_session_local_allocate_state state = {
492 : .lowest_id = lowest_id,
493 : .highest_id = highest_id,
494 : .last_id = 0,
495 : .useable_id = lowest_id,
496 : .status = NT_STATUS_INTERNAL_ERROR,
497 : };
498 133 : uint32_t i;
499 133 : uint32_t range;
500 133 : NTSTATUS status;
501 7622 : int count = 0;
502 :
503 7622 : *_rec = NULL;
504 7622 : *_id = 0;
505 :
506 7622 : if (lowest_id > highest_id) {
507 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
508 : }
509 :
510 : /*
511 : * first we try randomly
512 : */
513 7622 : range = (highest_id - lowest_id) + 1;
514 :
515 7622 : for (i = 0; i < (range / 2); i++) {
516 133 : uint32_t id;
517 133 : TDB_DATA val;
518 7622 : struct db_record *rec = NULL;
519 :
520 7622 : id = generate_random() % range;
521 7622 : id += lowest_id;
522 :
523 7622 : if (id < lowest_id) {
524 0 : id = lowest_id;
525 : }
526 7622 : if (id > highest_id) {
527 0 : id = highest_id;
528 : }
529 :
530 7622 : rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
531 7622 : if (rec == NULL) {
532 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
533 : }
534 :
535 7622 : val = dbwrap_record_get_value(rec);
536 7622 : if (val.dsize != 0) {
537 0 : TALLOC_FREE(rec);
538 0 : continue;
539 : }
540 :
541 7622 : *_rec = rec;
542 7622 : *_id = id;
543 7622 : return NT_STATUS_OK;
544 : }
545 :
546 : /*
547 : * if the range is almost full,
548 : * we traverse the whole table
549 : * (this relies on sorted behavior of dbwrap_rbt)
550 : */
551 0 : status = dbwrap_traverse_read(db, smb1srv_session_local_allocate_traverse,
552 : &state, &count);
553 0 : if (NT_STATUS_IS_OK(status)) {
554 0 : if (NT_STATUS_IS_OK(state.status)) {
555 0 : return NT_STATUS_INTERNAL_ERROR;
556 : }
557 :
558 0 : if (!NT_STATUS_EQUAL(state.status, NT_STATUS_INTERNAL_ERROR)) {
559 0 : return state.status;
560 : }
561 :
562 0 : if (state.useable_id <= state.highest_id) {
563 0 : state.status = NT_STATUS_OK;
564 : } else {
565 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
566 : }
567 0 : } else if (!NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_CORRUPTION)) {
568 : /*
569 : * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
570 : *
571 : * If we get anything else it is an error, because it
572 : * means we did not manage to find a free slot in
573 : * the db.
574 : */
575 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
576 : }
577 :
578 0 : if (NT_STATUS_IS_OK(state.status)) {
579 0 : uint32_t id;
580 0 : TDB_DATA val;
581 0 : struct db_record *rec = NULL;
582 :
583 0 : id = state.useable_id;
584 :
585 0 : rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
586 0 : if (rec == NULL) {
587 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
588 : }
589 :
590 0 : val = dbwrap_record_get_value(rec);
591 0 : if (val.dsize != 0) {
592 0 : TALLOC_FREE(rec);
593 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
594 : }
595 :
596 0 : *_rec = rec;
597 0 : *_id = id;
598 0 : return NT_STATUS_OK;
599 : }
600 :
601 0 : return state.status;
602 : }
603 :
604 : struct smbXsrv_session_local_fetch_state {
605 : struct smbXsrv_session *session;
606 : NTSTATUS status;
607 : };
608 :
609 3960815 : static void smbXsrv_session_local_fetch_parser(TDB_DATA key, TDB_DATA data,
610 : void *private_data)
611 : {
612 3960815 : struct smbXsrv_session_local_fetch_state *state =
613 : (struct smbXsrv_session_local_fetch_state *)private_data;
614 35548 : void *ptr;
615 :
616 3960815 : if (data.dsize != sizeof(ptr)) {
617 0 : state->status = NT_STATUS_INTERNAL_DB_ERROR;
618 0 : return;
619 : }
620 :
621 3960815 : memcpy(&ptr, data.dptr, data.dsize);
622 3960815 : state->session = talloc_get_type_abort(ptr, struct smbXsrv_session);
623 3960815 : state->status = NT_STATUS_OK;
624 : }
625 :
626 2167619 : static NTSTATUS smbXsrv_session_local_lookup(struct smbXsrv_session_table *table,
627 : /* conn: optional */
628 : struct smbXsrv_connection *conn,
629 : uint32_t session_local_id,
630 : NTTIME now,
631 : struct smbXsrv_session **_session)
632 : {
633 2167619 : struct smbXsrv_session_local_fetch_state state = {
634 : .session = NULL,
635 : .status = NT_STATUS_INTERNAL_ERROR,
636 : };
637 20292 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
638 20292 : TDB_DATA key;
639 20292 : NTSTATUS status;
640 :
641 2167619 : *_session = NULL;
642 :
643 2167619 : if (session_local_id == 0) {
644 83437 : return NT_STATUS_USER_SESSION_DELETED;
645 : }
646 :
647 2084182 : if (table == NULL) {
648 : /* this might happen before the end of negprot */
649 0 : return NT_STATUS_USER_SESSION_DELETED;
650 : }
651 :
652 2084182 : if (table->local.db_ctx == NULL) {
653 0 : return NT_STATUS_INTERNAL_ERROR;
654 : }
655 :
656 2084182 : key = smbXsrv_session_local_id_to_key(session_local_id, key_buf);
657 :
658 2084182 : status = dbwrap_parse_record(table->local.db_ctx, key,
659 : smbXsrv_session_local_fetch_parser,
660 : &state);
661 2084182 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
662 1057 : return NT_STATUS_USER_SESSION_DELETED;
663 2083125 : } else if (!NT_STATUS_IS_OK(status)) {
664 0 : return status;
665 : }
666 2083125 : if (!NT_STATUS_IS_OK(state.status)) {
667 0 : return state.status;
668 : }
669 :
670 2083125 : if (NT_STATUS_EQUAL(state.session->status, NT_STATUS_USER_SESSION_DELETED)) {
671 0 : return NT_STATUS_USER_SESSION_DELETED;
672 : }
673 :
674 : /*
675 : * If a connection is specified check if the session is
676 : * valid on the channel.
677 : */
678 2083125 : if (conn != NULL) {
679 2061778 : struct smbXsrv_channel_global0 *c = NULL;
680 :
681 2061778 : status = smbXsrv_session_find_channel(state.session, conn, &c);
682 2061778 : if (!NT_STATUS_IS_OK(status)) {
683 140 : return status;
684 : }
685 : }
686 :
687 2082985 : state.session->idle_time = now;
688 :
689 2082985 : if (!NT_STATUS_IS_OK(state.session->status)) {
690 32755 : *_session = state.session;
691 32755 : return state.session->status;
692 : }
693 :
694 2050230 : if (now > state.session->global->expiration_time) {
695 49 : state.session->status = NT_STATUS_NETWORK_SESSION_EXPIRED;
696 : }
697 :
698 2050230 : *_session = state.session;
699 2050230 : return state.session->status;
700 : }
701 :
702 33196 : static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0 *global)
703 : {
704 33196 : return 0;
705 : }
706 :
707 : static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
708 : bool *is_free,
709 : bool *was_free,
710 : TALLOC_CTX *mem_ctx,
711 : struct smbXsrv_session_global0 **_g,
712 : uint32_t *pseqnum);
713 :
714 33210 : static NTSTATUS smbXsrv_session_global_allocate(struct db_context *db,
715 : TALLOC_CTX *mem_ctx,
716 : struct smbXsrv_session_global0 **_global)
717 : {
718 760 : uint32_t i;
719 33210 : struct smbXsrv_session_global0 *global = NULL;
720 33210 : uint32_t last_free = 0;
721 33210 : const uint32_t min_tries = 3;
722 :
723 33210 : *_global = NULL;
724 :
725 33210 : global = talloc_zero(mem_ctx, struct smbXsrv_session_global0);
726 33210 : if (global == NULL) {
727 0 : return NT_STATUS_NO_MEMORY;
728 : }
729 33210 : talloc_set_destructor(global, smbXsrv_session_global_destructor);
730 :
731 : /*
732 : * Here we just randomly try the whole 32-bit space
733 : *
734 : * We use just 32-bit, because we want to reuse the
735 : * ID for SRVSVC.
736 : */
737 33970 : for (i = 0; i < UINT32_MAX; i++) {
738 33210 : bool is_free = false;
739 33210 : bool was_free = false;
740 760 : uint32_t id;
741 :
742 33210 : if (i >= min_tries && last_free != 0) {
743 0 : id = last_free;
744 : } else {
745 33210 : id = generate_random();
746 : }
747 33210 : if (id == 0) {
748 0 : id++;
749 : }
750 33210 : if (id == UINT32_MAX) {
751 0 : id--;
752 : }
753 :
754 33210 : global->db_rec = smbXsrv_session_global_fetch_locked(db, id,
755 : mem_ctx);
756 33210 : if (global->db_rec == NULL) {
757 0 : talloc_free(global);
758 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
759 : }
760 :
761 33210 : smbXsrv_session_global_verify_record(global->db_rec,
762 : &is_free,
763 : &was_free,
764 : NULL, NULL, NULL);
765 :
766 33210 : if (!is_free) {
767 0 : TALLOC_FREE(global->db_rec);
768 0 : continue;
769 : }
770 :
771 33210 : if (!was_free && i < min_tries) {
772 : /*
773 : * The session_id is free now,
774 : * but was not free before.
775 : *
776 : * This happens if a smbd crashed
777 : * and did not cleanup the record.
778 : *
779 : * If this is one of our first tries,
780 : * then we try to find a real free one.
781 : */
782 0 : if (last_free == 0) {
783 0 : last_free = id;
784 : }
785 0 : TALLOC_FREE(global->db_rec);
786 0 : continue;
787 : }
788 :
789 33210 : global->session_global_id = id;
790 :
791 33210 : *_global = global;
792 33210 : return NT_STATUS_OK;
793 : }
794 :
795 : /* should not be reached */
796 0 : talloc_free(global);
797 0 : return NT_STATUS_INTERNAL_ERROR;
798 : }
799 :
800 34535 : static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
801 : bool *is_free,
802 : bool *was_free,
803 : TALLOC_CTX *mem_ctx,
804 : struct smbXsrv_session_global0 **_g,
805 : uint32_t *pseqnum)
806 : {
807 973 : TDB_DATA key;
808 973 : TDB_DATA val;
809 973 : DATA_BLOB blob;
810 973 : struct smbXsrv_session_globalB global_blob;
811 973 : enum ndr_err_code ndr_err;
812 34535 : struct smbXsrv_session_global0 *global = NULL;
813 973 : bool exists;
814 34535 : TALLOC_CTX *frame = talloc_stackframe();
815 :
816 34535 : *is_free = false;
817 :
818 34535 : if (was_free) {
819 33210 : *was_free = false;
820 : }
821 34535 : if (_g) {
822 1325 : *_g = NULL;
823 : }
824 34535 : if (pseqnum) {
825 158 : *pseqnum = 0;
826 : }
827 :
828 34535 : key = dbwrap_record_get_key(db_rec);
829 :
830 34535 : val = dbwrap_record_get_value(db_rec);
831 34535 : if (val.dsize == 0) {
832 33322 : TALLOC_FREE(frame);
833 33322 : *is_free = true;
834 33322 : if (was_free) {
835 33210 : *was_free = true;
836 : }
837 33322 : return;
838 : }
839 :
840 1213 : blob = data_blob_const(val.dptr, val.dsize);
841 :
842 1213 : ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
843 : (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
844 1213 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
845 0 : NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
846 0 : DBG_WARNING("smbXsrv_session_global_verify_record: "
847 : "key '%s' ndr_pull_struct_blob - %s\n",
848 : tdb_data_dbg(key),
849 : nt_errstr(status));
850 0 : TALLOC_FREE(frame);
851 0 : *is_free = true;
852 0 : if (was_free) {
853 0 : *was_free = true;
854 : }
855 0 : return;
856 : }
857 :
858 1213 : DBG_DEBUG("smbXsrv_session_global_verify_record\n");
859 1213 : if (DEBUGLVL(DBGLVL_DEBUG)) {
860 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
861 : }
862 :
863 1213 : if (global_blob.version != SMBXSRV_VERSION_0) {
864 0 : DBG_ERR("smbXsrv_session_global_verify_record: "
865 : "key '%s' use unsupported version %u\n",
866 : tdb_data_dbg(key),
867 : global_blob.version);
868 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
869 0 : TALLOC_FREE(frame);
870 0 : *is_free = true;
871 0 : if (was_free) {
872 0 : *was_free = true;
873 : }
874 0 : return;
875 : }
876 :
877 1213 : global = global_blob.info.info0;
878 :
879 : #define __BLOB_KEEP_SECRET(__blob) do { \
880 : if ((__blob).length != 0) { \
881 : talloc_keep_secret((__blob).data); \
882 : } \
883 : } while(0)
884 : {
885 209 : uint32_t i;
886 1213 : __BLOB_KEEP_SECRET(global->application_key_blob);
887 1213 : __BLOB_KEEP_SECRET(global->signing_key_blob);
888 1213 : __BLOB_KEEP_SECRET(global->encryption_key_blob);
889 1213 : __BLOB_KEEP_SECRET(global->decryption_key_blob);
890 2434 : for (i = 0; i < global->num_channels; i++) {
891 1221 : __BLOB_KEEP_SECRET(global->channels[i].signing_key_blob);
892 : }
893 : }
894 : #undef __BLOB_KEEP_SECRET
895 :
896 1213 : exists = serverid_exists(&global->channels[0].server_id);
897 1213 : if (!exists) {
898 0 : struct server_id_buf idbuf;
899 0 : DBG_NOTICE("smbXsrv_session_global_verify_record: "
900 : "key '%s' server_id %s does not exist.\n",
901 : tdb_data_dbg(key),
902 : server_id_str_buf(global->channels[0].server_id,
903 : &idbuf));
904 0 : if (DEBUGLVL(DBGLVL_NOTICE)) {
905 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
906 : }
907 0 : TALLOC_FREE(frame);
908 0 : dbwrap_record_delete(db_rec);
909 0 : *is_free = true;
910 0 : return;
911 : }
912 :
913 1213 : if (_g) {
914 1213 : *_g = talloc_move(mem_ctx, &global);
915 : }
916 1213 : if (pseqnum) {
917 56 : *pseqnum = global_blob.seqnum;
918 : }
919 1213 : TALLOC_FREE(frame);
920 : }
921 :
922 166191 : static NTSTATUS smbXsrv_session_global_store(struct smbXsrv_session_global0 *global)
923 : {
924 3327 : struct smbXsrv_session_globalB global_blob;
925 166191 : DATA_BLOB blob = data_blob_null;
926 3327 : TDB_DATA key;
927 3327 : TDB_DATA val;
928 3327 : NTSTATUS status;
929 3327 : enum ndr_err_code ndr_err;
930 :
931 : /*
932 : * TODO: if we use other versions than '0'
933 : * we would add glue code here, that would be able to
934 : * store the information in the old format.
935 : */
936 :
937 166191 : if (global->db_rec == NULL) {
938 0 : return NT_STATUS_INTERNAL_ERROR;
939 : }
940 :
941 166191 : key = dbwrap_record_get_key(global->db_rec);
942 166191 : val = dbwrap_record_get_value(global->db_rec);
943 :
944 166191 : ZERO_STRUCT(global_blob);
945 166191 : global_blob.version = smbXsrv_version_global_current();
946 166191 : if (val.dsize >= 8) {
947 132981 : global_blob.seqnum = IVAL(val.dptr, 4);
948 : }
949 166191 : global_blob.seqnum += 1;
950 166191 : global_blob.info.info0 = global;
951 :
952 166191 : ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
953 : (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_globalB);
954 166191 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
955 0 : status = ndr_map_error2ntstatus(ndr_err);
956 0 : DBG_WARNING("smbXsrv_session_global_store: key '%s' ndr_push - %s\n",
957 : tdb_data_dbg(key),
958 : nt_errstr(status));
959 0 : TALLOC_FREE(global->db_rec);
960 0 : return status;
961 : }
962 :
963 166191 : val = make_tdb_data(blob.data, blob.length);
964 166191 : status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
965 166191 : if (!NT_STATUS_IS_OK(status)) {
966 0 : DBG_WARNING("smbXsrv_session_global_store: key '%s' store - %s\n",
967 : tdb_data_dbg(key),
968 : nt_errstr(status));
969 0 : TALLOC_FREE(global->db_rec);
970 0 : return status;
971 : }
972 :
973 166191 : if (DEBUGLVL(DBGLVL_DEBUG)) {
974 0 : DBG_DEBUG("smbXsrv_session_global_store: key '%s' stored\n",
975 : tdb_data_dbg(key));
976 0 : NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
977 : }
978 :
979 166191 : TALLOC_FREE(global->db_rec);
980 :
981 166191 : return NT_STATUS_OK;
982 : }
983 :
984 : struct smb2srv_session_close_previous_state {
985 : struct tevent_context *ev;
986 : struct smbXsrv_connection *connection;
987 : struct dom_sid *current_sid;
988 : uint64_t previous_session_id;
989 : uint64_t current_session_id;
990 : struct db_record *db_rec;
991 : uint64_t watch_instance;
992 : uint32_t last_seqnum;
993 : };
994 :
995 204 : static void smb2srv_session_close_previous_cleanup(struct tevent_req *req,
996 : enum tevent_req_state req_state)
997 : {
998 8 : struct smb2srv_session_close_previous_state *state =
999 204 : tevent_req_data(req,
1000 : struct smb2srv_session_close_previous_state);
1001 :
1002 204 : if (state->db_rec != NULL) {
1003 102 : dbwrap_watched_watch_remove_instance(state->db_rec,
1004 : state->watch_instance);
1005 102 : state->watch_instance = 0;
1006 102 : TALLOC_FREE(state->db_rec);
1007 : }
1008 204 : }
1009 :
1010 : static void smb2srv_session_close_previous_check(struct tevent_req *req);
1011 : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq);
1012 :
1013 102 : struct tevent_req *smb2srv_session_close_previous_send(TALLOC_CTX *mem_ctx,
1014 : struct tevent_context *ev,
1015 : struct smbXsrv_connection *conn,
1016 : struct auth_session_info *session_info,
1017 : uint64_t previous_session_id,
1018 : uint64_t current_session_id)
1019 : {
1020 4 : struct tevent_req *req;
1021 4 : struct smb2srv_session_close_previous_state *state;
1022 102 : uint32_t global_id = previous_session_id & UINT32_MAX;
1023 102 : uint64_t global_zeros = previous_session_id & 0xFFFFFFFF00000000LLU;
1024 102 : struct smbXsrv_session_table *table = conn->client->session_table;
1025 102 : struct security_token *current_token = NULL;
1026 :
1027 102 : req = tevent_req_create(mem_ctx, &state,
1028 : struct smb2srv_session_close_previous_state);
1029 102 : if (req == NULL) {
1030 0 : return NULL;
1031 : }
1032 102 : state->ev = ev;
1033 102 : state->connection = conn;
1034 102 : state->previous_session_id = previous_session_id;
1035 102 : state->current_session_id = current_session_id;
1036 :
1037 102 : tevent_req_set_cleanup_fn(req, smb2srv_session_close_previous_cleanup);
1038 :
1039 102 : if (global_zeros != 0) {
1040 0 : tevent_req_done(req);
1041 0 : return tevent_req_post(req, ev);
1042 : }
1043 :
1044 102 : if (session_info == NULL) {
1045 0 : tevent_req_done(req);
1046 0 : return tevent_req_post(req, ev);
1047 : }
1048 102 : current_token = session_info->security_token;
1049 :
1050 102 : if (current_token->num_sids > PRIMARY_USER_SID_INDEX) {
1051 102 : state->current_sid = ¤t_token->sids[PRIMARY_USER_SID_INDEX];
1052 : }
1053 :
1054 102 : if (state->current_sid == NULL) {
1055 0 : tevent_req_done(req);
1056 0 : return tevent_req_post(req, ev);
1057 : }
1058 :
1059 102 : if (!security_token_has_nt_authenticated_users(current_token)) {
1060 : /* TODO */
1061 0 : tevent_req_done(req);
1062 0 : return tevent_req_post(req, ev);
1063 : }
1064 :
1065 102 : state->db_rec = smbXsrv_session_global_fetch_locked(
1066 : table->global.db_ctx,
1067 : global_id,
1068 : state /* TALLOC_CTX */);
1069 102 : if (state->db_rec == NULL) {
1070 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1071 0 : return tevent_req_post(req, ev);
1072 : }
1073 :
1074 102 : smb2srv_session_close_previous_check(req);
1075 102 : if (!tevent_req_is_in_progress(req)) {
1076 46 : return tevent_req_post(req, ev);
1077 : }
1078 :
1079 52 : return req;
1080 : }
1081 :
1082 158 : static void smb2srv_session_close_previous_check(struct tevent_req *req)
1083 : {
1084 8 : struct smb2srv_session_close_previous_state *state =
1085 158 : tevent_req_data(req,
1086 : struct smb2srv_session_close_previous_state);
1087 158 : struct smbXsrv_connection *conn = state->connection;
1088 8 : DATA_BLOB blob;
1089 158 : struct security_token *previous_token = NULL;
1090 158 : struct smbXsrv_session_global0 *global = NULL;
1091 8 : enum ndr_err_code ndr_err;
1092 8 : struct smbXsrv_session_close0 close_info0;
1093 8 : struct smbXsrv_session_closeB close_blob;
1094 158 : struct tevent_req *subreq = NULL;
1095 8 : NTSTATUS status;
1096 158 : bool is_free = false;
1097 158 : uint32_t seqnum = 0;
1098 :
1099 158 : smbXsrv_session_global_verify_record(state->db_rec,
1100 : &is_free,
1101 : NULL,
1102 : state,
1103 : &global,
1104 : &seqnum);
1105 :
1106 158 : if (is_free) {
1107 102 : tevent_req_done(req);
1108 102 : return;
1109 : }
1110 :
1111 56 : if (global->auth_session_info == NULL) {
1112 0 : tevent_req_done(req);
1113 0 : return;
1114 : }
1115 :
1116 56 : previous_token = global->auth_session_info->security_token;
1117 :
1118 56 : if (!security_token_is_sid(previous_token, state->current_sid)) {
1119 0 : tevent_req_done(req);
1120 0 : return;
1121 : }
1122 :
1123 : /*
1124 : * If the record changed, but we are not happy with the change yet,
1125 : * we better remove ourself from the waiter list
1126 : * (most likely the first position)
1127 : * and re-add us at the end of the list.
1128 : *
1129 : * This gives other waiters a change
1130 : * to make progress.
1131 : *
1132 : * Otherwise we'll keep our waiter instance alive,
1133 : * keep waiting (most likely at first position).
1134 : * It means the order of watchers stays fair.
1135 : */
1136 56 : if (state->last_seqnum != seqnum) {
1137 56 : state->last_seqnum = seqnum;
1138 56 : dbwrap_watched_watch_remove_instance(state->db_rec,
1139 : state->watch_instance);
1140 56 : state->watch_instance =
1141 56 : dbwrap_watched_watch_add_instance(state->db_rec);
1142 : }
1143 :
1144 60 : subreq = dbwrap_watched_watch_send(state, state->ev, state->db_rec,
1145 : state->watch_instance,
1146 56 : (struct server_id){0});
1147 56 : if (tevent_req_nomem(subreq, req)) {
1148 0 : return;
1149 : }
1150 56 : tevent_req_set_callback(subreq,
1151 : smb2srv_session_close_previous_modified,
1152 : req);
1153 :
1154 56 : close_info0.old_session_global_id = global->session_global_id;
1155 56 : close_info0.old_session_wire_id = global->session_wire_id;
1156 56 : close_info0.old_creation_time = global->creation_time;
1157 56 : close_info0.new_session_wire_id = state->current_session_id;
1158 :
1159 56 : ZERO_STRUCT(close_blob);
1160 56 : close_blob.version = smbXsrv_version_global_current();
1161 56 : close_blob.info.info0 = &close_info0;
1162 :
1163 56 : ndr_err = ndr_push_struct_blob(&blob, state, &close_blob,
1164 : (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_closeB);
1165 56 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1166 0 : status = ndr_map_error2ntstatus(ndr_err);
1167 0 : DBG_WARNING("smb2srv_session_close_previous_check: "
1168 : "old_session[%llu] new_session[%llu] ndr_push - %s\n",
1169 : (unsigned long long)close_info0.old_session_wire_id,
1170 : (unsigned long long)close_info0.new_session_wire_id,
1171 : nt_errstr(status));
1172 0 : tevent_req_nterror(req, status);
1173 0 : return;
1174 : }
1175 :
1176 56 : status = messaging_send(conn->client->msg_ctx,
1177 56 : global->channels[0].server_id,
1178 : MSG_SMBXSRV_SESSION_CLOSE, &blob);
1179 56 : TALLOC_FREE(global);
1180 56 : if (tevent_req_nterror(req, status)) {
1181 0 : return;
1182 : }
1183 :
1184 56 : TALLOC_FREE(state->db_rec);
1185 52 : return;
1186 : }
1187 :
1188 56 : static void smb2srv_session_close_previous_modified(struct tevent_req *subreq)
1189 : {
1190 4 : struct tevent_req *req =
1191 56 : tevent_req_callback_data(subreq,
1192 : struct tevent_req);
1193 4 : struct smb2srv_session_close_previous_state *state =
1194 56 : tevent_req_data(req,
1195 : struct smb2srv_session_close_previous_state);
1196 4 : uint32_t global_id;
1197 4 : NTSTATUS status;
1198 56 : uint64_t instance = 0;
1199 :
1200 56 : status = dbwrap_watched_watch_recv(subreq, &instance, NULL, NULL);
1201 56 : TALLOC_FREE(subreq);
1202 56 : if (tevent_req_nterror(req, status)) {
1203 0 : return;
1204 : }
1205 :
1206 56 : state->watch_instance = instance;
1207 :
1208 56 : global_id = state->previous_session_id & UINT32_MAX;
1209 :
1210 112 : state->db_rec = smbXsrv_session_global_fetch_locked(
1211 56 : state->connection->client->session_table->global.db_ctx,
1212 : global_id, state /* TALLOC_CTX */);
1213 56 : if (state->db_rec == NULL) {
1214 0 : tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
1215 0 : return;
1216 : }
1217 :
1218 56 : smb2srv_session_close_previous_check(req);
1219 : }
1220 :
1221 102 : NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
1222 : {
1223 4 : NTSTATUS status;
1224 :
1225 102 : if (tevent_req_is_nterror(req, &status)) {
1226 0 : tevent_req_received(req);
1227 0 : return status;
1228 : }
1229 :
1230 102 : tevent_req_received(req);
1231 102 : return NT_STATUS_OK;
1232 : }
1233 :
1234 61932 : static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session)
1235 : {
1236 1499 : NTSTATUS status;
1237 61932 : struct smbXsrv_connection *xconn = NULL;
1238 :
1239 61932 : if (session->client != NULL) {
1240 32927 : xconn = session->client->connections;
1241 : }
1242 :
1243 94912 : for (; xconn != NULL; xconn = xconn->next) {
1244 750 : struct smbd_smb2_request *preq;
1245 :
1246 33037 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1247 57 : if (preq->session != session) {
1248 0 : continue;
1249 : }
1250 :
1251 57 : preq->session = NULL;
1252 : /*
1253 : * If we no longer have a session we can't
1254 : * sign or encrypt replies.
1255 : */
1256 57 : preq->do_signing = false;
1257 57 : preq->do_encryption = false;
1258 57 : preq->preauth = NULL;
1259 : }
1260 : }
1261 :
1262 61932 : status = smbXsrv_session_logoff(session);
1263 61932 : return status;
1264 : }
1265 :
1266 33196 : static int smbXsrv_session_destructor(struct smbXsrv_session *session)
1267 : {
1268 760 : NTSTATUS status;
1269 :
1270 33196 : DBG_DEBUG("destructing session(%llu)\n",
1271 : (unsigned long long)session->global->session_wire_id);
1272 :
1273 33196 : status = smbXsrv_session_clear_and_logoff(session);
1274 33196 : if (!NT_STATUS_IS_OK(status)) {
1275 0 : DBG_ERR("smbXsrv_session_destructor: "
1276 : "smbXsrv_session_logoff() failed: %s\n",
1277 : nt_errstr(status));
1278 : }
1279 :
1280 33196 : TALLOC_FREE(session->global);
1281 :
1282 33196 : return 0;
1283 : }
1284 :
1285 33210 : NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
1286 : NTTIME now,
1287 : struct smbXsrv_session **_session)
1288 : {
1289 33210 : struct smbXsrv_session_table *table = conn->client->session_table;
1290 33210 : struct db_record *local_rec = NULL;
1291 33210 : struct smbXsrv_session *session = NULL;
1292 33210 : void *ptr = NULL;
1293 760 : TDB_DATA val;
1294 33210 : struct smbXsrv_session_global0 *global = NULL;
1295 33210 : struct smbXsrv_channel_global0 *channel = NULL;
1296 760 : NTSTATUS status;
1297 :
1298 33210 : if (table->local.num_sessions >= table->local.max_sessions) {
1299 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1300 : }
1301 :
1302 33210 : session = talloc_zero(table, struct smbXsrv_session);
1303 33210 : if (session == NULL) {
1304 0 : return NT_STATUS_NO_MEMORY;
1305 : }
1306 33210 : session->table = table;
1307 33210 : session->idle_time = now;
1308 33210 : session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
1309 33210 : session->client = conn->client;
1310 33210 : session->homes_snum = -1;
1311 :
1312 33210 : status = smbXsrv_session_global_allocate(table->global.db_ctx,
1313 : session,
1314 : &global);
1315 33210 : if (!NT_STATUS_IS_OK(status)) {
1316 0 : TALLOC_FREE(session);
1317 0 : return status;
1318 : }
1319 33210 : session->global = global;
1320 :
1321 33210 : if (conn->protocol >= PROTOCOL_SMB2_02) {
1322 25588 : uint64_t id = global->session_global_id;
1323 :
1324 25588 : global->connection_dialect = conn->smb2.server.dialect;
1325 25588 : global->client_guid = conn->smb2.client.guid;
1326 :
1327 25588 : global->session_wire_id = id;
1328 :
1329 25588 : status = smb2srv_tcon_table_init(session);
1330 25588 : if (!NT_STATUS_IS_OK(status)) {
1331 0 : TALLOC_FREE(session);
1332 0 : return status;
1333 : }
1334 :
1335 25588 : session->local_id = global->session_global_id;
1336 :
1337 25588 : local_rec = smbXsrv_session_local_fetch_locked(
1338 : table->local.db_ctx,
1339 : session->local_id,
1340 : session /* TALLOC_CTX */);
1341 25588 : if (local_rec == NULL) {
1342 0 : TALLOC_FREE(session);
1343 0 : return NT_STATUS_NO_MEMORY;
1344 : }
1345 :
1346 25588 : val = dbwrap_record_get_value(local_rec);
1347 25588 : if (val.dsize != 0) {
1348 0 : TALLOC_FREE(session);
1349 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1350 : }
1351 : } else {
1352 :
1353 7622 : status = smb1srv_session_local_allocate_id(table->local.db_ctx,
1354 : table->local.lowest_id,
1355 : table->local.highest_id,
1356 : session,
1357 : &local_rec,
1358 : &session->local_id);
1359 7622 : if (!NT_STATUS_IS_OK(status)) {
1360 0 : TALLOC_FREE(session);
1361 0 : return status;
1362 : }
1363 :
1364 7622 : global->session_wire_id = session->local_id;
1365 : }
1366 :
1367 33210 : global->creation_time = now;
1368 33210 : global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1369 :
1370 33210 : status = smbXsrv_session_add_channel(session, conn, now, &channel);
1371 33210 : if (!NT_STATUS_IS_OK(status)) {
1372 0 : TALLOC_FREE(session);
1373 0 : return status;
1374 : }
1375 :
1376 33210 : ptr = session;
1377 33210 : val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
1378 33210 : status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
1379 33210 : TALLOC_FREE(local_rec);
1380 33210 : if (!NT_STATUS_IS_OK(status)) {
1381 0 : TALLOC_FREE(session);
1382 0 : return status;
1383 : }
1384 33210 : table->local.num_sessions += 1;
1385 :
1386 33210 : talloc_set_destructor(session, smbXsrv_session_destructor);
1387 :
1388 33210 : status = smbXsrv_session_global_store(global);
1389 33210 : if (!NT_STATUS_IS_OK(status)) {
1390 0 : DBG_ERR("smbXsrv_session_create: "
1391 : "global_id (0x%08x) store failed - %s\n",
1392 : session->global->session_global_id,
1393 : nt_errstr(status));
1394 0 : TALLOC_FREE(session);
1395 0 : return status;
1396 : }
1397 :
1398 33210 : if (DEBUGLVL(DBGLVL_DEBUG)) {
1399 0 : struct smbXsrv_sessionB session_blob = {
1400 : .version = SMBXSRV_VERSION_0,
1401 : .info.info0 = session,
1402 : };
1403 :
1404 0 : DBG_DEBUG("smbXsrv_session_create: global_id (0x%08x) stored\n",
1405 : session->global->session_global_id);
1406 0 : NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1407 : }
1408 :
1409 33210 : *_session = session;
1410 33210 : return NT_STATUS_OK;
1411 : }
1412 :
1413 34151 : NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
1414 : struct smbXsrv_connection *conn,
1415 : NTTIME now,
1416 : struct smbXsrv_channel_global0 **_c)
1417 : {
1418 34151 : struct smbXsrv_session_global0 *global = session->global;
1419 34151 : struct smbXsrv_channel_global0 *c = NULL;
1420 :
1421 34151 : if (global->num_channels > 31) {
1422 : /*
1423 : * Windows allow up to 32 channels
1424 : */
1425 4 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1426 : }
1427 :
1428 34147 : c = talloc_realloc(global,
1429 : global->channels,
1430 : struct smbXsrv_channel_global0,
1431 : global->num_channels + 1);
1432 34147 : if (c == NULL) {
1433 0 : return NT_STATUS_NO_MEMORY;
1434 : }
1435 34147 : global->channels = c;
1436 :
1437 34147 : c = &global->channels[global->num_channels];
1438 34147 : ZERO_STRUCTP(c);
1439 :
1440 34147 : c->server_id = messaging_server_id(conn->client->msg_ctx);
1441 34147 : c->channel_id = conn->channel_id;
1442 34147 : c->creation_time = now;
1443 68294 : c->local_address = tsocket_address_string(conn->local_address,
1444 34147 : global->channels);
1445 34147 : if (c->local_address == NULL) {
1446 0 : return NT_STATUS_NO_MEMORY;
1447 : }
1448 68294 : c->remote_address = tsocket_address_string(conn->remote_address,
1449 34147 : global->channels);
1450 34147 : if (c->remote_address == NULL) {
1451 0 : return NT_STATUS_NO_MEMORY;
1452 : }
1453 34147 : c->remote_name = talloc_strdup(global->channels,
1454 : conn->remote_hostname);
1455 34147 : if (c->remote_name == NULL) {
1456 0 : return NT_STATUS_NO_MEMORY;
1457 : }
1458 34147 : c->connection = conn;
1459 :
1460 34147 : global->num_channels += 1;
1461 :
1462 34147 : *_c = c;
1463 34147 : return NT_STATUS_OK;
1464 : }
1465 :
1466 132981 : NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session)
1467 : {
1468 132981 : struct smbXsrv_session_table *table = session->table;
1469 2567 : NTSTATUS status;
1470 :
1471 132981 : if (session->global->db_rec != NULL) {
1472 0 : DBG_ERR("smbXsrv_session_update(0x%08x): "
1473 : "Called with db_rec != NULL'\n",
1474 : session->global->session_global_id);
1475 0 : return NT_STATUS_INTERNAL_ERROR;
1476 : }
1477 :
1478 132981 : if (table == NULL) {
1479 0 : DBG_ERR("smbXsrv_session_update(0x%08x): "
1480 : "Called with table == NULL'\n",
1481 : session->global->session_global_id);
1482 0 : return NT_STATUS_INTERNAL_ERROR;
1483 : }
1484 :
1485 263395 : session->global->db_rec = smbXsrv_session_global_fetch_locked(
1486 : table->global.db_ctx,
1487 130414 : session->global->session_global_id,
1488 130414 : session->global /* TALLOC_CTX */);
1489 132981 : if (session->global->db_rec == NULL) {
1490 0 : return NT_STATUS_INTERNAL_DB_ERROR;
1491 : }
1492 :
1493 132981 : status = smbXsrv_session_global_store(session->global);
1494 132981 : if (!NT_STATUS_IS_OK(status)) {
1495 0 : DBG_ERR("smbXsrv_session_update: "
1496 : "global_id (0x%08x) store failed - %s\n",
1497 : session->global->session_global_id,
1498 : nt_errstr(status));
1499 0 : return status;
1500 : }
1501 :
1502 132981 : if (DEBUGLVL(DBGLVL_DEBUG)) {
1503 0 : struct smbXsrv_sessionB session_blob = {
1504 : .version = SMBXSRV_VERSION_0,
1505 : .info.info0 = session,
1506 : };
1507 :
1508 0 : DBG_DEBUG("smbXsrv_session_update: global_id (0x%08x) stored\n",
1509 : session->global->session_global_id);
1510 0 : NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1511 : }
1512 :
1513 132981 : return NT_STATUS_OK;
1514 : }
1515 :
1516 3547207 : NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
1517 : const struct smbXsrv_connection *conn,
1518 : struct smbXsrv_channel_global0 **_c)
1519 : {
1520 37808 : uint32_t i;
1521 :
1522 3631046 : for (i=0; i < session->global->num_channels; i++) {
1523 3624908 : struct smbXsrv_channel_global0 *c = &session->global->channels[i];
1524 :
1525 3624908 : if (c->channel_id != conn->channel_id) {
1526 83839 : continue;
1527 : }
1528 :
1529 3541069 : if (c->connection != conn) {
1530 0 : continue;
1531 : }
1532 :
1533 3541069 : *_c = c;
1534 3541069 : return NT_STATUS_OK;
1535 : }
1536 :
1537 6138 : return NT_STATUS_USER_SESSION_DELETED;
1538 : }
1539 :
1540 96716 : NTSTATUS smbXsrv_session_find_auth(const struct smbXsrv_session *session,
1541 : const struct smbXsrv_connection *conn,
1542 : NTTIME now,
1543 : struct smbXsrv_session_auth0 **_a)
1544 : {
1545 1980 : struct smbXsrv_session_auth0 *a;
1546 :
1547 96716 : for (a = session->pending_auth; a != NULL; a = a->next) {
1548 26158 : if (a->channel_id != conn->channel_id) {
1549 0 : continue;
1550 : }
1551 :
1552 26158 : if (a->connection == conn) {
1553 26158 : if (now != 0) {
1554 26140 : a->idle_time = now;
1555 : }
1556 26158 : *_a = a;
1557 26158 : return NT_STATUS_OK;
1558 : }
1559 : }
1560 :
1561 70558 : return NT_STATUS_USER_SESSION_DELETED;
1562 : }
1563 :
1564 34266 : static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0 *a)
1565 : {
1566 34266 : if (a->session == NULL) {
1567 14 : return 0;
1568 : }
1569 :
1570 34248 : DLIST_REMOVE(a->session->pending_auth, a);
1571 34248 : a->session = NULL;
1572 34248 : return 0;
1573 : }
1574 :
1575 34260 : NTSTATUS smbXsrv_session_create_auth(struct smbXsrv_session *session,
1576 : struct smbXsrv_connection *conn,
1577 : NTTIME now,
1578 : uint8_t in_flags,
1579 : uint8_t in_security_mode,
1580 : struct smbXsrv_session_auth0 **_a)
1581 : {
1582 811 : struct smbXsrv_session_auth0 *a;
1583 811 : NTSTATUS status;
1584 :
1585 34260 : status = smbXsrv_session_find_auth(session, conn, 0, &a);
1586 34260 : if (NT_STATUS_IS_OK(status)) {
1587 0 : return NT_STATUS_INTERNAL_ERROR;
1588 : }
1589 :
1590 34260 : a = talloc_zero(session, struct smbXsrv_session_auth0);
1591 34260 : if (a == NULL) {
1592 0 : return NT_STATUS_NO_MEMORY;
1593 : }
1594 34260 : a->session = session;
1595 34260 : a->connection = conn;
1596 34260 : a->in_flags = in_flags;
1597 34260 : a->in_security_mode = in_security_mode;
1598 34260 : a->creation_time = now;
1599 34260 : a->idle_time = now;
1600 34260 : a->channel_id = conn->channel_id;
1601 :
1602 34260 : if (conn->protocol >= PROTOCOL_SMB3_11) {
1603 24126 : a->preauth = talloc(a, struct smbXsrv_preauth);
1604 24126 : if (a->preauth == NULL) {
1605 0 : TALLOC_FREE(session);
1606 0 : return NT_STATUS_NO_MEMORY;
1607 : }
1608 24126 : *a->preauth = conn->smb2.preauth;
1609 : }
1610 :
1611 34260 : talloc_set_destructor(a, smbXsrv_session_auth0_destructor);
1612 34260 : DLIST_ADD_END(session->pending_auth, a);
1613 :
1614 34260 : *_a = a;
1615 34260 : return NT_STATUS_OK;
1616 : }
1617 :
1618 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq);
1619 :
1620 2056 : NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session,
1621 : struct smbXsrv_connection *xconn)
1622 : {
1623 2056 : struct smbXsrv_session_auth0 *a = NULL;
1624 2056 : struct smbXsrv_channel_global0 *c = NULL;
1625 210 : NTSTATUS status;
1626 2056 : bool need_update = false;
1627 :
1628 2056 : status = smbXsrv_session_find_auth(session, xconn, 0, &a);
1629 2056 : if (!NT_STATUS_IS_OK(status)) {
1630 2038 : a = NULL;
1631 : }
1632 2056 : status = smbXsrv_session_find_channel(session, xconn, &c);
1633 2056 : if (!NT_STATUS_IS_OK(status)) {
1634 1086 : c = NULL;
1635 : }
1636 :
1637 2056 : if (a != NULL) {
1638 18 : smbXsrv_session_auth0_destructor(a);
1639 18 : a->connection = NULL;
1640 18 : need_update = true;
1641 : }
1642 :
1643 2056 : if (c != NULL) {
1644 970 : struct smbXsrv_session_global0 *global = session->global;
1645 24 : ptrdiff_t n;
1646 :
1647 970 : n = (c - global->channels);
1648 970 : if (n >= global->num_channels || n < 0) {
1649 0 : return NT_STATUS_INTERNAL_ERROR;
1650 : }
1651 970 : ARRAY_DEL_ELEMENT(global->channels, n, global->num_channels);
1652 970 : global->num_channels--;
1653 970 : if (global->num_channels == 0) {
1654 44 : struct smbXsrv_client *client = session->client;
1655 44 : struct tevent_queue *xconn_wait_queue =
1656 : xconn->transport.shutdown_wait_queue;
1657 44 : struct tevent_req *subreq = NULL;
1658 :
1659 : /*
1660 : * Let the connection wait until the session is
1661 : * destroyed.
1662 : *
1663 : * We don't set a callback, as we just want to block the
1664 : * wait queue and the talloc_free() of the session will
1665 : * remove the item from the wait queue in order
1666 : * to remove allow the connection to disappear.
1667 : */
1668 44 : if (xconn_wait_queue != NULL) {
1669 44 : subreq = tevent_queue_wait_send(session,
1670 : client->raw_ev_ctx,
1671 : xconn_wait_queue);
1672 44 : if (subreq == NULL) {
1673 0 : status = NT_STATUS_NO_MEMORY;
1674 0 : DBG_ERR("tevent_queue_wait_send() session(%llu) failed: %s\n",
1675 : (unsigned long long)session->global->session_wire_id,
1676 : nt_errstr(status));
1677 0 : return status;
1678 : }
1679 : }
1680 :
1681 : /*
1682 : * This is guaranteed to set
1683 : * session->status = NT_STATUS_USER_SESSION_DELETED
1684 : * even if NULL is returned.
1685 : */
1686 44 : subreq = smb2srv_session_shutdown_send(session,
1687 : client->raw_ev_ctx,
1688 : session,
1689 : NULL);
1690 44 : if (subreq == NULL) {
1691 0 : status = NT_STATUS_NO_MEMORY;
1692 0 : DBG_ERR("smb2srv_session_shutdown_send(%llu) failed: %s\n",
1693 : (unsigned long long)session->global->session_wire_id,
1694 : nt_errstr(status));
1695 0 : return status;
1696 : }
1697 44 : tevent_req_set_callback(subreq,
1698 : smbXsrv_session_remove_channel_done,
1699 : session);
1700 : }
1701 946 : need_update = true;
1702 : }
1703 :
1704 2032 : if (!need_update) {
1705 1086 : return NT_STATUS_OK;
1706 : }
1707 :
1708 970 : return smbXsrv_session_update(session);
1709 : }
1710 :
1711 44 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq)
1712 : {
1713 4 : struct smbXsrv_session *session =
1714 44 : tevent_req_callback_data(subreq,
1715 : struct smbXsrv_session);
1716 4 : NTSTATUS status;
1717 :
1718 44 : status = smb2srv_session_shutdown_recv(subreq);
1719 44 : TALLOC_FREE(subreq);
1720 44 : if (!NT_STATUS_IS_OK(status)) {
1721 0 : DBG_ERR("smb2srv_session_shutdown_recv(%llu) failed: %s\n",
1722 : (unsigned long long)session->global->session_wire_id,
1723 : nt_errstr(status));
1724 : }
1725 :
1726 44 : status = smbXsrv_session_logoff(session);
1727 44 : if (!NT_STATUS_IS_OK(status)) {
1728 0 : DBG_ERR("smbXsrv_session_logoff(%llu) failed: %s\n",
1729 : (unsigned long long)session->global->session_wire_id,
1730 : nt_errstr(status));
1731 : }
1732 :
1733 44 : TALLOC_FREE(session);
1734 44 : }
1735 :
1736 : struct smb2srv_session_shutdown_state {
1737 : struct tevent_queue *wait_queue;
1738 : };
1739 :
1740 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
1741 :
1742 2578 : struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
1743 : struct tevent_context *ev,
1744 : struct smbXsrv_session *session,
1745 : struct smbd_smb2_request *current_req)
1746 : {
1747 21 : struct tevent_req *req;
1748 21 : struct smb2srv_session_shutdown_state *state;
1749 21 : struct tevent_req *subreq;
1750 2578 : struct smbXsrv_connection *xconn = NULL;
1751 2578 : size_t len = 0;
1752 :
1753 : /*
1754 : * Make sure that no new request will be able to use this session.
1755 : */
1756 2578 : session->status = NT_STATUS_USER_SESSION_DELETED;
1757 :
1758 2578 : req = tevent_req_create(mem_ctx, &state,
1759 : struct smb2srv_session_shutdown_state);
1760 2578 : if (req == NULL) {
1761 0 : return NULL;
1762 : }
1763 :
1764 2578 : state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
1765 2578 : if (tevent_req_nomem(state->wait_queue, req)) {
1766 0 : return tevent_req_post(req, ev);
1767 : }
1768 :
1769 5246 : for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
1770 33 : struct smbd_smb2_request *preq;
1771 :
1772 5186 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1773 2518 : if (preq == current_req) {
1774 : /* Can't cancel current request. */
1775 2480 : continue;
1776 : }
1777 38 : if (preq->session != session) {
1778 : /* Request on different session. */
1779 26 : continue;
1780 : }
1781 :
1782 12 : if (preq->subreq != NULL) {
1783 12 : tevent_req_cancel(preq->subreq);
1784 : }
1785 :
1786 : /*
1787 : * Now wait until the request is finished.
1788 : *
1789 : * We don't set a callback, as we just want to block the
1790 : * wait queue and the talloc_free() of the request will
1791 : * remove the item from the wait queue.
1792 : */
1793 12 : subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
1794 12 : if (tevent_req_nomem(subreq, req)) {
1795 0 : return tevent_req_post(req, ev);
1796 : }
1797 : }
1798 : }
1799 :
1800 2578 : len = tevent_queue_length(state->wait_queue);
1801 2578 : if (len == 0) {
1802 2566 : tevent_req_done(req);
1803 2566 : return tevent_req_post(req, ev);
1804 : }
1805 :
1806 : /*
1807 : * Now we add our own waiter to the end of the queue,
1808 : * this way we get notified when all pending requests are finished
1809 : * and send to the socket.
1810 : */
1811 12 : subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
1812 12 : if (tevent_req_nomem(subreq, req)) {
1813 0 : return tevent_req_post(req, ev);
1814 : }
1815 12 : tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
1816 :
1817 12 : return req;
1818 : }
1819 :
1820 12 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
1821 : {
1822 0 : struct tevent_req *req =
1823 12 : tevent_req_callback_data(subreq,
1824 : struct tevent_req);
1825 :
1826 12 : tevent_queue_wait_recv(subreq);
1827 12 : TALLOC_FREE(subreq);
1828 :
1829 12 : tevent_req_done(req);
1830 12 : }
1831 :
1832 2578 : NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
1833 : {
1834 2578 : return tevent_req_simple_recv_ntstatus(req);
1835 : }
1836 :
1837 62201 : NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
1838 : {
1839 1513 : struct smbXsrv_session_table *table;
1840 62201 : struct db_record *local_rec = NULL;
1841 62201 : struct db_record *global_rec = NULL;
1842 62201 : struct smbd_server_connection *sconn = NULL;
1843 1513 : NTSTATUS status;
1844 62201 : NTSTATUS error = NT_STATUS_OK;
1845 :
1846 62201 : if (session->table == NULL) {
1847 29005 : return NT_STATUS_OK;
1848 : }
1849 :
1850 33196 : table = session->table;
1851 33196 : session->table = NULL;
1852 :
1853 33196 : sconn = session->client->sconn;
1854 33196 : session->client = NULL;
1855 33196 : session->status = NT_STATUS_USER_SESSION_DELETED;
1856 :
1857 : /*
1858 : * For SMB2 this is a bit redundant as files are also close
1859 : * below via smb2srv_tcon_disconnect_all() -> ... ->
1860 : * smbXsrv_tcon_disconnect() -> close_cnum() ->
1861 : * file_close_conn().
1862 : */
1863 33196 : file_close_user(sconn, session->global->session_wire_id);
1864 :
1865 33196 : if (session->tcon_table != NULL) {
1866 : /*
1867 : * Note: We only have a tcon_table for SMB2.
1868 : */
1869 25586 : status = smb2srv_tcon_disconnect_all(session);
1870 25586 : if (!NT_STATUS_IS_OK(status)) {
1871 52 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1872 : "smb2srv_tcon_disconnect_all() failed: %s\n",
1873 : session->global->session_global_id,
1874 : nt_errstr(status));
1875 52 : error = status;
1876 : }
1877 : }
1878 :
1879 33196 : invalidate_vuid(sconn, session->global->session_wire_id);
1880 :
1881 33196 : global_rec = session->global->db_rec;
1882 33196 : session->global->db_rec = NULL;
1883 33196 : if (global_rec == NULL) {
1884 33196 : global_rec = smbXsrv_session_global_fetch_locked(
1885 : table->global.db_ctx,
1886 32436 : session->global->session_global_id,
1887 32436 : session->global /* TALLOC_CTX */);
1888 33196 : if (global_rec == NULL) {
1889 0 : error = NT_STATUS_INTERNAL_ERROR;
1890 : }
1891 : }
1892 :
1893 33196 : if (global_rec != NULL) {
1894 33196 : status = dbwrap_record_delete(global_rec);
1895 33196 : if (!NT_STATUS_IS_OK(status)) {
1896 0 : TDB_DATA key = dbwrap_record_get_key(global_rec);
1897 :
1898 0 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1899 : "failed to delete global key '%s': %s\n",
1900 : session->global->session_global_id,
1901 : tdb_data_dbg(key),
1902 : nt_errstr(status));
1903 0 : error = status;
1904 : }
1905 : }
1906 33196 : TALLOC_FREE(global_rec);
1907 :
1908 33196 : local_rec = session->db_rec;
1909 33196 : if (local_rec == NULL) {
1910 4460 : local_rec = smbXsrv_session_local_fetch_locked(
1911 : table->local.db_ctx,
1912 : session->local_id,
1913 : session /* TALLOC_CTX */);
1914 4460 : if (local_rec == NULL) {
1915 0 : error = NT_STATUS_INTERNAL_ERROR;
1916 : }
1917 : }
1918 :
1919 33196 : if (local_rec != NULL) {
1920 33196 : status = dbwrap_record_delete(local_rec);
1921 33196 : if (!NT_STATUS_IS_OK(status)) {
1922 0 : TDB_DATA key = dbwrap_record_get_key(local_rec);
1923 :
1924 0 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1925 : "failed to delete local key '%s': %s\n",
1926 : session->global->session_global_id,
1927 : tdb_data_dbg(key),
1928 : nt_errstr(status));
1929 0 : error = status;
1930 : }
1931 33196 : table->local.num_sessions -= 1;
1932 : }
1933 33196 : if (session->db_rec == NULL) {
1934 4460 : TALLOC_FREE(local_rec);
1935 : }
1936 33196 : session->db_rec = NULL;
1937 :
1938 33196 : return error;
1939 : }
1940 :
1941 : struct smbXsrv_session_logoff_all_state {
1942 : NTSTATUS first_status;
1943 : int errors;
1944 : };
1945 :
1946 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1947 : void *private_data);
1948 :
1949 31366 : NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_client *client)
1950 : {
1951 31366 : struct smbXsrv_session_table *table = client->session_table;
1952 842 : struct smbXsrv_session_logoff_all_state state;
1953 842 : NTSTATUS status;
1954 31366 : int count = 0;
1955 :
1956 31366 : if (table == NULL) {
1957 692 : DBG_DEBUG("smbXsrv_session_logoff_all: "
1958 : "empty session_table, nothing to do.\n");
1959 692 : return NT_STATUS_OK;
1960 : }
1961 :
1962 30674 : ZERO_STRUCT(state);
1963 :
1964 30674 : status = dbwrap_traverse(table->local.db_ctx,
1965 : smbXsrv_session_logoff_all_callback,
1966 : &state, &count);
1967 30674 : if (!NT_STATUS_IS_OK(status)) {
1968 0 : DBG_ERR("smbXsrv_session_logoff_all: "
1969 : "dbwrap_traverse() failed: %s\n",
1970 : nt_errstr(status));
1971 0 : return status;
1972 : }
1973 :
1974 30674 : if (!NT_STATUS_IS_OK(state.first_status)) {
1975 50 : DBG_ERR("smbXsrv_session_logoff_all: "
1976 : "count[%d] errors[%d] first[%s]\n",
1977 : count, state.errors,
1978 : nt_errstr(state.first_status));
1979 50 : return state.first_status;
1980 : }
1981 :
1982 30624 : return NT_STATUS_OK;
1983 : }
1984 :
1985 28736 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1986 : void *private_data)
1987 : {
1988 28736 : struct smbXsrv_session_logoff_all_state *state =
1989 : (struct smbXsrv_session_logoff_all_state *)private_data;
1990 739 : TDB_DATA val;
1991 28736 : void *ptr = NULL;
1992 28736 : struct smbXsrv_session *session = NULL;
1993 739 : NTSTATUS status;
1994 :
1995 28736 : val = dbwrap_record_get_value(local_rec);
1996 28736 : if (val.dsize != sizeof(ptr)) {
1997 0 : status = NT_STATUS_INTERNAL_ERROR;
1998 0 : if (NT_STATUS_IS_OK(state->first_status)) {
1999 0 : state->first_status = status;
2000 : }
2001 0 : state->errors++;
2002 0 : return 0;
2003 : }
2004 :
2005 28736 : memcpy(&ptr, val.dptr, val.dsize);
2006 28736 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2007 :
2008 28736 : session->db_rec = local_rec;
2009 28736 : status = smbXsrv_session_clear_and_logoff(session);
2010 28736 : session->db_rec = NULL;
2011 28736 : if (!NT_STATUS_IS_OK(status)) {
2012 52 : if (NT_STATUS_IS_OK(state->first_status)) {
2013 50 : state->first_status = status;
2014 : }
2015 52 : state->errors++;
2016 52 : return 0;
2017 : }
2018 :
2019 27945 : return 0;
2020 : }
2021 :
2022 : struct smbXsrv_session_local_trav_state {
2023 : NTSTATUS status;
2024 : int (*caller_cb)(struct smbXsrv_session *session,
2025 : void *caller_data);
2026 : void *caller_data;
2027 : };
2028 :
2029 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
2030 : void *private_data);
2031 :
2032 0 : NTSTATUS smbXsrv_session_local_traverse(
2033 : struct smbXsrv_client *client,
2034 : int (*caller_cb)(struct smbXsrv_session *session,
2035 : void *caller_data),
2036 : void *caller_data)
2037 : {
2038 0 : struct smbXsrv_session_table *table = client->session_table;
2039 0 : struct smbXsrv_session_local_trav_state state;
2040 0 : NTSTATUS status;
2041 0 : int count = 0;
2042 :
2043 0 : state = (struct smbXsrv_session_local_trav_state) {
2044 : .status = NT_STATUS_OK,
2045 : .caller_cb = caller_cb,
2046 : .caller_data = caller_data,
2047 : };
2048 :
2049 0 : if (table == NULL) {
2050 0 : DBG_DEBUG("empty session_table, nothing to do.\n");
2051 0 : return NT_STATUS_OK;
2052 : }
2053 :
2054 0 : status = dbwrap_traverse(table->local.db_ctx,
2055 : smbXsrv_session_local_traverse_cb,
2056 : &state,
2057 : &count);
2058 0 : if (!NT_STATUS_IS_OK(status)) {
2059 0 : DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
2060 0 : return status;
2061 : }
2062 0 : if (!NT_STATUS_IS_OK(state.status)) {
2063 0 : DBG_ERR("count[%d] status[%s]\n",
2064 : count, nt_errstr(state.status));
2065 0 : return state.status;
2066 : }
2067 :
2068 0 : return NT_STATUS_OK;
2069 : }
2070 :
2071 0 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
2072 : void *private_data)
2073 : {
2074 0 : struct smbXsrv_session_local_trav_state *state =
2075 : (struct smbXsrv_session_local_trav_state *)private_data;
2076 0 : TDB_DATA val;
2077 0 : void *ptr = NULL;
2078 0 : struct smbXsrv_session *session = NULL;
2079 0 : int ret;
2080 :
2081 0 : val = dbwrap_record_get_value(local_rec);
2082 0 : if (val.dsize != sizeof(ptr)) {
2083 0 : state->status = NT_STATUS_INTERNAL_ERROR;
2084 0 : return -1;
2085 : }
2086 :
2087 0 : memcpy(&ptr, val.dptr, val.dsize);
2088 0 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2089 :
2090 0 : session->db_rec = local_rec;
2091 0 : ret = state->caller_cb(session, state->caller_data);
2092 0 : session->db_rec = NULL;
2093 :
2094 0 : return ret;
2095 : }
2096 :
2097 : struct smbXsrv_session_disconnect_xconn_state {
2098 : struct smbXsrv_connection *xconn;
2099 : NTSTATUS first_status;
2100 : int errors;
2101 : };
2102 :
2103 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
2104 : void *private_data);
2105 :
2106 1136 : NTSTATUS smbXsrv_session_disconnect_xconn(struct smbXsrv_connection *xconn)
2107 : {
2108 1136 : struct smbXsrv_client *client = xconn->client;
2109 1136 : struct smbXsrv_session_table *table = client->session_table;
2110 52 : struct smbXsrv_session_disconnect_xconn_state state;
2111 52 : NTSTATUS status;
2112 1136 : int count = 0;
2113 :
2114 1136 : if (table == NULL) {
2115 0 : DBG_ERR("empty session_table, nothing to do.\n");
2116 0 : return NT_STATUS_OK;
2117 : }
2118 :
2119 1136 : ZERO_STRUCT(state);
2120 1136 : state.xconn = xconn;
2121 :
2122 1136 : status = dbwrap_traverse(table->local.db_ctx,
2123 : smbXsrv_session_disconnect_xconn_callback,
2124 : &state, &count);
2125 1136 : if (!NT_STATUS_IS_OK(status)) {
2126 0 : DBG_ERR("dbwrap_traverse() failed: %s\n",
2127 : nt_errstr(status));
2128 0 : return status;
2129 : }
2130 :
2131 1136 : if (!NT_STATUS_IS_OK(state.first_status)) {
2132 0 : DBG_ERR("count[%d] errors[%d] first[%s]\n",
2133 : count, state.errors,
2134 : nt_errstr(state.first_status));
2135 0 : return state.first_status;
2136 : }
2137 :
2138 1136 : return NT_STATUS_OK;
2139 : }
2140 :
2141 1214 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
2142 : void *private_data)
2143 : {
2144 1214 : struct smbXsrv_session_disconnect_xconn_state *state =
2145 : (struct smbXsrv_session_disconnect_xconn_state *)private_data;
2146 62 : TDB_DATA val;
2147 1214 : void *ptr = NULL;
2148 1214 : struct smbXsrv_session *session = NULL;
2149 62 : NTSTATUS status;
2150 :
2151 1214 : val = dbwrap_record_get_value(local_rec);
2152 1214 : if (val.dsize != sizeof(ptr)) {
2153 0 : status = NT_STATUS_INTERNAL_ERROR;
2154 0 : if (NT_STATUS_IS_OK(state->first_status)) {
2155 0 : state->first_status = status;
2156 : }
2157 0 : state->errors++;
2158 0 : return 0;
2159 : }
2160 :
2161 1214 : memcpy(&ptr, val.dptr, val.dsize);
2162 1214 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2163 :
2164 1214 : session->db_rec = local_rec;
2165 1214 : status = smbXsrv_session_remove_channel(session, state->xconn);
2166 1214 : session->db_rec = NULL;
2167 1214 : if (!NT_STATUS_IS_OK(status)) {
2168 0 : if (NT_STATUS_IS_OK(state->first_status)) {
2169 0 : state->first_status = status;
2170 : }
2171 0 : state->errors++;
2172 : }
2173 :
2174 1152 : return 0;
2175 : }
2176 :
2177 5780 : NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn)
2178 : {
2179 : /*
2180 : * Allow a range from 1..65534 with 65534 values.
2181 : */
2182 5780 : return smbXsrv_session_table_init(conn, 1, UINT16_MAX - 1,
2183 : UINT16_MAX - 1);
2184 : }
2185 :
2186 677142 : NTSTATUS smb1srv_session_lookup(struct smbXsrv_connection *conn,
2187 : uint16_t vuid, NTTIME now,
2188 : struct smbXsrv_session **session)
2189 : {
2190 677142 : struct smbXsrv_session_table *table = conn->client->session_table;
2191 677142 : uint32_t local_id = vuid;
2192 :
2193 677142 : return smbXsrv_session_local_lookup(table, conn, local_id, now,
2194 : session);
2195 : }
2196 :
2197 1844165 : NTSTATUS smbXsrv_session_info_lookup(struct smbXsrv_client *client,
2198 : uint64_t session_wire_id,
2199 : struct auth_session_info **si)
2200 : {
2201 1844165 : struct smbXsrv_session_table *table = client->session_table;
2202 16712 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2203 1844165 : struct smbXsrv_session_local_fetch_state state = {
2204 : .session = NULL,
2205 : .status = NT_STATUS_INTERNAL_ERROR,
2206 : };
2207 16712 : TDB_DATA key;
2208 16712 : NTSTATUS status;
2209 :
2210 1844165 : if (session_wire_id == 0) {
2211 0 : return NT_STATUS_USER_SESSION_DELETED;
2212 : }
2213 :
2214 1844165 : if (table == NULL) {
2215 : /* this might happen before the end of negprot */
2216 0 : return NT_STATUS_USER_SESSION_DELETED;
2217 : }
2218 :
2219 1844165 : if (table->local.db_ctx == NULL) {
2220 0 : return NT_STATUS_INTERNAL_ERROR;
2221 : }
2222 :
2223 1844165 : key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2224 :
2225 1844165 : status = dbwrap_parse_record(table->local.db_ctx, key,
2226 : smbXsrv_session_local_fetch_parser,
2227 : &state);
2228 1844165 : if (!NT_STATUS_IS_OK(status)) {
2229 17 : return status;
2230 : }
2231 1844148 : if (!NT_STATUS_IS_OK(state.status)) {
2232 0 : return state.status;
2233 : }
2234 1844148 : if (state.session->global->auth_session_info == NULL) {
2235 0 : return NT_STATUS_USER_SESSION_DELETED;
2236 : }
2237 :
2238 1844148 : *si = state.session->global->auth_session_info;
2239 1844148 : return NT_STATUS_OK;
2240 : }
2241 :
2242 : /*
2243 : * In memory of get_valid_user_struct()
2244 : *
2245 : * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
2246 : * but it doesn't implement the state checks of
2247 : * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
2248 : * session wire-id of incoming SMB requests, it MUST only be used in later
2249 : * internal processing where the session wire-id has already been validated.
2250 : */
2251 33542 : NTSTATUS get_valid_smbXsrv_session(struct smbXsrv_client *client,
2252 : uint64_t session_wire_id,
2253 : struct smbXsrv_session **session)
2254 : {
2255 33542 : struct smbXsrv_session_table *table = client->session_table;
2256 760 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2257 33542 : struct smbXsrv_session_local_fetch_state state = {
2258 : .session = NULL,
2259 : .status = NT_STATUS_INTERNAL_ERROR,
2260 : };
2261 760 : TDB_DATA key;
2262 760 : NTSTATUS status;
2263 :
2264 33542 : if (session_wire_id == 0) {
2265 0 : return NT_STATUS_USER_SESSION_DELETED;
2266 : }
2267 :
2268 33542 : if (table == NULL) {
2269 : /* this might happen before the end of negprot */
2270 0 : return NT_STATUS_USER_SESSION_DELETED;
2271 : }
2272 :
2273 33542 : if (table->local.db_ctx == NULL) {
2274 0 : return NT_STATUS_INTERNAL_ERROR;
2275 : }
2276 :
2277 33542 : key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2278 :
2279 33542 : status = dbwrap_parse_record(table->local.db_ctx, key,
2280 : smbXsrv_session_local_fetch_parser,
2281 : &state);
2282 33542 : if (!NT_STATUS_IS_OK(status)) {
2283 0 : return status;
2284 : }
2285 33542 : if (!NT_STATUS_IS_OK(state.status)) {
2286 0 : return state.status;
2287 : }
2288 33542 : if (state.session->global->auth_session_info == NULL) {
2289 4162 : return NT_STATUS_USER_SESSION_DELETED;
2290 : }
2291 :
2292 29380 : *session = state.session;
2293 29380 : return NT_STATUS_OK;
2294 : }
2295 :
2296 26755 : NTSTATUS smb2srv_session_lookup_global(struct smbXsrv_client *client,
2297 : uint64_t session_wire_id,
2298 : TALLOC_CTX *mem_ctx,
2299 : struct smbXsrv_session **_session)
2300 : {
2301 26755 : TALLOC_CTX *frame = talloc_stackframe();
2302 26755 : struct smbXsrv_session_table *table = client->session_table;
2303 26755 : uint32_t global_id = session_wire_id & UINT32_MAX;
2304 26755 : uint64_t global_zeros = session_wire_id & 0xFFFFFFFF00000000LLU;
2305 26755 : struct smbXsrv_session *session = NULL;
2306 26755 : struct db_record *global_rec = NULL;
2307 26755 : bool is_free = false;
2308 832 : NTSTATUS status;
2309 :
2310 26755 : if (global_id == 0) {
2311 25588 : TALLOC_FREE(frame);
2312 25588 : return NT_STATUS_USER_SESSION_DELETED;
2313 : }
2314 1167 : if (global_zeros != 0) {
2315 0 : TALLOC_FREE(frame);
2316 0 : return NT_STATUS_USER_SESSION_DELETED;
2317 : }
2318 :
2319 1167 : if (table == NULL) {
2320 : /* this might happen before the end of negprot */
2321 0 : TALLOC_FREE(frame);
2322 0 : return NT_STATUS_USER_SESSION_DELETED;
2323 : }
2324 :
2325 1167 : if (table->global.db_ctx == NULL) {
2326 0 : TALLOC_FREE(frame);
2327 0 : return NT_STATUS_INTERNAL_ERROR;
2328 : }
2329 :
2330 1167 : session = talloc_zero(mem_ctx, struct smbXsrv_session);
2331 1167 : if (session == NULL) {
2332 0 : TALLOC_FREE(frame);
2333 0 : return NT_STATUS_NO_MEMORY;
2334 : }
2335 1167 : talloc_steal(frame, session);
2336 :
2337 1167 : session->client = client;
2338 1167 : session->status = NT_STATUS_BAD_LOGON_SESSION_STATE;
2339 1167 : session->local_id = global_id;
2340 :
2341 : /*
2342 : * This means smb2_get_new_nonce() will return
2343 : * NT_STATUS_ENCRYPTION_FAILED.
2344 : *
2345 : * But we initialize some random parts just in case...
2346 : */
2347 1167 : session->nonce_high_max = session->nonce_high = 0;
2348 1167 : generate_nonce_buffer((uint8_t *)&session->nonce_high_random,
2349 : sizeof(session->nonce_high_random));
2350 1167 : generate_nonce_buffer((uint8_t *)&session->nonce_low,
2351 : sizeof(session->nonce_low));
2352 :
2353 1167 : global_rec = smbXsrv_session_global_fetch_locked(table->global.db_ctx,
2354 : global_id,
2355 : frame);
2356 1167 : if (global_rec == NULL) {
2357 0 : TALLOC_FREE(frame);
2358 0 : return NT_STATUS_INTERNAL_DB_ERROR;
2359 : }
2360 :
2361 1167 : smbXsrv_session_global_verify_record(global_rec,
2362 : &is_free,
2363 : NULL,
2364 : session,
2365 1167 : &session->global,
2366 : NULL);
2367 1167 : if (is_free) {
2368 10 : TALLOC_FREE(frame);
2369 10 : return NT_STATUS_USER_SESSION_DELETED;
2370 : }
2371 :
2372 : /*
2373 : * We don't have channels on this session
2374 : * and only the main signing key
2375 : */
2376 1157 : session->global->num_channels = 0;
2377 1362 : status = smb2_signing_key_sign_create(session->global,
2378 1157 : session->global->signing_algo,
2379 : NULL, /* no master key */
2380 : NULL, /* derivations */
2381 952 : &session->global->signing_key);
2382 1157 : if (!NT_STATUS_IS_OK(status)) {
2383 0 : TALLOC_FREE(frame);
2384 0 : return NT_STATUS_NO_MEMORY;
2385 : }
2386 1157 : session->global->signing_key->blob = session->global->signing_key_blob;
2387 1157 : session->global->signing_flags = 0;
2388 :
2389 1362 : status = smb2_signing_key_cipher_create(session->global,
2390 1157 : session->global->encryption_cipher,
2391 : NULL, /* no master key */
2392 : NULL, /* derivations */
2393 952 : &session->global->decryption_key);
2394 1157 : if (!NT_STATUS_IS_OK(status)) {
2395 0 : TALLOC_FREE(frame);
2396 0 : return NT_STATUS_NO_MEMORY;
2397 : }
2398 1157 : session->global->decryption_key->blob = session->global->decryption_key_blob;
2399 1157 : session->global->encryption_flags = 0;
2400 :
2401 1157 : *_session = talloc_move(mem_ctx, &session);
2402 1157 : TALLOC_FREE(frame);
2403 1157 : return NT_STATUS_OK;
2404 : }
2405 :
2406 24908 : NTSTATUS smb2srv_session_table_init(struct smbXsrv_connection *conn)
2407 : {
2408 : /*
2409 : * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
2410 : */
2411 24908 : return smbXsrv_session_table_init(conn, 1, UINT32_MAX - 1,
2412 : UINT16_MAX - 1);
2413 : }
2414 :
2415 1490501 : static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
2416 : /* conn: optional */
2417 : struct smbXsrv_connection *conn,
2418 : uint64_t session_id, NTTIME now,
2419 : struct smbXsrv_session **session)
2420 : {
2421 1490501 : uint32_t local_id = session_id & UINT32_MAX;
2422 1490501 : uint64_t local_zeros = session_id & 0xFFFFFFFF00000000LLU;
2423 :
2424 1490501 : if (local_zeros != 0) {
2425 24 : return NT_STATUS_USER_SESSION_DELETED;
2426 : }
2427 :
2428 1490477 : return smbXsrv_session_local_lookup(table, conn, local_id, now,
2429 : session);
2430 : }
2431 :
2432 1442726 : NTSTATUS smb2srv_session_lookup_conn(struct smbXsrv_connection *conn,
2433 : uint64_t session_id, NTTIME now,
2434 : struct smbXsrv_session **session)
2435 : {
2436 1442726 : struct smbXsrv_session_table *table = conn->client->session_table;
2437 1442726 : return smb2srv_session_lookup_raw(table, conn, session_id, now,
2438 : session);
2439 : }
2440 :
2441 47775 : NTSTATUS smb2srv_session_lookup_client(struct smbXsrv_client *client,
2442 : uint64_t session_id, NTTIME now,
2443 : struct smbXsrv_session **session)
2444 : {
2445 47775 : struct smbXsrv_session_table *table = client->session_table;
2446 47775 : return smb2srv_session_lookup_raw(table, NULL, session_id, now,
2447 : session);
2448 : }
2449 :
2450 : struct smbXsrv_session_global_traverse_state {
2451 : int (*fn)(struct smbXsrv_session_global0 *, void *);
2452 : void *private_data;
2453 : };
2454 :
2455 46 : static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
2456 : {
2457 46 : int ret = -1;
2458 46 : struct smbXsrv_session_global_traverse_state *state =
2459 : (struct smbXsrv_session_global_traverse_state*)data;
2460 46 : TDB_DATA key = dbwrap_record_get_key(rec);
2461 46 : TDB_DATA val = dbwrap_record_get_value(rec);
2462 46 : DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
2463 0 : struct smbXsrv_session_globalB global_blob;
2464 0 : enum ndr_err_code ndr_err;
2465 46 : TALLOC_CTX *frame = talloc_stackframe();
2466 :
2467 46 : ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
2468 : (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
2469 46 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2470 0 : DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2471 : "key '%s' ndr_pull_struct_blob - %s\n",
2472 : tdb_data_dbg(key),
2473 : ndr_errstr(ndr_err));
2474 0 : goto done;
2475 : }
2476 :
2477 46 : if (global_blob.version != SMBXSRV_VERSION_0) {
2478 0 : DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2479 : "key '%s' unsupported version - %d\n",
2480 : tdb_data_dbg(key),
2481 : (int)global_blob.version);
2482 0 : goto done;
2483 : }
2484 :
2485 46 : if (global_blob.info.info0 == NULL) {
2486 0 : DBG_WARNING("Invalid record in smbXsrv_tcon_global.tdb:"
2487 : "key '%s' info0 NULL pointer\n",
2488 : tdb_data_dbg(key));
2489 0 : goto done;
2490 : }
2491 :
2492 46 : global_blob.info.info0->db_rec = rec;
2493 46 : ret = state->fn(global_blob.info.info0, state->private_data);
2494 46 : done:
2495 46 : TALLOC_FREE(frame);
2496 46 : return ret;
2497 : }
2498 :
2499 42 : NTSTATUS smbXsrv_session_global_traverse(
2500 : int (*fn)(struct smbXsrv_session_global0 *, void *),
2501 : void *private_data)
2502 : {
2503 :
2504 0 : NTSTATUS status;
2505 42 : int count = 0;
2506 42 : struct smbXsrv_session_global_traverse_state state = {
2507 : .fn = fn,
2508 : .private_data = private_data,
2509 : };
2510 :
2511 42 : become_root();
2512 42 : status = smbXsrv_session_global_init(NULL);
2513 42 : if (!NT_STATUS_IS_OK(status)) {
2514 0 : unbecome_root();
2515 0 : DBG_ERR("Failed to initialize session_global: %s\n",
2516 : nt_errstr(status));
2517 0 : return status;
2518 : }
2519 :
2520 42 : status = dbwrap_traverse_read(smbXsrv_session_global_db_ctx,
2521 : smbXsrv_session_global_traverse_fn,
2522 : &state,
2523 : &count);
2524 42 : unbecome_root();
2525 :
2526 42 : return status;
2527 : }
|