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