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