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 30534 : NTSTATUS smbXsrv_session_global_init(struct messaging_context *msg_ctx)
60 : {
61 30534 : char *global_path = NULL;
62 30534 : struct db_context *backend = NULL;
63 30534 : struct db_context *db_ctx = NULL;
64 :
65 30534 : if (smbXsrv_session_global_db_ctx != NULL) {
66 30512 : 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 197010 : 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 197010 : RSIVAL(key_buf, 0, id);
120 :
121 197010 : key = make_tdb_data(key_buf, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE);
122 :
123 197010 : 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 3976530 : static TDB_DATA smbXsrv_session_local_id_to_key(uint32_t id,
146 : uint8_t *key_buf)
147 : {
148 38089 : TDB_DATA key;
149 :
150 3976530 : RSIVAL(key_buf, 0, id);
151 :
152 3976530 : key = make_tdb_data(key_buf, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE);
153 :
154 3976530 : 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 197010 : 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 197010 : struct db_record *rec = NULL;
180 :
181 197010 : key = smbXsrv_session_global_id_to_key(id, key_buf);
182 :
183 197010 : rec = dbwrap_fetch_locked(db, mem_ctx, key);
184 :
185 197010 : 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 197010 : return rec;
191 : }
192 :
193 36062 : 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 36062 : struct db_record *rec = NULL;
201 :
202 36062 : key = smbXsrv_session_local_id_to_key(id, key_buf);
203 :
204 36062 : rec = dbwrap_fetch_locked(db, mem_ctx, key);
205 :
206 36062 : 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 36062 : return rec;
212 : }
213 :
214 : static void smbXsrv_session_close_loop(struct tevent_req *subreq);
215 :
216 30492 : 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 30492 : 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 30492 : if (lowest_id > highest_id) {
228 0 : return NT_STATUS_INTERNAL_ERROR;
229 : }
230 :
231 30492 : max_range = highest_id;
232 30492 : max_range -= lowest_id;
233 30492 : max_range += 1;
234 :
235 30492 : if (max_sessions > max_range) {
236 0 : return NT_STATUS_INTERNAL_ERROR;
237 : }
238 :
239 30492 : table = talloc_zero(client, struct smbXsrv_session_table);
240 30492 : if (table == NULL) {
241 0 : return NT_STATUS_NO_MEMORY;
242 : }
243 :
244 30492 : table->local.db_ctx = db_open_rbt(table);
245 30492 : if (table->local.db_ctx == NULL) {
246 0 : TALLOC_FREE(table);
247 0 : return NT_STATUS_NO_MEMORY;
248 : }
249 30492 : table->local.lowest_id = lowest_id;
250 30492 : table->local.highest_id = highest_id;
251 30492 : table->local.max_sessions = max_sessions;
252 :
253 30492 : status = smbXsrv_session_global_init(client->msg_ctx);
254 30492 : if (!NT_STATUS_IS_OK(status)) {
255 0 : TALLOC_FREE(table);
256 0 : return status;
257 : }
258 :
259 30492 : table->global.db_ctx = smbXsrv_session_global_db_ctx;
260 :
261 30492 : subreq = messaging_read_send(table,
262 : client->raw_ev_ctx,
263 : client->msg_ctx,
264 : MSG_SMBXSRV_SESSION_CLOSE);
265 30492 : if (subreq == NULL) {
266 0 : TALLOC_FREE(table);
267 0 : return NT_STATUS_NO_MEMORY;
268 : }
269 30492 : tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
270 :
271 30492 : client->session_table = table;
272 30492 : 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 6805 : 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 6805 : 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 6805 : int count = 0;
502 :
503 6805 : *_rec = NULL;
504 6805 : *_id = 0;
505 :
506 6805 : if (lowest_id > highest_id) {
507 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
508 : }
509 :
510 : /*
511 : * first we try randomly
512 : */
513 6805 : range = (highest_id - lowest_id) + 1;
514 :
515 6805 : for (i = 0; i < (range / 2); i++) {
516 133 : uint32_t id;
517 133 : TDB_DATA val;
518 6805 : struct db_record *rec = NULL;
519 :
520 6805 : id = generate_random() % range;
521 6805 : id += lowest_id;
522 :
523 6805 : if (id < lowest_id) {
524 0 : id = lowest_id;
525 : }
526 6805 : if (id > highest_id) {
527 0 : id = highest_id;
528 : }
529 :
530 6805 : rec = smbXsrv_session_local_fetch_locked(db, id, mem_ctx);
531 6805 : if (rec == NULL) {
532 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
533 : }
534 :
535 6805 : val = dbwrap_record_get_value(rec);
536 6805 : if (val.dsize != 0) {
537 0 : TALLOC_FREE(rec);
538 0 : continue;
539 : }
540 :
541 6805 : *_rec = rec;
542 6805 : *_id = id;
543 6805 : 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 3939394 : static void smbXsrv_session_local_fetch_parser(TDB_DATA key, TDB_DATA data,
610 : void *private_data)
611 : {
612 3939394 : struct smbXsrv_session_local_fetch_state *state =
613 : (struct smbXsrv_session_local_fetch_state *)private_data;
614 37142 : void *ptr;
615 :
616 3939394 : if (data.dsize != sizeof(ptr)) {
617 0 : state->status = NT_STATUS_INTERNAL_DB_ERROR;
618 0 : return;
619 : }
620 :
621 3939394 : memcpy(&ptr, data.dptr, data.dsize);
622 3939394 : state->session = talloc_get_type_abort(ptr, struct smbXsrv_session);
623 3939394 : state->status = NT_STATUS_OK;
624 : }
625 :
626 2154696 : 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 2154696 : struct smbXsrv_session_local_fetch_state state = {
634 : .session = NULL,
635 : .status = NT_STATUS_INTERNAL_ERROR,
636 : };
637 21089 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
638 21089 : TDB_DATA key;
639 21089 : NTSTATUS status;
640 :
641 2154696 : *_session = NULL;
642 :
643 2154696 : if (session_local_id == 0) {
644 82080 : return NT_STATUS_USER_SESSION_DELETED;
645 : }
646 :
647 2072616 : if (table == NULL) {
648 : /* this might happen before the end of negprot */
649 0 : return NT_STATUS_USER_SESSION_DELETED;
650 : }
651 :
652 2072616 : if (table->local.db_ctx == NULL) {
653 0 : return NT_STATUS_INTERNAL_ERROR;
654 : }
655 :
656 2072616 : key = smbXsrv_session_local_id_to_key(session_local_id, key_buf);
657 :
658 2072616 : status = dbwrap_parse_record(table->local.db_ctx, key,
659 : smbXsrv_session_local_fetch_parser,
660 : &state);
661 2072616 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
662 1057 : return NT_STATUS_USER_SESSION_DELETED;
663 2071559 : } else if (!NT_STATUS_IS_OK(status)) {
664 0 : return status;
665 : }
666 2071559 : if (!NT_STATUS_IS_OK(state.status)) {
667 0 : return state.status;
668 : }
669 :
670 2071559 : 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 2071559 : if (conn != NULL) {
679 2050493 : struct smbXsrv_channel_global0 *c = NULL;
680 :
681 2050493 : status = smbXsrv_session_find_channel(state.session, conn, &c);
682 2050493 : if (!NT_STATUS_IS_OK(status)) {
683 140 : return status;
684 : }
685 : }
686 :
687 2071419 : state.session->idle_time = now;
688 :
689 2071419 : if (!NT_STATUS_IS_OK(state.session->status)) {
690 30898 : *_session = state.session;
691 30898 : return state.session->status;
692 : }
693 :
694 2040521 : if (now > state.session->global->expiration_time) {
695 49 : state.session->status = NT_STATUS_NETWORK_SESSION_EXPIRED;
696 : }
697 :
698 2040521 : *_session = state.session;
699 2040521 : return state.session->status;
700 : }
701 :
702 32297 : static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0 *global)
703 : {
704 32297 : 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 32311 : 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 32311 : struct smbXsrv_session_global0 *global = NULL;
720 32311 : uint32_t last_free = 0;
721 32311 : const uint32_t min_tries = 3;
722 :
723 32311 : *_global = NULL;
724 :
725 32311 : global = talloc_zero(mem_ctx, struct smbXsrv_session_global0);
726 32311 : if (global == NULL) {
727 0 : return NT_STATUS_NO_MEMORY;
728 : }
729 32311 : 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 33071 : for (i = 0; i < UINT32_MAX; i++) {
738 32311 : bool is_free = false;
739 32311 : bool was_free = false;
740 760 : uint32_t id;
741 :
742 32311 : if (i >= min_tries && last_free != 0) {
743 0 : id = last_free;
744 : } else {
745 32311 : id = generate_random();
746 : }
747 32311 : if (id == 0) {
748 0 : id++;
749 : }
750 32311 : if (id == UINT32_MAX) {
751 0 : id--;
752 : }
753 :
754 32311 : global->db_rec = smbXsrv_session_global_fetch_locked(db, id,
755 : mem_ctx);
756 32311 : if (global->db_rec == NULL) {
757 0 : talloc_free(global);
758 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
759 : }
760 :
761 32311 : smbXsrv_session_global_verify_record(global->db_rec,
762 : &is_free,
763 : &was_free,
764 : NULL, NULL, NULL);
765 :
766 32311 : if (!is_free) {
767 0 : TALLOC_FREE(global->db_rec);
768 0 : continue;
769 : }
770 :
771 32311 : 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 32311 : global->session_global_id = id;
790 :
791 32311 : *_global = global;
792 32311 : 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 33636 : 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 33636 : struct smbXsrv_session_global0 *global = NULL;
813 973 : bool exists;
814 33636 : TALLOC_CTX *frame = talloc_stackframe();
815 :
816 33636 : *is_free = false;
817 :
818 33636 : if (was_free) {
819 32311 : *was_free = false;
820 : }
821 33636 : if (_g) {
822 1325 : *_g = NULL;
823 : }
824 33636 : if (pseqnum) {
825 158 : *pseqnum = 0;
826 : }
827 :
828 33636 : key = dbwrap_record_get_key(db_rec);
829 :
830 33636 : val = dbwrap_record_get_value(db_rec);
831 33636 : if (val.dsize == 0) {
832 32423 : TALLOC_FREE(frame);
833 32423 : *is_free = true;
834 32423 : if (was_free) {
835 32311 : *was_free = true;
836 : }
837 32423 : 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 163388 : static NTSTATUS smbXsrv_session_global_store(struct smbXsrv_session_global0 *global)
923 : {
924 3327 : struct smbXsrv_session_globalB global_blob;
925 163388 : 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 163388 : if (global->db_rec == NULL) {
938 0 : return NT_STATUS_INTERNAL_ERROR;
939 : }
940 :
941 163388 : key = dbwrap_record_get_key(global->db_rec);
942 163388 : val = dbwrap_record_get_value(global->db_rec);
943 :
944 163388 : ZERO_STRUCT(global_blob);
945 163388 : global_blob.version = smbXsrv_version_global_current();
946 163388 : if (val.dsize >= 8) {
947 131077 : global_blob.seqnum = IVAL(val.dptr, 4);
948 : }
949 163388 : global_blob.seqnum += 1;
950 163388 : global_blob.info.info0 = global;
951 :
952 163388 : ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
953 : (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_globalB);
954 163388 : 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 163388 : val = make_tdb_data(blob.data, blob.length);
964 163388 : status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
965 163388 : 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 163388 : 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 163388 : TALLOC_FREE(global->db_rec);
980 :
981 163388 : 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 60843 : static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session)
1235 : {
1236 1499 : NTSTATUS status;
1237 60843 : struct smbXsrv_connection *xconn = NULL;
1238 :
1239 60843 : if (session->client != NULL) {
1240 32028 : xconn = session->client->connections;
1241 : }
1242 :
1243 92923 : for (; xconn != NULL; xconn = xconn->next) {
1244 750 : struct smbd_smb2_request *preq;
1245 :
1246 32136 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1247 56 : if (preq->session != session) {
1248 0 : continue;
1249 : }
1250 :
1251 56 : preq->session = NULL;
1252 : /*
1253 : * If we no longer have a session we can't
1254 : * sign or encrypt replies.
1255 : */
1256 56 : preq->do_signing = false;
1257 56 : preq->do_encryption = false;
1258 56 : preq->preauth = NULL;
1259 : }
1260 : }
1261 :
1262 60843 : status = smbXsrv_session_logoff(session);
1263 60843 : return status;
1264 : }
1265 :
1266 32297 : static int smbXsrv_session_destructor(struct smbXsrv_session *session)
1267 : {
1268 760 : NTSTATUS status;
1269 :
1270 32297 : DBG_DEBUG("destructing session(%llu)\n",
1271 : (unsigned long long)session->global->session_wire_id);
1272 :
1273 32297 : status = smbXsrv_session_clear_and_logoff(session);
1274 32297 : 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 32297 : TALLOC_FREE(session->global);
1281 :
1282 32297 : return 0;
1283 : }
1284 :
1285 32311 : NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
1286 : NTTIME now,
1287 : struct smbXsrv_session **_session)
1288 : {
1289 32311 : struct smbXsrv_session_table *table = conn->client->session_table;
1290 32311 : struct db_record *local_rec = NULL;
1291 32311 : struct smbXsrv_session *session = NULL;
1292 32311 : void *ptr = NULL;
1293 760 : TDB_DATA val;
1294 32311 : struct smbXsrv_session_global0 *global = NULL;
1295 32311 : struct smbXsrv_channel_global0 *channel = NULL;
1296 760 : NTSTATUS status;
1297 :
1298 32311 : if (table->local.num_sessions >= table->local.max_sessions) {
1299 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1300 : }
1301 :
1302 32311 : session = talloc_zero(table, struct smbXsrv_session);
1303 32311 : if (session == NULL) {
1304 0 : return NT_STATUS_NO_MEMORY;
1305 : }
1306 32311 : session->table = table;
1307 32311 : session->idle_time = now;
1308 32311 : session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
1309 32311 : session->client = conn->client;
1310 32311 : session->homes_snum = -1;
1311 :
1312 32311 : status = smbXsrv_session_global_allocate(table->global.db_ctx,
1313 : session,
1314 : &global);
1315 32311 : if (!NT_STATUS_IS_OK(status)) {
1316 0 : TALLOC_FREE(session);
1317 0 : return status;
1318 : }
1319 32311 : session->global = global;
1320 :
1321 32311 : if (conn->protocol >= PROTOCOL_SMB2_02) {
1322 25506 : uint64_t id = global->session_global_id;
1323 :
1324 25506 : global->connection_dialect = conn->smb2.server.dialect;
1325 :
1326 25506 : global->session_wire_id = id;
1327 :
1328 25506 : status = smb2srv_tcon_table_init(session);
1329 25506 : if (!NT_STATUS_IS_OK(status)) {
1330 0 : TALLOC_FREE(session);
1331 0 : return status;
1332 : }
1333 :
1334 25506 : session->local_id = global->session_global_id;
1335 :
1336 25506 : local_rec = smbXsrv_session_local_fetch_locked(
1337 : table->local.db_ctx,
1338 : session->local_id,
1339 : session /* TALLOC_CTX */);
1340 25506 : if (local_rec == NULL) {
1341 0 : TALLOC_FREE(session);
1342 0 : return NT_STATUS_NO_MEMORY;
1343 : }
1344 :
1345 25506 : val = dbwrap_record_get_value(local_rec);
1346 25506 : if (val.dsize != 0) {
1347 0 : TALLOC_FREE(session);
1348 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1349 : }
1350 : } else {
1351 :
1352 6805 : status = smb1srv_session_local_allocate_id(table->local.db_ctx,
1353 : table->local.lowest_id,
1354 : table->local.highest_id,
1355 : session,
1356 : &local_rec,
1357 : &session->local_id);
1358 6805 : if (!NT_STATUS_IS_OK(status)) {
1359 0 : TALLOC_FREE(session);
1360 0 : return status;
1361 : }
1362 :
1363 6805 : global->session_wire_id = session->local_id;
1364 : }
1365 :
1366 32311 : global->creation_time = now;
1367 32311 : global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1368 :
1369 32311 : status = smbXsrv_session_add_channel(session, conn, now, &channel);
1370 32311 : if (!NT_STATUS_IS_OK(status)) {
1371 0 : TALLOC_FREE(session);
1372 0 : return status;
1373 : }
1374 :
1375 32311 : ptr = session;
1376 32311 : val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
1377 32311 : status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
1378 32311 : TALLOC_FREE(local_rec);
1379 32311 : if (!NT_STATUS_IS_OK(status)) {
1380 0 : TALLOC_FREE(session);
1381 0 : return status;
1382 : }
1383 32311 : table->local.num_sessions += 1;
1384 :
1385 32311 : talloc_set_destructor(session, smbXsrv_session_destructor);
1386 :
1387 32311 : status = smbXsrv_session_global_store(global);
1388 32311 : if (!NT_STATUS_IS_OK(status)) {
1389 0 : DBG_ERR("smbXsrv_session_create: "
1390 : "global_id (0x%08x) store failed - %s\n",
1391 : session->global->session_global_id,
1392 : nt_errstr(status));
1393 0 : TALLOC_FREE(session);
1394 0 : return status;
1395 : }
1396 :
1397 32311 : if (DEBUGLVL(DBGLVL_DEBUG)) {
1398 0 : struct smbXsrv_sessionB session_blob = {
1399 : .version = SMBXSRV_VERSION_0,
1400 : .info.info0 = session,
1401 : };
1402 :
1403 0 : DBG_DEBUG("smbXsrv_session_create: global_id (0x%08x) stored\n",
1404 : session->global->session_global_id);
1405 0 : NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1406 : }
1407 :
1408 32311 : *_session = session;
1409 32311 : return NT_STATUS_OK;
1410 : }
1411 :
1412 33221 : NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
1413 : struct smbXsrv_connection *conn,
1414 : NTTIME now,
1415 : struct smbXsrv_channel_global0 **_c)
1416 : {
1417 33221 : struct smbXsrv_session_global0 *global = session->global;
1418 33221 : struct smbXsrv_channel_global0 *c = NULL;
1419 :
1420 33221 : if (global->num_channels > 31) {
1421 : /*
1422 : * Windows allow up to 32 channels
1423 : */
1424 4 : return NT_STATUS_INSUFFICIENT_RESOURCES;
1425 : }
1426 :
1427 33217 : c = talloc_realloc(global,
1428 : global->channels,
1429 : struct smbXsrv_channel_global0,
1430 : global->num_channels + 1);
1431 33217 : if (c == NULL) {
1432 0 : return NT_STATUS_NO_MEMORY;
1433 : }
1434 33217 : global->channels = c;
1435 :
1436 33217 : c = &global->channels[global->num_channels];
1437 33217 : ZERO_STRUCTP(c);
1438 :
1439 33217 : c->server_id = messaging_server_id(conn->client->msg_ctx);
1440 33217 : c->channel_id = conn->channel_id;
1441 33217 : c->creation_time = now;
1442 66434 : c->local_address = tsocket_address_string(conn->local_address,
1443 33217 : global->channels);
1444 33217 : if (c->local_address == NULL) {
1445 0 : return NT_STATUS_NO_MEMORY;
1446 : }
1447 66434 : c->remote_address = tsocket_address_string(conn->remote_address,
1448 33217 : global->channels);
1449 33217 : if (c->remote_address == NULL) {
1450 0 : return NT_STATUS_NO_MEMORY;
1451 : }
1452 33217 : c->remote_name = talloc_strdup(global->channels,
1453 : conn->remote_hostname);
1454 33217 : if (c->remote_name == NULL) {
1455 0 : return NT_STATUS_NO_MEMORY;
1456 : }
1457 33217 : c->connection = conn;
1458 :
1459 33217 : global->num_channels += 1;
1460 :
1461 33217 : *_c = c;
1462 33217 : return NT_STATUS_OK;
1463 : }
1464 :
1465 131077 : NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session)
1466 : {
1467 131077 : struct smbXsrv_session_table *table = session->table;
1468 2567 : NTSTATUS status;
1469 :
1470 131077 : if (session->global->db_rec != NULL) {
1471 0 : DBG_ERR("smbXsrv_session_update(0x%08x): "
1472 : "Called with db_rec != NULL'\n",
1473 : session->global->session_global_id);
1474 0 : return NT_STATUS_INTERNAL_ERROR;
1475 : }
1476 :
1477 131077 : if (table == NULL) {
1478 0 : DBG_ERR("smbXsrv_session_update(0x%08x): "
1479 : "Called with table == NULL'\n",
1480 : session->global->session_global_id);
1481 0 : return NT_STATUS_INTERNAL_ERROR;
1482 : }
1483 :
1484 259587 : session->global->db_rec = smbXsrv_session_global_fetch_locked(
1485 : table->global.db_ctx,
1486 128510 : session->global->session_global_id,
1487 128510 : session->global /* TALLOC_CTX */);
1488 131077 : if (session->global->db_rec == NULL) {
1489 0 : return NT_STATUS_INTERNAL_DB_ERROR;
1490 : }
1491 :
1492 131077 : status = smbXsrv_session_global_store(session->global);
1493 131077 : if (!NT_STATUS_IS_OK(status)) {
1494 0 : DBG_ERR("smbXsrv_session_update: "
1495 : "global_id (0x%08x) store failed - %s\n",
1496 : session->global->session_global_id,
1497 : nt_errstr(status));
1498 0 : return status;
1499 : }
1500 :
1501 131077 : if (DEBUGLVL(DBGLVL_DEBUG)) {
1502 0 : struct smbXsrv_sessionB session_blob = {
1503 : .version = SMBXSRV_VERSION_0,
1504 : .info.info0 = session,
1505 : };
1506 :
1507 0 : DBG_DEBUG("smbXsrv_session_update: global_id (0x%08x) stored\n",
1508 : session->global->session_global_id);
1509 0 : NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1510 : }
1511 :
1512 131077 : return NT_STATUS_OK;
1513 : }
1514 :
1515 3532912 : NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
1516 : const struct smbXsrv_connection *conn,
1517 : struct smbXsrv_channel_global0 **_c)
1518 : {
1519 40199 : uint32_t i;
1520 :
1521 3612286 : for (i=0; i < session->global->num_channels; i++) {
1522 3606210 : struct smbXsrv_channel_global0 *c = &session->global->channels[i];
1523 :
1524 3606210 : if (c->channel_id != conn->channel_id) {
1525 79374 : continue;
1526 : }
1527 :
1528 3526836 : if (c->connection != conn) {
1529 0 : continue;
1530 : }
1531 :
1532 3526836 : *_c = c;
1533 3526836 : return NT_STATUS_OK;
1534 : }
1535 :
1536 6076 : return NT_STATUS_USER_SESSION_DELETED;
1537 : }
1538 :
1539 93757 : NTSTATUS smbXsrv_session_find_auth(const struct smbXsrv_session *session,
1540 : const struct smbXsrv_connection *conn,
1541 : NTTIME now,
1542 : struct smbXsrv_session_auth0 **_a)
1543 : {
1544 1980 : struct smbXsrv_session_auth0 *a;
1545 :
1546 93757 : for (a = session->pending_auth; a != NULL; a = a->next) {
1547 25089 : if (a->channel_id != conn->channel_id) {
1548 0 : continue;
1549 : }
1550 :
1551 25089 : if (a->connection == conn) {
1552 25089 : if (now != 0) {
1553 25071 : a->idle_time = now;
1554 : }
1555 25089 : *_a = a;
1556 25089 : return NT_STATUS_OK;
1557 : }
1558 : }
1559 :
1560 68668 : return NT_STATUS_USER_SESSION_DELETED;
1561 : }
1562 :
1563 33336 : static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0 *a)
1564 : {
1565 33336 : if (a->session == NULL) {
1566 14 : return 0;
1567 : }
1568 :
1569 33318 : DLIST_REMOVE(a->session->pending_auth, a);
1570 33318 : a->session = NULL;
1571 33318 : return 0;
1572 : }
1573 :
1574 33330 : NTSTATUS smbXsrv_session_create_auth(struct smbXsrv_session *session,
1575 : struct smbXsrv_connection *conn,
1576 : NTTIME now,
1577 : uint8_t in_flags,
1578 : uint8_t in_security_mode,
1579 : struct smbXsrv_session_auth0 **_a)
1580 : {
1581 811 : struct smbXsrv_session_auth0 *a;
1582 811 : NTSTATUS status;
1583 :
1584 33330 : status = smbXsrv_session_find_auth(session, conn, 0, &a);
1585 33330 : if (NT_STATUS_IS_OK(status)) {
1586 0 : return NT_STATUS_INTERNAL_ERROR;
1587 : }
1588 :
1589 33330 : a = talloc_zero(session, struct smbXsrv_session_auth0);
1590 33330 : if (a == NULL) {
1591 0 : return NT_STATUS_NO_MEMORY;
1592 : }
1593 33330 : a->session = session;
1594 33330 : a->connection = conn;
1595 33330 : a->in_flags = in_flags;
1596 33330 : a->in_security_mode = in_security_mode;
1597 33330 : a->creation_time = now;
1598 33330 : a->idle_time = now;
1599 33330 : a->channel_id = conn->channel_id;
1600 :
1601 33330 : if (conn->protocol >= PROTOCOL_SMB3_11) {
1602 24031 : a->preauth = talloc(a, struct smbXsrv_preauth);
1603 24031 : if (a->preauth == NULL) {
1604 0 : TALLOC_FREE(session);
1605 0 : return NT_STATUS_NO_MEMORY;
1606 : }
1607 24031 : *a->preauth = conn->smb2.preauth;
1608 : }
1609 :
1610 33330 : talloc_set_destructor(a, smbXsrv_session_auth0_destructor);
1611 33330 : DLIST_ADD_END(session->pending_auth, a);
1612 :
1613 33330 : *_a = a;
1614 33330 : return NT_STATUS_OK;
1615 : }
1616 :
1617 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq);
1618 :
1619 2026 : NTSTATUS smbXsrv_session_remove_channel(struct smbXsrv_session *session,
1620 : struct smbXsrv_connection *xconn)
1621 : {
1622 2026 : struct smbXsrv_session_auth0 *a = NULL;
1623 2026 : struct smbXsrv_channel_global0 *c = NULL;
1624 210 : NTSTATUS status;
1625 2026 : bool need_update = false;
1626 :
1627 2026 : status = smbXsrv_session_find_auth(session, xconn, 0, &a);
1628 2026 : if (!NT_STATUS_IS_OK(status)) {
1629 2008 : a = NULL;
1630 : }
1631 2026 : status = smbXsrv_session_find_channel(session, xconn, &c);
1632 2026 : if (!NT_STATUS_IS_OK(status)) {
1633 1086 : c = NULL;
1634 : }
1635 :
1636 2026 : if (a != NULL) {
1637 18 : smbXsrv_session_auth0_destructor(a);
1638 18 : a->connection = NULL;
1639 18 : need_update = true;
1640 : }
1641 :
1642 2026 : if (c != NULL) {
1643 940 : struct smbXsrv_session_global0 *global = session->global;
1644 24 : ptrdiff_t n;
1645 :
1646 940 : n = (c - global->channels);
1647 940 : if (n >= global->num_channels || n < 0) {
1648 0 : return NT_STATUS_INTERNAL_ERROR;
1649 : }
1650 940 : ARRAY_DEL_ELEMENT(global->channels, n, global->num_channels);
1651 940 : global->num_channels--;
1652 940 : if (global->num_channels == 0) {
1653 44 : struct smbXsrv_client *client = session->client;
1654 44 : struct tevent_queue *xconn_wait_queue =
1655 : xconn->transport.shutdown_wait_queue;
1656 44 : struct tevent_req *subreq = NULL;
1657 :
1658 : /*
1659 : * Let the connection wait until the session is
1660 : * destroyed.
1661 : *
1662 : * We don't set a callback, as we just want to block the
1663 : * wait queue and the talloc_free() of the session will
1664 : * remove the item from the wait queue in order
1665 : * to remove allow the connection to disappear.
1666 : */
1667 44 : if (xconn_wait_queue != NULL) {
1668 44 : subreq = tevent_queue_wait_send(session,
1669 : client->raw_ev_ctx,
1670 : xconn_wait_queue);
1671 44 : if (subreq == NULL) {
1672 0 : status = NT_STATUS_NO_MEMORY;
1673 0 : DBG_ERR("tevent_queue_wait_send() session(%llu) failed: %s\n",
1674 : (unsigned long long)session->global->session_wire_id,
1675 : nt_errstr(status));
1676 0 : return status;
1677 : }
1678 : }
1679 :
1680 : /*
1681 : * This is guaranteed to set
1682 : * session->status = NT_STATUS_USER_SESSION_DELETED
1683 : * even if NULL is returned.
1684 : */
1685 44 : subreq = smb2srv_session_shutdown_send(session,
1686 : client->raw_ev_ctx,
1687 : session,
1688 : NULL);
1689 44 : if (subreq == NULL) {
1690 0 : status = NT_STATUS_NO_MEMORY;
1691 0 : DBG_ERR("smb2srv_session_shutdown_send(%llu) failed: %s\n",
1692 : (unsigned long long)session->global->session_wire_id,
1693 : nt_errstr(status));
1694 0 : return status;
1695 : }
1696 44 : tevent_req_set_callback(subreq,
1697 : smbXsrv_session_remove_channel_done,
1698 : session);
1699 : }
1700 916 : need_update = true;
1701 : }
1702 :
1703 2002 : if (!need_update) {
1704 1086 : return NT_STATUS_OK;
1705 : }
1706 :
1707 940 : return smbXsrv_session_update(session);
1708 : }
1709 :
1710 44 : static void smbXsrv_session_remove_channel_done(struct tevent_req *subreq)
1711 : {
1712 4 : struct smbXsrv_session *session =
1713 44 : tevent_req_callback_data(subreq,
1714 : struct smbXsrv_session);
1715 4 : NTSTATUS status;
1716 :
1717 44 : status = smb2srv_session_shutdown_recv(subreq);
1718 44 : TALLOC_FREE(subreq);
1719 44 : if (!NT_STATUS_IS_OK(status)) {
1720 0 : DBG_ERR("smb2srv_session_shutdown_recv(%llu) failed: %s\n",
1721 : (unsigned long long)session->global->session_wire_id,
1722 : nt_errstr(status));
1723 : }
1724 :
1725 44 : status = smbXsrv_session_logoff(session);
1726 44 : if (!NT_STATUS_IS_OK(status)) {
1727 0 : DBG_ERR("smbXsrv_session_logoff(%llu) failed: %s\n",
1728 : (unsigned long long)session->global->session_wire_id,
1729 : nt_errstr(status));
1730 : }
1731 :
1732 44 : TALLOC_FREE(session);
1733 44 : }
1734 :
1735 : struct smb2srv_session_shutdown_state {
1736 : struct tevent_queue *wait_queue;
1737 : };
1738 :
1739 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
1740 :
1741 2531 : struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
1742 : struct tevent_context *ev,
1743 : struct smbXsrv_session *session,
1744 : struct smbd_smb2_request *current_req)
1745 : {
1746 21 : struct tevent_req *req;
1747 21 : struct smb2srv_session_shutdown_state *state;
1748 21 : struct tevent_req *subreq;
1749 2531 : struct smbXsrv_connection *xconn = NULL;
1750 2531 : size_t len = 0;
1751 :
1752 : /*
1753 : * Make sure that no new request will be able to use this session.
1754 : */
1755 2531 : session->status = NT_STATUS_USER_SESSION_DELETED;
1756 :
1757 2531 : req = tevent_req_create(mem_ctx, &state,
1758 : struct smb2srv_session_shutdown_state);
1759 2531 : if (req == NULL) {
1760 0 : return NULL;
1761 : }
1762 :
1763 2531 : state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
1764 2531 : if (tevent_req_nomem(state->wait_queue, req)) {
1765 0 : return tevent_req_post(req, ev);
1766 : }
1767 :
1768 5152 : for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
1769 33 : struct smbd_smb2_request *preq;
1770 :
1771 5092 : for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1772 2471 : if (preq == current_req) {
1773 : /* Can't cancel current request. */
1774 2433 : continue;
1775 : }
1776 38 : if (preq->session != session) {
1777 : /* Request on different session. */
1778 26 : continue;
1779 : }
1780 :
1781 12 : if (preq->subreq != NULL) {
1782 12 : tevent_req_cancel(preq->subreq);
1783 : }
1784 :
1785 : /*
1786 : * Now wait until the request is finished.
1787 : *
1788 : * We don't set a callback, as we just want to block the
1789 : * wait queue and the talloc_free() of the request will
1790 : * remove the item from the wait queue.
1791 : */
1792 12 : subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
1793 12 : if (tevent_req_nomem(subreq, req)) {
1794 0 : return tevent_req_post(req, ev);
1795 : }
1796 : }
1797 : }
1798 :
1799 2531 : len = tevent_queue_length(state->wait_queue);
1800 2531 : if (len == 0) {
1801 2519 : tevent_req_done(req);
1802 2519 : return tevent_req_post(req, ev);
1803 : }
1804 :
1805 : /*
1806 : * Now we add our own waiter to the end of the queue,
1807 : * this way we get notified when all pending requests are finished
1808 : * and send to the socket.
1809 : */
1810 12 : subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
1811 12 : if (tevent_req_nomem(subreq, req)) {
1812 0 : return tevent_req_post(req, ev);
1813 : }
1814 12 : tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
1815 :
1816 12 : return req;
1817 : }
1818 :
1819 12 : static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
1820 : {
1821 0 : struct tevent_req *req =
1822 12 : tevent_req_callback_data(subreq,
1823 : struct tevent_req);
1824 :
1825 12 : tevent_queue_wait_recv(subreq);
1826 12 : TALLOC_FREE(subreq);
1827 :
1828 12 : tevent_req_done(req);
1829 12 : }
1830 :
1831 2531 : NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
1832 : {
1833 2531 : return tevent_req_simple_recv_ntstatus(req);
1834 : }
1835 :
1836 61112 : NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
1837 : {
1838 1513 : struct smbXsrv_session_table *table;
1839 61112 : struct db_record *local_rec = NULL;
1840 61112 : struct db_record *global_rec = NULL;
1841 61112 : struct smbd_server_connection *sconn = NULL;
1842 1513 : NTSTATUS status;
1843 61112 : NTSTATUS error = NT_STATUS_OK;
1844 :
1845 61112 : if (session->table == NULL) {
1846 28815 : return NT_STATUS_OK;
1847 : }
1848 :
1849 32297 : table = session->table;
1850 32297 : session->table = NULL;
1851 :
1852 32297 : sconn = session->client->sconn;
1853 32297 : session->client = NULL;
1854 32297 : session->status = NT_STATUS_USER_SESSION_DELETED;
1855 :
1856 : /*
1857 : * For SMB2 this is a bit redundant as files are also close
1858 : * below via smb2srv_tcon_disconnect_all() -> ... ->
1859 : * smbXsrv_tcon_disconnect() -> close_cnum() ->
1860 : * file_close_conn().
1861 : */
1862 32297 : file_close_user(sconn, session->global->session_wire_id);
1863 :
1864 32297 : if (session->tcon_table != NULL) {
1865 : /*
1866 : * Note: We only have a tcon_table for SMB2.
1867 : */
1868 25504 : status = smb2srv_tcon_disconnect_all(session);
1869 25504 : if (!NT_STATUS_IS_OK(status)) {
1870 52 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1871 : "smb2srv_tcon_disconnect_all() failed: %s\n",
1872 : session->global->session_global_id,
1873 : nt_errstr(status));
1874 52 : error = status;
1875 : }
1876 : }
1877 :
1878 32297 : invalidate_vuid(sconn, session->global->session_wire_id);
1879 :
1880 32297 : global_rec = session->global->db_rec;
1881 32297 : session->global->db_rec = NULL;
1882 32297 : if (global_rec == NULL) {
1883 32297 : global_rec = smbXsrv_session_global_fetch_locked(
1884 : table->global.db_ctx,
1885 31537 : session->global->session_global_id,
1886 31537 : session->global /* TALLOC_CTX */);
1887 32297 : if (global_rec == NULL) {
1888 0 : error = NT_STATUS_INTERNAL_ERROR;
1889 : }
1890 : }
1891 :
1892 32297 : if (global_rec != NULL) {
1893 32297 : status = dbwrap_record_delete(global_rec);
1894 32297 : if (!NT_STATUS_IS_OK(status)) {
1895 0 : TDB_DATA key = dbwrap_record_get_key(global_rec);
1896 :
1897 0 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1898 : "failed to delete global key '%s': %s\n",
1899 : session->global->session_global_id,
1900 : tdb_data_dbg(key),
1901 : nt_errstr(status));
1902 0 : error = status;
1903 : }
1904 : }
1905 32297 : TALLOC_FREE(global_rec);
1906 :
1907 32297 : local_rec = session->db_rec;
1908 32297 : if (local_rec == NULL) {
1909 3751 : local_rec = smbXsrv_session_local_fetch_locked(
1910 : table->local.db_ctx,
1911 : session->local_id,
1912 : session /* TALLOC_CTX */);
1913 3751 : if (local_rec == NULL) {
1914 0 : error = NT_STATUS_INTERNAL_ERROR;
1915 : }
1916 : }
1917 :
1918 32297 : if (local_rec != NULL) {
1919 32297 : status = dbwrap_record_delete(local_rec);
1920 32297 : if (!NT_STATUS_IS_OK(status)) {
1921 0 : TDB_DATA key = dbwrap_record_get_key(local_rec);
1922 :
1923 0 : DBG_ERR("smbXsrv_session_logoff(0x%08x): "
1924 : "failed to delete local key '%s': %s\n",
1925 : session->global->session_global_id,
1926 : tdb_data_dbg(key),
1927 : nt_errstr(status));
1928 0 : error = status;
1929 : }
1930 32297 : table->local.num_sessions -= 1;
1931 : }
1932 32297 : if (session->db_rec == NULL) {
1933 3751 : TALLOC_FREE(local_rec);
1934 : }
1935 32297 : session->db_rec = NULL;
1936 :
1937 32297 : return error;
1938 : }
1939 :
1940 : struct smbXsrv_session_logoff_all_state {
1941 : NTSTATUS first_status;
1942 : int errors;
1943 : };
1944 :
1945 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1946 : void *private_data);
1947 :
1948 31037 : NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_client *client)
1949 : {
1950 31037 : struct smbXsrv_session_table *table = client->session_table;
1951 842 : struct smbXsrv_session_logoff_all_state state;
1952 842 : NTSTATUS status;
1953 31037 : int count = 0;
1954 :
1955 31037 : if (table == NULL) {
1956 559 : DBG_DEBUG("smbXsrv_session_logoff_all: "
1957 : "empty session_table, nothing to do.\n");
1958 559 : return NT_STATUS_OK;
1959 : }
1960 :
1961 30478 : ZERO_STRUCT(state);
1962 :
1963 30478 : status = dbwrap_traverse(table->local.db_ctx,
1964 : smbXsrv_session_logoff_all_callback,
1965 : &state, &count);
1966 30478 : if (!NT_STATUS_IS_OK(status)) {
1967 0 : DBG_ERR("smbXsrv_session_logoff_all: "
1968 : "dbwrap_traverse() failed: %s\n",
1969 : nt_errstr(status));
1970 0 : return status;
1971 : }
1972 :
1973 30478 : if (!NT_STATUS_IS_OK(state.first_status)) {
1974 50 : DBG_ERR("smbXsrv_session_logoff_all: "
1975 : "count[%d] errors[%d] first[%s]\n",
1976 : count, state.errors,
1977 : nt_errstr(state.first_status));
1978 50 : return state.first_status;
1979 : }
1980 :
1981 30428 : return NT_STATUS_OK;
1982 : }
1983 :
1984 28546 : static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1985 : void *private_data)
1986 : {
1987 28546 : struct smbXsrv_session_logoff_all_state *state =
1988 : (struct smbXsrv_session_logoff_all_state *)private_data;
1989 739 : TDB_DATA val;
1990 28546 : void *ptr = NULL;
1991 28546 : struct smbXsrv_session *session = NULL;
1992 739 : NTSTATUS status;
1993 :
1994 28546 : val = dbwrap_record_get_value(local_rec);
1995 28546 : if (val.dsize != sizeof(ptr)) {
1996 0 : status = NT_STATUS_INTERNAL_ERROR;
1997 0 : if (NT_STATUS_IS_OK(state->first_status)) {
1998 0 : state->first_status = status;
1999 : }
2000 0 : state->errors++;
2001 0 : return 0;
2002 : }
2003 :
2004 28546 : memcpy(&ptr, val.dptr, val.dsize);
2005 28546 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2006 :
2007 28546 : session->db_rec = local_rec;
2008 28546 : status = smbXsrv_session_clear_and_logoff(session);
2009 28546 : session->db_rec = NULL;
2010 28546 : if (!NT_STATUS_IS_OK(status)) {
2011 52 : if (NT_STATUS_IS_OK(state->first_status)) {
2012 50 : state->first_status = status;
2013 : }
2014 52 : state->errors++;
2015 52 : return 0;
2016 : }
2017 :
2018 27755 : return 0;
2019 : }
2020 :
2021 : struct smbXsrv_session_local_trav_state {
2022 : NTSTATUS status;
2023 : int (*caller_cb)(struct smbXsrv_session *session,
2024 : void *caller_data);
2025 : void *caller_data;
2026 : };
2027 :
2028 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
2029 : void *private_data);
2030 :
2031 0 : NTSTATUS smbXsrv_session_local_traverse(
2032 : struct smbXsrv_client *client,
2033 : int (*caller_cb)(struct smbXsrv_session *session,
2034 : void *caller_data),
2035 : void *caller_data)
2036 : {
2037 0 : struct smbXsrv_session_table *table = client->session_table;
2038 0 : struct smbXsrv_session_local_trav_state state;
2039 0 : NTSTATUS status;
2040 0 : int count = 0;
2041 :
2042 0 : state = (struct smbXsrv_session_local_trav_state) {
2043 : .status = NT_STATUS_OK,
2044 : .caller_cb = caller_cb,
2045 : .caller_data = caller_data,
2046 : };
2047 :
2048 0 : if (table == NULL) {
2049 0 : DBG_DEBUG("empty session_table, nothing to do.\n");
2050 0 : return NT_STATUS_OK;
2051 : }
2052 :
2053 0 : status = dbwrap_traverse(table->local.db_ctx,
2054 : smbXsrv_session_local_traverse_cb,
2055 : &state,
2056 : &count);
2057 0 : if (!NT_STATUS_IS_OK(status)) {
2058 0 : DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
2059 0 : return status;
2060 : }
2061 0 : if (!NT_STATUS_IS_OK(state.status)) {
2062 0 : DBG_ERR("count[%d] status[%s]\n",
2063 : count, nt_errstr(state.status));
2064 0 : return state.status;
2065 : }
2066 :
2067 0 : return NT_STATUS_OK;
2068 : }
2069 :
2070 0 : static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
2071 : void *private_data)
2072 : {
2073 0 : struct smbXsrv_session_local_trav_state *state =
2074 : (struct smbXsrv_session_local_trav_state *)private_data;
2075 0 : TDB_DATA val;
2076 0 : void *ptr = NULL;
2077 0 : struct smbXsrv_session *session = NULL;
2078 0 : int ret;
2079 :
2080 0 : val = dbwrap_record_get_value(local_rec);
2081 0 : if (val.dsize != sizeof(ptr)) {
2082 0 : state->status = NT_STATUS_INTERNAL_ERROR;
2083 0 : return -1;
2084 : }
2085 :
2086 0 : memcpy(&ptr, val.dptr, val.dsize);
2087 0 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2088 :
2089 0 : session->db_rec = local_rec;
2090 0 : ret = state->caller_cb(session, state->caller_data);
2091 0 : session->db_rec = NULL;
2092 :
2093 0 : return ret;
2094 : }
2095 :
2096 : struct smbXsrv_session_disconnect_xconn_state {
2097 : struct smbXsrv_connection *xconn;
2098 : NTSTATUS first_status;
2099 : int errors;
2100 : };
2101 :
2102 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
2103 : void *private_data);
2104 :
2105 1106 : NTSTATUS smbXsrv_session_disconnect_xconn(struct smbXsrv_connection *xconn)
2106 : {
2107 1106 : struct smbXsrv_client *client = xconn->client;
2108 1106 : struct smbXsrv_session_table *table = client->session_table;
2109 52 : struct smbXsrv_session_disconnect_xconn_state state;
2110 52 : NTSTATUS status;
2111 1106 : int count = 0;
2112 :
2113 1106 : if (table == NULL) {
2114 0 : DBG_ERR("empty session_table, nothing to do.\n");
2115 0 : return NT_STATUS_OK;
2116 : }
2117 :
2118 1106 : ZERO_STRUCT(state);
2119 1106 : state.xconn = xconn;
2120 :
2121 1106 : status = dbwrap_traverse(table->local.db_ctx,
2122 : smbXsrv_session_disconnect_xconn_callback,
2123 : &state, &count);
2124 1106 : if (!NT_STATUS_IS_OK(status)) {
2125 0 : DBG_ERR("dbwrap_traverse() failed: %s\n",
2126 : nt_errstr(status));
2127 0 : return status;
2128 : }
2129 :
2130 1106 : if (!NT_STATUS_IS_OK(state.first_status)) {
2131 0 : DBG_ERR("count[%d] errors[%d] first[%s]\n",
2132 : count, state.errors,
2133 : nt_errstr(state.first_status));
2134 0 : return state.first_status;
2135 : }
2136 :
2137 1106 : return NT_STATUS_OK;
2138 : }
2139 :
2140 1184 : static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
2141 : void *private_data)
2142 : {
2143 1184 : struct smbXsrv_session_disconnect_xconn_state *state =
2144 : (struct smbXsrv_session_disconnect_xconn_state *)private_data;
2145 62 : TDB_DATA val;
2146 1184 : void *ptr = NULL;
2147 1184 : struct smbXsrv_session *session = NULL;
2148 62 : NTSTATUS status;
2149 :
2150 1184 : val = dbwrap_record_get_value(local_rec);
2151 1184 : if (val.dsize != sizeof(ptr)) {
2152 0 : status = NT_STATUS_INTERNAL_ERROR;
2153 0 : if (NT_STATUS_IS_OK(state->first_status)) {
2154 0 : state->first_status = status;
2155 : }
2156 0 : state->errors++;
2157 0 : return 0;
2158 : }
2159 :
2160 1184 : memcpy(&ptr, val.dptr, val.dsize);
2161 1184 : session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2162 :
2163 1184 : session->db_rec = local_rec;
2164 1184 : status = smbXsrv_session_remove_channel(session, state->xconn);
2165 1184 : session->db_rec = NULL;
2166 1184 : if (!NT_STATUS_IS_OK(status)) {
2167 0 : if (NT_STATUS_IS_OK(state->first_status)) {
2168 0 : state->first_status = status;
2169 : }
2170 0 : state->errors++;
2171 : }
2172 :
2173 1122 : return 0;
2174 : }
2175 :
2176 5623 : NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn)
2177 : {
2178 : /*
2179 : * Allow a range from 1..65534 with 65534 values.
2180 : */
2181 5623 : return smbXsrv_session_table_init(conn, 1, UINT16_MAX - 1,
2182 : UINT16_MAX - 1);
2183 : }
2184 :
2185 671961 : NTSTATUS smb1srv_session_lookup(struct smbXsrv_connection *conn,
2186 : uint16_t vuid, NTTIME now,
2187 : struct smbXsrv_session **session)
2188 : {
2189 671961 : struct smbXsrv_session_table *table = conn->client->session_table;
2190 671961 : uint32_t local_id = vuid;
2191 :
2192 671961 : return smbXsrv_session_local_lookup(table, conn, local_id, now,
2193 : session);
2194 : }
2195 :
2196 1835242 : NTSTATUS smbXsrv_session_info_lookup(struct smbXsrv_client *client,
2197 : uint64_t session_wire_id,
2198 : struct auth_session_info **si)
2199 : {
2200 1835242 : struct smbXsrv_session_table *table = client->session_table;
2201 17509 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2202 1835242 : struct smbXsrv_session_local_fetch_state state = {
2203 : .session = NULL,
2204 : .status = NT_STATUS_INTERNAL_ERROR,
2205 : };
2206 17509 : TDB_DATA key;
2207 17509 : NTSTATUS status;
2208 :
2209 1835242 : if (session_wire_id == 0) {
2210 0 : return NT_STATUS_USER_SESSION_DELETED;
2211 : }
2212 :
2213 1835242 : if (table == NULL) {
2214 : /* this might happen before the end of negprot */
2215 0 : return NT_STATUS_USER_SESSION_DELETED;
2216 : }
2217 :
2218 1835242 : if (table->local.db_ctx == NULL) {
2219 0 : return NT_STATUS_INTERNAL_ERROR;
2220 : }
2221 :
2222 1835242 : key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2223 :
2224 1835242 : status = dbwrap_parse_record(table->local.db_ctx, key,
2225 : smbXsrv_session_local_fetch_parser,
2226 : &state);
2227 1835242 : if (!NT_STATUS_IS_OK(status)) {
2228 17 : return status;
2229 : }
2230 1835225 : if (!NT_STATUS_IS_OK(state.status)) {
2231 0 : return state.status;
2232 : }
2233 1835225 : if (state.session->global->auth_session_info == NULL) {
2234 0 : return NT_STATUS_USER_SESSION_DELETED;
2235 : }
2236 :
2237 1835225 : *si = state.session->global->auth_session_info;
2238 1835225 : return NT_STATUS_OK;
2239 : }
2240 :
2241 : /*
2242 : * In memory of get_valid_user_struct()
2243 : *
2244 : * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
2245 : * but it doesn't implement the state checks of
2246 : * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
2247 : * session wire-id of incoming SMB requests, it MUST only be used in later
2248 : * internal processing where the session wire-id has already been validated.
2249 : */
2250 32610 : NTSTATUS get_valid_smbXsrv_session(struct smbXsrv_client *client,
2251 : uint64_t session_wire_id,
2252 : struct smbXsrv_session **session)
2253 : {
2254 32610 : struct smbXsrv_session_table *table = client->session_table;
2255 760 : uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2256 32610 : struct smbXsrv_session_local_fetch_state state = {
2257 : .session = NULL,
2258 : .status = NT_STATUS_INTERNAL_ERROR,
2259 : };
2260 760 : TDB_DATA key;
2261 760 : NTSTATUS status;
2262 :
2263 32610 : if (session_wire_id == 0) {
2264 0 : return NT_STATUS_USER_SESSION_DELETED;
2265 : }
2266 :
2267 32610 : if (table == NULL) {
2268 : /* this might happen before the end of negprot */
2269 0 : return NT_STATUS_USER_SESSION_DELETED;
2270 : }
2271 :
2272 32610 : if (table->local.db_ctx == NULL) {
2273 0 : return NT_STATUS_INTERNAL_ERROR;
2274 : }
2275 :
2276 32610 : key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2277 :
2278 32610 : status = dbwrap_parse_record(table->local.db_ctx, key,
2279 : smbXsrv_session_local_fetch_parser,
2280 : &state);
2281 32610 : if (!NT_STATUS_IS_OK(status)) {
2282 0 : return status;
2283 : }
2284 32610 : if (!NT_STATUS_IS_OK(state.status)) {
2285 0 : return state.status;
2286 : }
2287 32610 : if (state.session->global->auth_session_info == NULL) {
2288 3455 : return NT_STATUS_USER_SESSION_DELETED;
2289 : }
2290 :
2291 29155 : *session = state.session;
2292 29155 : return NT_STATUS_OK;
2293 : }
2294 :
2295 26673 : NTSTATUS smb2srv_session_lookup_global(struct smbXsrv_client *client,
2296 : uint64_t session_wire_id,
2297 : TALLOC_CTX *mem_ctx,
2298 : struct smbXsrv_session **_session)
2299 : {
2300 26673 : TALLOC_CTX *frame = talloc_stackframe();
2301 26673 : struct smbXsrv_session_table *table = client->session_table;
2302 26673 : uint32_t global_id = session_wire_id & UINT32_MAX;
2303 26673 : uint64_t global_zeros = session_wire_id & 0xFFFFFFFF00000000LLU;
2304 26673 : struct smbXsrv_session *session = NULL;
2305 26673 : struct db_record *global_rec = NULL;
2306 26673 : bool is_free = false;
2307 832 : NTSTATUS status;
2308 :
2309 26673 : if (global_id == 0) {
2310 25506 : TALLOC_FREE(frame);
2311 25506 : return NT_STATUS_USER_SESSION_DELETED;
2312 : }
2313 1167 : if (global_zeros != 0) {
2314 0 : TALLOC_FREE(frame);
2315 0 : return NT_STATUS_USER_SESSION_DELETED;
2316 : }
2317 :
2318 1167 : if (table == NULL) {
2319 : /* this might happen before the end of negprot */
2320 0 : TALLOC_FREE(frame);
2321 0 : return NT_STATUS_USER_SESSION_DELETED;
2322 : }
2323 :
2324 1167 : if (table->global.db_ctx == NULL) {
2325 0 : TALLOC_FREE(frame);
2326 0 : return NT_STATUS_INTERNAL_ERROR;
2327 : }
2328 :
2329 1167 : session = talloc_zero(mem_ctx, struct smbXsrv_session);
2330 1167 : if (session == NULL) {
2331 0 : TALLOC_FREE(frame);
2332 0 : return NT_STATUS_NO_MEMORY;
2333 : }
2334 1167 : talloc_steal(frame, session);
2335 :
2336 1167 : session->client = client;
2337 1167 : session->status = NT_STATUS_BAD_LOGON_SESSION_STATE;
2338 1167 : session->local_id = global_id;
2339 :
2340 : /*
2341 : * This means smb2_get_new_nonce() will return
2342 : * NT_STATUS_ENCRYPTION_FAILED.
2343 : *
2344 : * But we initialize some random parts just in case...
2345 : */
2346 1167 : session->nonce_high_max = session->nonce_high = 0;
2347 1167 : generate_nonce_buffer((uint8_t *)&session->nonce_high_random,
2348 : sizeof(session->nonce_high_random));
2349 1167 : generate_nonce_buffer((uint8_t *)&session->nonce_low,
2350 : sizeof(session->nonce_low));
2351 :
2352 1167 : global_rec = smbXsrv_session_global_fetch_locked(table->global.db_ctx,
2353 : global_id,
2354 : frame);
2355 1167 : if (global_rec == NULL) {
2356 0 : TALLOC_FREE(frame);
2357 0 : return NT_STATUS_INTERNAL_DB_ERROR;
2358 : }
2359 :
2360 1167 : smbXsrv_session_global_verify_record(global_rec,
2361 : &is_free,
2362 : NULL,
2363 : session,
2364 1167 : &session->global,
2365 : NULL);
2366 1167 : if (is_free) {
2367 10 : TALLOC_FREE(frame);
2368 10 : return NT_STATUS_USER_SESSION_DELETED;
2369 : }
2370 :
2371 : /*
2372 : * We don't have channels on this session
2373 : * and only the main signing key
2374 : */
2375 1157 : session->global->num_channels = 0;
2376 1362 : status = smb2_signing_key_sign_create(session->global,
2377 1157 : session->global->signing_algo,
2378 : NULL, /* no master key */
2379 : NULL, /* derivations */
2380 952 : &session->global->signing_key);
2381 1157 : if (!NT_STATUS_IS_OK(status)) {
2382 0 : TALLOC_FREE(frame);
2383 0 : return NT_STATUS_NO_MEMORY;
2384 : }
2385 1157 : session->global->signing_key->blob = session->global->signing_key_blob;
2386 1157 : session->global->signing_flags = 0;
2387 :
2388 1362 : status = smb2_signing_key_cipher_create(session->global,
2389 1157 : session->global->encryption_cipher,
2390 : NULL, /* no master key */
2391 : NULL, /* derivations */
2392 952 : &session->global->decryption_key);
2393 1157 : if (!NT_STATUS_IS_OK(status)) {
2394 0 : TALLOC_FREE(frame);
2395 0 : return NT_STATUS_NO_MEMORY;
2396 : }
2397 1157 : session->global->decryption_key->blob = session->global->decryption_key_blob;
2398 1157 : session->global->encryption_flags = 0;
2399 :
2400 1157 : *_session = talloc_move(mem_ctx, &session);
2401 1157 : TALLOC_FREE(frame);
2402 1157 : return NT_STATUS_OK;
2403 : }
2404 :
2405 24869 : NTSTATUS smb2srv_session_table_init(struct smbXsrv_connection *conn)
2406 : {
2407 : /*
2408 : * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
2409 : */
2410 24869 : return smbXsrv_session_table_init(conn, 1, UINT32_MAX - 1,
2411 : UINT16_MAX - 1);
2412 : }
2413 :
2414 1482759 : static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
2415 : /* conn: optional */
2416 : struct smbXsrv_connection *conn,
2417 : uint64_t session_id, NTTIME now,
2418 : struct smbXsrv_session **session)
2419 : {
2420 1482759 : uint32_t local_id = session_id & UINT32_MAX;
2421 1482759 : uint64_t local_zeros = session_id & 0xFFFFFFFF00000000LLU;
2422 :
2423 1482759 : if (local_zeros != 0) {
2424 24 : return NT_STATUS_USER_SESSION_DELETED;
2425 : }
2426 :
2427 1482735 : return smbXsrv_session_local_lookup(table, conn, local_id, now,
2428 : session);
2429 : }
2430 :
2431 1435347 : NTSTATUS smb2srv_session_lookup_conn(struct smbXsrv_connection *conn,
2432 : uint64_t session_id, NTTIME now,
2433 : struct smbXsrv_session **session)
2434 : {
2435 1435347 : struct smbXsrv_session_table *table = conn->client->session_table;
2436 1435347 : return smb2srv_session_lookup_raw(table, conn, session_id, now,
2437 : session);
2438 : }
2439 :
2440 47412 : NTSTATUS smb2srv_session_lookup_client(struct smbXsrv_client *client,
2441 : uint64_t session_id, NTTIME now,
2442 : struct smbXsrv_session **session)
2443 : {
2444 47412 : struct smbXsrv_session_table *table = client->session_table;
2445 47412 : return smb2srv_session_lookup_raw(table, NULL, session_id, now,
2446 : session);
2447 : }
2448 :
2449 : struct smbXsrv_session_global_traverse_state {
2450 : int (*fn)(struct smbXsrv_session_global0 *, void *);
2451 : void *private_data;
2452 : };
2453 :
2454 46 : static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
2455 : {
2456 46 : int ret = -1;
2457 46 : struct smbXsrv_session_global_traverse_state *state =
2458 : (struct smbXsrv_session_global_traverse_state*)data;
2459 46 : TDB_DATA key = dbwrap_record_get_key(rec);
2460 46 : TDB_DATA val = dbwrap_record_get_value(rec);
2461 46 : DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
2462 0 : struct smbXsrv_session_globalB global_blob;
2463 0 : enum ndr_err_code ndr_err;
2464 46 : TALLOC_CTX *frame = talloc_stackframe();
2465 :
2466 46 : ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
2467 : (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
2468 46 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2469 0 : DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2470 : "key '%s' ndr_pull_struct_blob - %s\n",
2471 : tdb_data_dbg(key),
2472 : ndr_errstr(ndr_err));
2473 0 : goto done;
2474 : }
2475 :
2476 46 : if (global_blob.version != SMBXSRV_VERSION_0) {
2477 0 : DBG_WARNING("Invalid record in smbXsrv_session_global.tdb:"
2478 : "key '%s' unsupported version - %d\n",
2479 : tdb_data_dbg(key),
2480 : (int)global_blob.version);
2481 0 : goto done;
2482 : }
2483 :
2484 46 : if (global_blob.info.info0 == NULL) {
2485 0 : DBG_WARNING("Invalid record in smbXsrv_tcon_global.tdb:"
2486 : "key '%s' info0 NULL pointer\n",
2487 : tdb_data_dbg(key));
2488 0 : goto done;
2489 : }
2490 :
2491 46 : global_blob.info.info0->db_rec = rec;
2492 46 : ret = state->fn(global_blob.info.info0, state->private_data);
2493 46 : done:
2494 46 : TALLOC_FREE(frame);
2495 46 : return ret;
2496 : }
2497 :
2498 42 : NTSTATUS smbXsrv_session_global_traverse(
2499 : int (*fn)(struct smbXsrv_session_global0 *, void *),
2500 : void *private_data)
2501 : {
2502 :
2503 0 : NTSTATUS status;
2504 42 : int count = 0;
2505 42 : struct smbXsrv_session_global_traverse_state state = {
2506 : .fn = fn,
2507 : .private_data = private_data,
2508 : };
2509 :
2510 42 : become_root();
2511 42 : status = smbXsrv_session_global_init(NULL);
2512 42 : if (!NT_STATUS_IS_OK(status)) {
2513 0 : unbecome_root();
2514 0 : DBG_ERR("Failed to initialize session_global: %s\n",
2515 : nt_errstr(status));
2516 0 : return status;
2517 : }
2518 :
2519 42 : status = dbwrap_traverse_read(smbXsrv_session_global_db_ctx,
2520 : smbXsrv_session_global_traverse_fn,
2521 : &state,
2522 : &count);
2523 42 : unbecome_root();
2524 :
2525 42 : return status;
2526 : }
|