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