smbd: make use of smb2_signing_key_{copy,sign_create,cipher_create}() helpers
[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
1166         smb2srv_session_close_previous_check(req);
1167 }
1168
1169 NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
1170 {
1171         NTSTATUS status;
1172
1173         if (tevent_req_is_nterror(req, &status)) {
1174                 tevent_req_received(req);
1175                 return status;
1176         }
1177
1178         tevent_req_received(req);
1179         return NT_STATUS_OK;
1180 }
1181
1182 static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session)
1183 {
1184         NTSTATUS status;
1185         struct smbXsrv_connection *xconn = NULL;
1186
1187         if (session->client != NULL) {
1188                 xconn = session->client->connections;
1189         }
1190
1191         for (; xconn != NULL; xconn = xconn->next) {
1192                 struct smbd_smb2_request *preq;
1193
1194                 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1195                         if (preq->session != session) {
1196                                 continue;
1197                         }
1198
1199                         preq->session = NULL;
1200                         /*
1201                          * If we no longer have a session we can't
1202                          * sign or encrypt replies.
1203                          */
1204                         preq->do_signing = false;
1205                         preq->do_encryption = false;
1206                         preq->preauth = NULL;
1207                 }
1208         }
1209
1210         status = smbXsrv_session_logoff(session);
1211         return status;
1212 }
1213
1214 static int smbXsrv_session_destructor(struct smbXsrv_session *session)
1215 {
1216         NTSTATUS status;
1217
1218         status = smbXsrv_session_clear_and_logoff(session);
1219         if (!NT_STATUS_IS_OK(status)) {
1220                 DEBUG(0, ("smbXsrv_session_destructor: "
1221                           "smbXsrv_session_logoff() failed: %s\n",
1222                           nt_errstr(status)));
1223         }
1224
1225         TALLOC_FREE(session->global);
1226
1227         return 0;
1228 }
1229
1230 NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
1231                                 NTTIME now,
1232                                 struct smbXsrv_session **_session)
1233 {
1234         struct smbXsrv_session_table *table = conn->client->session_table;
1235         struct db_record *local_rec = NULL;
1236         struct smbXsrv_session *session = NULL;
1237         void *ptr = NULL;
1238         TDB_DATA val;
1239         struct smbXsrv_session_global0 *global = NULL;
1240         struct smbXsrv_channel_global0 *channel = NULL;
1241         NTSTATUS status;
1242
1243         if (table->local.num_sessions >= table->local.max_sessions) {
1244                 return NT_STATUS_INSUFFICIENT_RESOURCES;
1245         }
1246
1247         session = talloc_zero(table, struct smbXsrv_session);
1248         if (session == NULL) {
1249                 return NT_STATUS_NO_MEMORY;
1250         }
1251         session->table = table;
1252         session->idle_time = now;
1253         session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
1254         session->client = conn->client;
1255         session->homes_snum = -1;
1256
1257         status = smbXsrv_session_global_allocate(table->global.db_ctx,
1258                                                  session,
1259                                                  &global);
1260         if (!NT_STATUS_IS_OK(status)) {
1261                 TALLOC_FREE(session);
1262                 return status;
1263         }
1264         session->global = global;
1265
1266         if (conn->protocol >= PROTOCOL_SMB2_02) {
1267                 uint64_t id = global->session_global_id;
1268
1269                 global->connection_dialect = conn->smb2.server.dialect;
1270
1271                 global->session_wire_id = id;
1272
1273                 status = smb2srv_tcon_table_init(session);
1274                 if (!NT_STATUS_IS_OK(status)) {
1275                         TALLOC_FREE(session);
1276                         return status;
1277                 }
1278
1279                 session->local_id = global->session_global_id;
1280
1281                 local_rec = smbXsrv_session_local_fetch_locked(
1282                                                 table->local.db_ctx,
1283                                                 session->local_id,
1284                                                 session /* TALLOC_CTX */);
1285                 if (local_rec == NULL) {
1286                         TALLOC_FREE(session);
1287                         return NT_STATUS_NO_MEMORY;
1288                 }
1289
1290                 val = dbwrap_record_get_value(local_rec);
1291                 if (val.dsize != 0) {
1292                         TALLOC_FREE(session);
1293                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1294                 }
1295         } else {
1296
1297                 status = smb1srv_session_local_allocate_id(table->local.db_ctx,
1298                                                         table->local.lowest_id,
1299                                                         table->local.highest_id,
1300                                                         session,
1301                                                         &local_rec,
1302                                                         &session->local_id);
1303                 if (!NT_STATUS_IS_OK(status)) {
1304                         TALLOC_FREE(session);
1305                         return status;
1306                 }
1307
1308                 global->session_wire_id = session->local_id;
1309         }
1310
1311         global->creation_time = now;
1312         global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1313
1314         status = smbXsrv_session_add_channel(session, conn, now, &channel);
1315         if (!NT_STATUS_IS_OK(status)) {
1316                 TALLOC_FREE(session);
1317                 return status;
1318         }
1319
1320         ptr = session;
1321         val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
1322         status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
1323         TALLOC_FREE(local_rec);
1324         if (!NT_STATUS_IS_OK(status)) {
1325                 TALLOC_FREE(session);
1326                 return status;
1327         }
1328         table->local.num_sessions += 1;
1329
1330         talloc_set_destructor(session, smbXsrv_session_destructor);
1331
1332         status = smbXsrv_session_global_store(global);
1333         if (!NT_STATUS_IS_OK(status)) {
1334                 DEBUG(0,("smbXsrv_session_create: "
1335                          "global_id (0x%08x) store failed - %s\n",
1336                          session->global->session_global_id,
1337                          nt_errstr(status)));
1338                 TALLOC_FREE(session);
1339                 return status;
1340         }
1341
1342         if (DEBUGLVL(10)) {
1343                 struct smbXsrv_sessionB session_blob = {
1344                         .version = SMBXSRV_VERSION_0,
1345                         .info.info0 = session,
1346                 };
1347
1348                 DEBUG(10,("smbXsrv_session_create: global_id (0x%08x) stored\n",
1349                          session->global->session_global_id));
1350                 NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1351         }
1352
1353         *_session = session;
1354         return NT_STATUS_OK;
1355 }
1356
1357 NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session,
1358                                      struct smbXsrv_connection *conn,
1359                                      NTTIME now,
1360                                      struct smbXsrv_channel_global0 **_c)
1361 {
1362         struct smbXsrv_session_global0 *global = session->global;
1363         struct smbXsrv_channel_global0 *c = NULL;
1364
1365         if (global->num_channels > 31) {
1366                 /*
1367                  * Windows allow up to 32 channels
1368                  */
1369                 return NT_STATUS_INSUFFICIENT_RESOURCES;
1370         }
1371
1372         c = talloc_realloc(global,
1373                            global->channels,
1374                            struct smbXsrv_channel_global0,
1375                            global->num_channels + 1);
1376         if (c == NULL) {
1377                 return NT_STATUS_NO_MEMORY;
1378         }
1379         global->channels = c;
1380
1381         c = &global->channels[global->num_channels];
1382         ZERO_STRUCTP(c);
1383
1384         c->server_id = messaging_server_id(conn->client->msg_ctx);
1385         c->channel_id = conn->channel_id;
1386         c->creation_time = now;
1387         c->local_address = tsocket_address_string(conn->local_address,
1388                                                   global->channels);
1389         if (c->local_address == NULL) {
1390                 return NT_STATUS_NO_MEMORY;
1391         }
1392         c->remote_address = tsocket_address_string(conn->remote_address,
1393                                                    global->channels);
1394         if (c->remote_address == NULL) {
1395                 return NT_STATUS_NO_MEMORY;
1396         }
1397         c->remote_name = talloc_strdup(global->channels,
1398                                        conn->remote_hostname);
1399         if (c->remote_name == NULL) {
1400                 return NT_STATUS_NO_MEMORY;
1401         }
1402         c->connection = conn;
1403
1404         global->num_channels += 1;
1405
1406         *_c = c;
1407         return NT_STATUS_OK;
1408 }
1409
1410 NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session)
1411 {
1412         struct smbXsrv_session_table *table = session->table;
1413         NTSTATUS status;
1414
1415         if (session->global->db_rec != NULL) {
1416                 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1417                           "Called with db_rec != NULL'\n",
1418                           session->global->session_global_id));
1419                 return NT_STATUS_INTERNAL_ERROR;
1420         }
1421
1422         session->global->db_rec = smbXsrv_session_global_fetch_locked(
1423                                         table->global.db_ctx,
1424                                         session->global->session_global_id,
1425                                         session->global /* TALLOC_CTX */);
1426         if (session->global->db_rec == NULL) {
1427                 return NT_STATUS_INTERNAL_DB_ERROR;
1428         }
1429
1430         status = smbXsrv_session_global_store(session->global);
1431         if (!NT_STATUS_IS_OK(status)) {
1432                 DEBUG(0,("smbXsrv_session_update: "
1433                          "global_id (0x%08x) store failed - %s\n",
1434                          session->global->session_global_id,
1435                          nt_errstr(status)));
1436                 return status;
1437         }
1438
1439         if (DEBUGLVL(10)) {
1440                 struct smbXsrv_sessionB session_blob = {
1441                         .version = SMBXSRV_VERSION_0,
1442                         .info.info0 = session,
1443                 };
1444
1445                 DEBUG(10,("smbXsrv_session_update: global_id (0x%08x) stored\n",
1446                           session->global->session_global_id));
1447                 NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1448         }
1449
1450         return NT_STATUS_OK;
1451 }
1452
1453 NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
1454                                       const struct smbXsrv_connection *conn,
1455                                       struct smbXsrv_channel_global0 **_c)
1456 {
1457         uint32_t i;
1458
1459         for (i=0; i < session->global->num_channels; i++) {
1460                 struct smbXsrv_channel_global0 *c = &session->global->channels[i];
1461
1462                 if (c->channel_id != conn->channel_id) {
1463                         continue;
1464                 }
1465
1466                 if (c->connection != conn) {
1467                         continue;
1468                 }
1469
1470                 *_c = c;
1471                 return NT_STATUS_OK;
1472         }
1473
1474         return NT_STATUS_USER_SESSION_DELETED;
1475 }
1476
1477 NTSTATUS smbXsrv_session_find_auth(const struct smbXsrv_session *session,
1478                                    const struct smbXsrv_connection *conn,
1479                                    NTTIME now,
1480                                    struct smbXsrv_session_auth0 **_a)
1481 {
1482         struct smbXsrv_session_auth0 *a;
1483
1484         for (a = session->pending_auth; a != NULL; a = a->next) {
1485                 if (a->channel_id != conn->channel_id) {
1486                         continue;
1487                 }
1488
1489                 if (a->connection == conn) {
1490                         if (now != 0) {
1491                                 a->idle_time = now;
1492                         }
1493                         *_a = a;
1494                         return NT_STATUS_OK;
1495                 }
1496         }
1497
1498         return NT_STATUS_USER_SESSION_DELETED;
1499 }
1500
1501 static int smbXsrv_session_auth0_destructor(struct smbXsrv_session_auth0 *a)
1502 {
1503         if (a->session == NULL) {
1504                 return 0;
1505         }
1506
1507         DLIST_REMOVE(a->session->pending_auth, a);
1508         a->session = NULL;
1509         return 0;
1510 }
1511
1512 NTSTATUS smbXsrv_session_create_auth(struct smbXsrv_session *session,
1513                                      struct smbXsrv_connection *conn,
1514                                      NTTIME now,
1515                                      uint8_t in_flags,
1516                                      uint8_t in_security_mode,
1517                                      struct smbXsrv_session_auth0 **_a)
1518 {
1519         struct smbXsrv_session_auth0 *a;
1520         NTSTATUS status;
1521
1522         status = smbXsrv_session_find_auth(session, conn, 0, &a);
1523         if (NT_STATUS_IS_OK(status)) {
1524                 return NT_STATUS_INTERNAL_ERROR;
1525         }
1526
1527         a = talloc_zero(session, struct smbXsrv_session_auth0);
1528         if (a == NULL) {
1529                 return NT_STATUS_NO_MEMORY;
1530         }
1531         a->session = session;
1532         a->connection = conn;
1533         a->in_flags = in_flags;
1534         a->in_security_mode = in_security_mode;
1535         a->creation_time = now;
1536         a->idle_time = now;
1537         a->channel_id = conn->channel_id;
1538
1539         if (conn->protocol >= PROTOCOL_SMB3_10) {
1540                 a->preauth = talloc(a, struct smbXsrv_preauth);
1541                 if (a->preauth == NULL) {
1542                         TALLOC_FREE(session);
1543                         return NT_STATUS_NO_MEMORY;
1544                 }
1545                 *a->preauth = conn->smb2.preauth;
1546         }
1547
1548         talloc_set_destructor(a, smbXsrv_session_auth0_destructor);
1549         DLIST_ADD_END(session->pending_auth, a);
1550
1551         *_a = a;
1552         return NT_STATUS_OK;
1553 }
1554
1555 struct smb2srv_session_shutdown_state {
1556         struct tevent_queue *wait_queue;
1557 };
1558
1559 static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
1560
1561 struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
1562                                         struct tevent_context *ev,
1563                                         struct smbXsrv_session *session,
1564                                         struct smbd_smb2_request *current_req)
1565 {
1566         struct tevent_req *req;
1567         struct smb2srv_session_shutdown_state *state;
1568         struct tevent_req *subreq;
1569         struct smbXsrv_connection *xconn = NULL;
1570         size_t len = 0;
1571
1572         /*
1573          * Make sure that no new request will be able to use this session.
1574          */
1575         session->status = NT_STATUS_USER_SESSION_DELETED;
1576
1577         req = tevent_req_create(mem_ctx, &state,
1578                                 struct smb2srv_session_shutdown_state);
1579         if (req == NULL) {
1580                 return NULL;
1581         }
1582
1583         state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
1584         if (tevent_req_nomem(state->wait_queue, req)) {
1585                 return tevent_req_post(req, ev);
1586         }
1587
1588         for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
1589                 struct smbd_smb2_request *preq;
1590
1591                 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1592                         if (preq == current_req) {
1593                                 /* Can't cancel current request. */
1594                                 continue;
1595                         }
1596                         if (preq->session != session) {
1597                                 /* Request on different session. */
1598                                 continue;
1599                         }
1600
1601                         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1602                                 preq->session = NULL;
1603                                 /*
1604                                  * If we no longer have a session we can't
1605                                  * sign or encrypt replies.
1606                                  */
1607                                 preq->do_signing = false;
1608                                 preq->do_encryption = false;
1609                                 preq->preauth = NULL;
1610
1611                                 if (preq->subreq != NULL) {
1612                                         tevent_req_cancel(preq->subreq);
1613                                 }
1614                                 continue;
1615                         }
1616
1617                         /*
1618                          * Never cancel anything in a compound
1619                          * request. Way too hard to deal with
1620                          * the result.
1621                          */
1622                         if (!preq->compound_related && preq->subreq != NULL) {
1623                                 tevent_req_cancel(preq->subreq);
1624                         }
1625
1626                         /*
1627                          * Now wait until the request is finished.
1628                          *
1629                          * We don't set a callback, as we just want to block the
1630                          * wait queue and the talloc_free() of the request will
1631                          * remove the item from the wait queue.
1632                          */
1633                         subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
1634                         if (tevent_req_nomem(subreq, req)) {
1635                                 return tevent_req_post(req, ev);
1636                         }
1637                 }
1638         }
1639
1640         len = tevent_queue_length(state->wait_queue);
1641         if (len == 0) {
1642                 tevent_req_done(req);
1643                 return tevent_req_post(req, ev);
1644         }
1645
1646         /*
1647          * Now we add our own waiter to the end of the queue,
1648          * this way we get notified when all pending requests are finished
1649          * and send to the socket.
1650          */
1651         subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
1652         if (tevent_req_nomem(subreq, req)) {
1653                 return tevent_req_post(req, ev);
1654         }
1655         tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
1656
1657         return req;
1658 }
1659
1660 static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
1661 {
1662         struct tevent_req *req =
1663                 tevent_req_callback_data(subreq,
1664                 struct tevent_req);
1665
1666         tevent_queue_wait_recv(subreq);
1667         TALLOC_FREE(subreq);
1668
1669         tevent_req_done(req);
1670 }
1671
1672 NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
1673 {
1674         return tevent_req_simple_recv_ntstatus(req);
1675 }
1676
1677 NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
1678 {
1679         struct smbXsrv_session_table *table;
1680         struct db_record *local_rec = NULL;
1681         struct db_record *global_rec = NULL;
1682         struct smbd_server_connection *sconn = NULL;
1683         NTSTATUS status;
1684         NTSTATUS error = NT_STATUS_OK;
1685
1686         if (session->table == NULL) {
1687                 return NT_STATUS_OK;
1688         }
1689
1690         table = session->table;
1691         session->table = NULL;
1692
1693         sconn = session->client->sconn;
1694         session->client = NULL;
1695         session->status = NT_STATUS_USER_SESSION_DELETED;
1696
1697         /*
1698          * For SMB2 this is a bit redundant as files are also close
1699          * below via smb2srv_tcon_disconnect_all() -> ... ->
1700          * smbXsrv_tcon_disconnect() -> close_cnum() ->
1701          * file_close_conn().
1702          */
1703         file_close_user(sconn, session->global->session_wire_id);
1704
1705         if (session->tcon_table != NULL) {
1706                 /*
1707                  * Note: We only have a tcon_table for SMB2.
1708                  */
1709                 status = smb2srv_tcon_disconnect_all(session);
1710                 if (!NT_STATUS_IS_OK(status)) {
1711                         DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1712                                   "smb2srv_tcon_disconnect_all() failed: %s\n",
1713                                   session->global->session_global_id,
1714                                   nt_errstr(status)));
1715                         error = status;
1716                 }
1717         }
1718
1719         invalidate_vuid(sconn, session->global->session_wire_id);
1720
1721         global_rec = session->global->db_rec;
1722         session->global->db_rec = NULL;
1723         if (global_rec == NULL) {
1724                 global_rec = smbXsrv_session_global_fetch_locked(
1725                                         table->global.db_ctx,
1726                                         session->global->session_global_id,
1727                                         session->global /* TALLOC_CTX */);
1728                 if (global_rec == NULL) {
1729                         error = NT_STATUS_INTERNAL_ERROR;
1730                 }
1731         }
1732
1733         if (global_rec != NULL) {
1734                 status = dbwrap_record_delete(global_rec);
1735                 if (!NT_STATUS_IS_OK(status)) {
1736                         TDB_DATA key = dbwrap_record_get_key(global_rec);
1737
1738                         DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1739                                   "failed to delete global key '%s': %s\n",
1740                                   session->global->session_global_id,
1741                                   hex_encode_talloc(global_rec, key.dptr,
1742                                                     key.dsize),
1743                                   nt_errstr(status)));
1744                         error = status;
1745                 }
1746         }
1747         TALLOC_FREE(global_rec);
1748
1749         local_rec = session->db_rec;
1750         if (local_rec == NULL) {
1751                 local_rec = smbXsrv_session_local_fetch_locked(
1752                                                 table->local.db_ctx,
1753                                                 session->local_id,
1754                                                 session /* TALLOC_CTX */);
1755                 if (local_rec == NULL) {
1756                         error = NT_STATUS_INTERNAL_ERROR;
1757                 }
1758         }
1759
1760         if (local_rec != NULL) {
1761                 status = dbwrap_record_delete(local_rec);
1762                 if (!NT_STATUS_IS_OK(status)) {
1763                         TDB_DATA key = dbwrap_record_get_key(local_rec);
1764
1765                         DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1766                                   "failed to delete local key '%s': %s\n",
1767                                   session->global->session_global_id,
1768                                   hex_encode_talloc(local_rec, key.dptr,
1769                                                     key.dsize),
1770                                   nt_errstr(status)));
1771                         error = status;
1772                 }
1773                 table->local.num_sessions -= 1;
1774         }
1775         if (session->db_rec == NULL) {
1776                 TALLOC_FREE(local_rec);
1777         }
1778         session->db_rec = NULL;
1779
1780         return error;
1781 }
1782
1783 struct smbXsrv_session_logoff_all_state {
1784         NTSTATUS first_status;
1785         int errors;
1786 };
1787
1788 static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1789                                                void *private_data);
1790
1791 NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_client *client)
1792 {
1793         struct smbXsrv_session_table *table = client->session_table;
1794         struct smbXsrv_session_logoff_all_state state;
1795         NTSTATUS status;
1796         int count = 0;
1797
1798         if (table == NULL) {
1799                 DEBUG(10, ("smbXsrv_session_logoff_all: "
1800                            "empty session_table, nothing to do.\n"));
1801                 return NT_STATUS_OK;
1802         }
1803
1804         ZERO_STRUCT(state);
1805
1806         status = dbwrap_traverse(table->local.db_ctx,
1807                                  smbXsrv_session_logoff_all_callback,
1808                                  &state, &count);
1809         if (!NT_STATUS_IS_OK(status)) {
1810                 DEBUG(0, ("smbXsrv_session_logoff_all: "
1811                           "dbwrap_traverse() failed: %s\n",
1812                           nt_errstr(status)));
1813                 return status;
1814         }
1815
1816         if (!NT_STATUS_IS_OK(state.first_status)) {
1817                 DEBUG(0, ("smbXsrv_session_logoff_all: "
1818                           "count[%d] errors[%d] first[%s]\n",
1819                           count, state.errors,
1820                           nt_errstr(state.first_status)));
1821                 return state.first_status;
1822         }
1823
1824         return NT_STATUS_OK;
1825 }
1826
1827 static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1828                                                void *private_data)
1829 {
1830         struct smbXsrv_session_logoff_all_state *state =
1831                 (struct smbXsrv_session_logoff_all_state *)private_data;
1832         TDB_DATA val;
1833         void *ptr = NULL;
1834         struct smbXsrv_session *session = NULL;
1835         NTSTATUS status;
1836
1837         val = dbwrap_record_get_value(local_rec);
1838         if (val.dsize != sizeof(ptr)) {
1839                 status = NT_STATUS_INTERNAL_ERROR;
1840                 if (NT_STATUS_IS_OK(state->first_status)) {
1841                         state->first_status = status;
1842                 }
1843                 state->errors++;
1844                 return 0;
1845         }
1846
1847         memcpy(&ptr, val.dptr, val.dsize);
1848         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
1849
1850         session->db_rec = local_rec;
1851         status = smbXsrv_session_clear_and_logoff(session);
1852         session->db_rec = NULL;
1853         if (!NT_STATUS_IS_OK(status)) {
1854                 if (NT_STATUS_IS_OK(state->first_status)) {
1855                         state->first_status = status;
1856                 }
1857                 state->errors++;
1858                 return 0;
1859         }
1860
1861         return 0;
1862 }
1863
1864 struct smbXsrv_session_local_trav_state {
1865         NTSTATUS status;
1866         int (*caller_cb)(struct smbXsrv_session *session,
1867                          void *caller_data);
1868         void *caller_data;
1869 };
1870
1871 static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
1872                                              void *private_data);
1873
1874 NTSTATUS smbXsrv_session_local_traverse(
1875         struct smbXsrv_client *client,
1876         int (*caller_cb)(struct smbXsrv_session *session,
1877                          void *caller_data),
1878         void *caller_data)
1879 {
1880         struct smbXsrv_session_table *table = client->session_table;
1881         struct smbXsrv_session_local_trav_state state;
1882         NTSTATUS status;
1883         int count = 0;
1884
1885         state = (struct smbXsrv_session_local_trav_state) {
1886                 .status = NT_STATUS_OK,
1887                 .caller_cb = caller_cb,
1888                 .caller_data = caller_data,
1889         };
1890
1891         if (table == NULL) {
1892                 DBG_DEBUG("empty session_table, nothing to do.\n");
1893                 return NT_STATUS_OK;
1894         }
1895
1896         status = dbwrap_traverse(table->local.db_ctx,
1897                                  smbXsrv_session_local_traverse_cb,
1898                                  &state,
1899                                  &count);
1900         if (!NT_STATUS_IS_OK(status)) {
1901                 DBG_ERR("dbwrap_traverse() failed: %s\n", nt_errstr(status));
1902                 return status;
1903         }
1904         if (!NT_STATUS_IS_OK(state.status)) {
1905                 DBG_ERR("count[%d] status[%s]\n",
1906                         count, nt_errstr(state.status));
1907                 return state.status;
1908         }
1909
1910         return NT_STATUS_OK;
1911 }
1912
1913 static int smbXsrv_session_local_traverse_cb(struct db_record *local_rec,
1914                                              void *private_data)
1915 {
1916         struct smbXsrv_session_local_trav_state *state =
1917                 (struct smbXsrv_session_local_trav_state *)private_data;
1918         TDB_DATA val;
1919         void *ptr = NULL;
1920         struct smbXsrv_session *session = NULL;
1921         int ret;
1922
1923         val = dbwrap_record_get_value(local_rec);
1924         if (val.dsize != sizeof(ptr)) {
1925                 state->status = NT_STATUS_INTERNAL_ERROR;
1926                 return -1;
1927         }
1928
1929         memcpy(&ptr, val.dptr, val.dsize);
1930         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
1931
1932         session->db_rec = local_rec;
1933         ret = state->caller_cb(session, state->caller_data);
1934         session->db_rec = NULL;
1935
1936         return ret;
1937 }
1938
1939 struct smbXsrv_session_disconnect_xconn_state {
1940         struct smbXsrv_connection *xconn;
1941         NTSTATUS first_status;
1942         int errors;
1943 };
1944
1945 static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
1946                                                void *private_data);
1947
1948 NTSTATUS smbXsrv_session_disconnect_xconn(struct smbXsrv_connection *xconn)
1949 {
1950         struct smbXsrv_client *client = xconn->client;
1951         struct smbXsrv_session_table *table = client->session_table;
1952         struct smbXsrv_session_disconnect_xconn_state state;
1953         NTSTATUS status;
1954         int count = 0;
1955
1956         if (table == NULL) {
1957                 DBG_ERR("empty session_table, nothing to do.\n");
1958                 return NT_STATUS_OK;
1959         }
1960
1961         ZERO_STRUCT(state);
1962         state.xconn = xconn;
1963
1964         status = dbwrap_traverse(table->local.db_ctx,
1965                                  smbXsrv_session_disconnect_xconn_callback,
1966                                  &state, &count);
1967         if (!NT_STATUS_IS_OK(status)) {
1968                 DBG_ERR("dbwrap_traverse() failed: %s\n",
1969                         nt_errstr(status));
1970                 return status;
1971         }
1972
1973         if (!NT_STATUS_IS_OK(state.first_status)) {
1974                 DBG_ERR("count[%d] errors[%d] first[%s]\n",
1975                         count, state.errors,
1976                         nt_errstr(state.first_status));
1977                 return state.first_status;
1978         }
1979
1980         return NT_STATUS_OK;
1981 }
1982
1983 static int smbXsrv_session_disconnect_xconn_callback(struct db_record *local_rec,
1984                                                void *private_data)
1985 {
1986         struct smbXsrv_session_disconnect_xconn_state *state =
1987                 (struct smbXsrv_session_disconnect_xconn_state *)private_data;
1988         TDB_DATA val;
1989         void *ptr = NULL;
1990         struct smbXsrv_session *session = NULL;
1991         struct smbXsrv_session_auth0 *a = NULL;
1992         struct smbXsrv_channel_global0 *c = NULL;
1993         NTSTATUS status;
1994         bool need_update = false;
1995
1996         val = dbwrap_record_get_value(local_rec);
1997         if (val.dsize != sizeof(ptr)) {
1998                 status = NT_STATUS_INTERNAL_ERROR;
1999                 if (NT_STATUS_IS_OK(state->first_status)) {
2000                         state->first_status = status;
2001                 }
2002                 state->errors++;
2003                 return 0;
2004         }
2005
2006         memcpy(&ptr, val.dptr, val.dsize);
2007         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
2008
2009         session->db_rec = local_rec;
2010
2011         status = smbXsrv_session_find_auth(session, state->xconn, 0, &a);
2012         if (!NT_STATUS_IS_OK(status)) {
2013                 a = NULL;
2014         }
2015         status = smbXsrv_session_find_channel(session, state->xconn, &c);
2016         if (!NT_STATUS_IS_OK(status)) {
2017                 c = NULL;
2018         }
2019         if (session->global->num_channels <= 1) {
2020                 /*
2021                  * The last channel is treated different
2022                  */
2023                 c = NULL;
2024         }
2025
2026         if (a != NULL) {
2027                 smbXsrv_session_auth0_destructor(a);
2028                 a->connection = NULL;
2029                 need_update = true;
2030         }
2031
2032         if (c != NULL) {
2033                 struct smbXsrv_session_global0 *global = session->global;
2034                 ptrdiff_t n;
2035
2036                 n = (c - global->channels);
2037                 if (n >= global->num_channels || n < 0) {
2038                         status = NT_STATUS_INTERNAL_ERROR;
2039                         if (NT_STATUS_IS_OK(state->first_status)) {
2040                                 state->first_status = status;
2041                         }
2042                         state->errors++;
2043                         session->db_rec = NULL;
2044                         return 0;
2045                 }
2046                 ARRAY_DEL_ELEMENT(global->channels, n, global->num_channels);
2047                 global->num_channels--;
2048                 need_update = true;
2049         }
2050
2051         if (need_update) {
2052                 status = smbXsrv_session_update(session);
2053                 if (NT_STATUS_IS_OK(state->first_status)) {
2054                         state->first_status = status;
2055                 }
2056                 state->errors++;
2057         }
2058
2059         session->db_rec = NULL;
2060         return 0;
2061 }
2062
2063 NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn)
2064 {
2065         /*
2066          * Allow a range from 1..65534 with 65534 values.
2067          */
2068         return smbXsrv_session_table_init(conn, 1, UINT16_MAX - 1,
2069                                           UINT16_MAX - 1);
2070 }
2071
2072 NTSTATUS smb1srv_session_lookup(struct smbXsrv_connection *conn,
2073                                 uint16_t vuid, NTTIME now,
2074                                 struct smbXsrv_session **session)
2075 {
2076         struct smbXsrv_session_table *table = conn->client->session_table;
2077         uint32_t local_id = vuid;
2078
2079         return smbXsrv_session_local_lookup(table, conn, local_id, now,
2080                                             session);
2081 }
2082
2083 NTSTATUS smbXsrv_session_info_lookup(struct smbXsrv_client *client,
2084                                      uint64_t session_wire_id,
2085                                      struct auth_session_info **si)
2086 {
2087         struct smbXsrv_session_table *table = client->session_table;
2088         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2089         struct smbXsrv_session_local_fetch_state state = {
2090                 .session = NULL,
2091                 .status = NT_STATUS_INTERNAL_ERROR,
2092         };
2093         TDB_DATA key;
2094         NTSTATUS status;
2095
2096         if (session_wire_id == 0) {
2097                 return NT_STATUS_USER_SESSION_DELETED;
2098         }
2099
2100         if (table == NULL) {
2101                 /* this might happen before the end of negprot */
2102                 return NT_STATUS_USER_SESSION_DELETED;
2103         }
2104
2105         if (table->local.db_ctx == NULL) {
2106                 return NT_STATUS_INTERNAL_ERROR;
2107         }
2108
2109         key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2110
2111         status = dbwrap_parse_record(table->local.db_ctx, key,
2112                                      smbXsrv_session_local_fetch_parser,
2113                                      &state);
2114         if (!NT_STATUS_IS_OK(status)) {
2115                 return status;
2116         }
2117         if (!NT_STATUS_IS_OK(state.status)) {
2118                 return state.status;
2119         }
2120         if (state.session->global->auth_session_info == NULL) {
2121                 return NT_STATUS_USER_SESSION_DELETED;
2122         }
2123
2124         *si = state.session->global->auth_session_info;
2125         return NT_STATUS_OK;
2126 }
2127
2128 /*
2129  * In memory of get_valid_user_struct()
2130  *
2131  * This function is similar to smbXsrv_session_local_lookup() and it's wrappers,
2132  * but it doesn't implement the state checks of
2133  * those. get_valid_smbXsrv_session() is NOT meant to be called to validate the
2134  * session wire-id of incoming SMB requests, it MUST only be used in later
2135  * internal processing where the session wire-id has already been validated.
2136  */
2137 NTSTATUS get_valid_smbXsrv_session(struct smbXsrv_client *client,
2138                                    uint64_t session_wire_id,
2139                                    struct smbXsrv_session **session)
2140 {
2141         struct smbXsrv_session_table *table = client->session_table;
2142         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
2143         struct smbXsrv_session_local_fetch_state state = {
2144                 .session = NULL,
2145                 .status = NT_STATUS_INTERNAL_ERROR,
2146         };
2147         TDB_DATA key;
2148         NTSTATUS status;
2149
2150         if (session_wire_id == 0) {
2151                 return NT_STATUS_USER_SESSION_DELETED;
2152         }
2153
2154         if (table == NULL) {
2155                 /* this might happen before the end of negprot */
2156                 return NT_STATUS_USER_SESSION_DELETED;
2157         }
2158
2159         if (table->local.db_ctx == NULL) {
2160                 return NT_STATUS_INTERNAL_ERROR;
2161         }
2162
2163         key = smbXsrv_session_local_id_to_key(session_wire_id, key_buf);
2164
2165         status = dbwrap_parse_record(table->local.db_ctx, key,
2166                                      smbXsrv_session_local_fetch_parser,
2167                                      &state);
2168         if (!NT_STATUS_IS_OK(status)) {
2169                 return status;
2170         }
2171         if (!NT_STATUS_IS_OK(state.status)) {
2172                 return state.status;
2173         }
2174         if (state.session->global->auth_session_info == NULL) {
2175                 return NT_STATUS_USER_SESSION_DELETED;
2176         }
2177
2178         *session = state.session;
2179         return NT_STATUS_OK;
2180 }
2181
2182 NTSTATUS smb2srv_session_table_init(struct smbXsrv_connection *conn)
2183 {
2184         /*
2185          * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
2186          */
2187         return smbXsrv_session_table_init(conn, 1, UINT32_MAX - 1,
2188                                           UINT16_MAX - 1);
2189 }
2190
2191 static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
2192                                            /* conn: optional */
2193                                            struct smbXsrv_connection *conn,
2194                                            uint64_t session_id, NTTIME now,
2195                                            struct smbXsrv_session **session)
2196 {
2197         uint32_t local_id = session_id & UINT32_MAX;
2198         uint64_t local_zeros = session_id & 0xFFFFFFFF00000000LLU;
2199
2200         if (local_zeros != 0) {
2201                 return NT_STATUS_USER_SESSION_DELETED;
2202         }
2203
2204         return smbXsrv_session_local_lookup(table, conn, local_id, now,
2205                                             session);
2206 }
2207
2208 NTSTATUS smb2srv_session_lookup_conn(struct smbXsrv_connection *conn,
2209                                      uint64_t session_id, NTTIME now,
2210                                      struct smbXsrv_session **session)
2211 {
2212         struct smbXsrv_session_table *table = conn->client->session_table;
2213         return smb2srv_session_lookup_raw(table, conn, session_id, now,
2214                                           session);
2215 }
2216
2217 NTSTATUS smb2srv_session_lookup_client(struct smbXsrv_client *client,
2218                                        uint64_t session_id, NTTIME now,
2219                                        struct smbXsrv_session **session)
2220 {
2221         struct smbXsrv_session_table *table = client->session_table;
2222         return smb2srv_session_lookup_raw(table, NULL, session_id, now,
2223                                           session);
2224 }
2225
2226 struct smbXsrv_session_global_traverse_state {
2227         int (*fn)(struct smbXsrv_session_global0 *, void *);
2228         void *private_data;
2229 };
2230
2231 static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
2232 {
2233         int ret = -1;
2234         struct smbXsrv_session_global_traverse_state *state =
2235                 (struct smbXsrv_session_global_traverse_state*)data;
2236         TDB_DATA key = dbwrap_record_get_key(rec);
2237         TDB_DATA val = dbwrap_record_get_value(rec);
2238         DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
2239         struct smbXsrv_session_globalB global_blob;
2240         enum ndr_err_code ndr_err;
2241         TALLOC_CTX *frame = talloc_stackframe();
2242
2243         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
2244                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
2245         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2246                 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
2247                          "key '%s' ndr_pull_struct_blob - %s\n",
2248                          hex_encode_talloc(frame, key.dptr, key.dsize),
2249                          ndr_errstr(ndr_err)));
2250                 goto done;
2251         }
2252
2253         if (global_blob.version != SMBXSRV_VERSION_0) {
2254                 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
2255                          "key '%s' unsupported version - %d\n",
2256                          hex_encode_talloc(frame, key.dptr, key.dsize),
2257                          (int)global_blob.version));
2258                 goto done;
2259         }
2260
2261         global_blob.info.info0->db_rec = rec;
2262         ret = state->fn(global_blob.info.info0, state->private_data);
2263 done:
2264         TALLOC_FREE(frame);
2265         return ret;
2266 }
2267
2268 NTSTATUS smbXsrv_session_global_traverse(
2269                         int (*fn)(struct smbXsrv_session_global0 *, void *),
2270                         void *private_data)
2271 {
2272
2273         NTSTATUS status;
2274         int count = 0;
2275         struct smbXsrv_session_global_traverse_state state = {
2276                 .fn = fn,
2277                 .private_data = private_data,
2278         };
2279
2280         become_root();
2281         status = smbXsrv_session_global_init(NULL);
2282         if (!NT_STATUS_IS_OK(status)) {
2283                 unbecome_root();
2284                 DEBUG(0, ("Failed to initialize session_global: %s\n",
2285                           nt_errstr(status)));
2286                 return status;
2287         }
2288
2289         status = dbwrap_traverse_read(smbXsrv_session_global_db_ctx,
2290                                       smbXsrv_session_global_traverse_fn,
2291                                       &state,
2292                                       &count);
2293         unbecome_root();
2294
2295         return status;
2296 }