smbXsrv: rename smb2srv_session_lookup -> smb2srv_session_lookup_conn
[nivanova/samba-autobuild/.git] / source3 / smbd / smbXsrv_session.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Stefan Metzmacher 2011-2012
5    Copyright (C) Michael Adam 2012
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include <tevent.h>
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "dbwrap/dbwrap.h"
27 #include "dbwrap/dbwrap_rbt.h"
28 #include "dbwrap/dbwrap_open.h"
29 #include "dbwrap/dbwrap_watch.h"
30 #include "session.h"
31 #include "auth.h"
32 #include "auth/gensec/gensec.h"
33 #include "../lib/tsocket/tsocket.h"
34 #include "../libcli/security/security.h"
35 #include "messages.h"
36 #include "lib/util/util_tdb.h"
37 #include "librpc/gen_ndr/ndr_smbXsrv.h"
38 #include "serverid.h"
39 #include "lib/util/tevent_ntstatus.h"
40
41 struct smbXsrv_session_table {
42         struct {
43                 struct db_context *db_ctx;
44                 uint32_t lowest_id;
45                 uint32_t highest_id;
46                 uint32_t max_sessions;
47                 uint32_t num_sessions;
48         } local;
49         struct {
50                 struct db_context *db_ctx;
51         } global;
52 };
53
54 static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
55                                            /* conn: optional */
56                                            struct smbXsrv_connection *conn,
57                                            uint64_t session_id, NTTIME now,
58                                            struct smbXsrv_session **session);
59
60 static struct db_context *smbXsrv_session_global_db_ctx = NULL;
61
62 NTSTATUS smbXsrv_session_global_init(void)
63 {
64         char *global_path = NULL;
65         struct db_context *db_ctx = NULL;
66
67         if (smbXsrv_session_global_db_ctx != NULL) {
68                 return NT_STATUS_OK;
69         }
70
71         /*
72          * This contains secret information like session keys!
73          */
74         global_path = lock_path("smbXsrv_session_global.tdb");
75         if (global_path == NULL) {
76                 return NT_STATUS_NO_MEMORY;
77         }
78
79         db_ctx = db_open(NULL, global_path,
80                          0, /* hash_size */
81                          TDB_DEFAULT |
82                          TDB_CLEAR_IF_FIRST |
83                          TDB_INCOMPATIBLE_HASH,
84                          O_RDWR | O_CREAT, 0600,
85                          DBWRAP_LOCK_ORDER_1,
86                          DBWRAP_FLAG_NONE);
87         TALLOC_FREE(global_path);
88         if (db_ctx == NULL) {
89                 NTSTATUS status;
90
91                 status = map_nt_error_from_unix_common(errno);
92
93                 return status;
94         }
95
96         smbXsrv_session_global_db_ctx = db_ctx;
97
98         return NT_STATUS_OK;
99 }
100
101 /*
102  * NOTE:
103  * We need to store the keys in big endian so that dbwrap_rbt's memcmp
104  * has the same result as integer comparison between the uint32_t
105  * values.
106  *
107  * TODO: implement string based key
108  */
109
110 #define SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE sizeof(uint32_t)
111
112 static TDB_DATA smbXsrv_session_global_id_to_key(uint32_t id,
113                                                  uint8_t *key_buf)
114 {
115         TDB_DATA key;
116
117         RSIVAL(key_buf, 0, id);
118
119         key = make_tdb_data(key_buf, SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE);
120
121         return key;
122 }
123
124 #if 0
125 static NTSTATUS smbXsrv_session_global_key_to_id(TDB_DATA key, uint32_t *id)
126 {
127         if (id == NULL) {
128                 return NT_STATUS_INVALID_PARAMETER;
129         }
130
131         if (key.dsize != SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE) {
132                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
133         }
134
135         *id = RIVAL(key.dptr, 0);
136
137         return NT_STATUS_OK;
138 }
139 #endif
140
141 #define SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE sizeof(uint32_t)
142
143 static TDB_DATA smbXsrv_session_local_id_to_key(uint32_t id,
144                                                 uint8_t *key_buf)
145 {
146         TDB_DATA key;
147
148         RSIVAL(key_buf, 0, id);
149
150         key = make_tdb_data(key_buf, SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE);
151
152         return key;
153 }
154
155 static NTSTATUS smbXsrv_session_local_key_to_id(TDB_DATA key, uint32_t *id)
156 {
157         if (id == NULL) {
158                 return NT_STATUS_INVALID_PARAMETER;
159         }
160
161         if (key.dsize != SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE) {
162                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
163         }
164
165         *id = RIVAL(key.dptr, 0);
166
167         return NT_STATUS_OK;
168 }
169
170 static void smbXsrv_session_close_loop(struct tevent_req *subreq);
171
172 static NTSTATUS smbXsrv_session_table_init(struct smbXsrv_connection *conn,
173                                            uint32_t lowest_id,
174                                            uint32_t highest_id,
175                                            uint32_t max_sessions)
176 {
177         struct smbXsrv_client *client = conn->client;
178         struct smbXsrv_session_table *table;
179         NTSTATUS status;
180         struct tevent_req *subreq;
181         uint64_t max_range;
182
183         if (lowest_id > highest_id) {
184                 return NT_STATUS_INTERNAL_ERROR;
185         }
186
187         max_range = highest_id;
188         max_range -= lowest_id;
189         max_range += 1;
190
191         if (max_sessions > max_range) {
192                 return NT_STATUS_INTERNAL_ERROR;
193         }
194
195         table = talloc_zero(client, struct smbXsrv_session_table);
196         if (table == NULL) {
197                 return NT_STATUS_NO_MEMORY;
198         }
199
200         table->local.db_ctx = db_open_rbt(table);
201         if (table->local.db_ctx == NULL) {
202                 TALLOC_FREE(table);
203                 return NT_STATUS_NO_MEMORY;
204         }
205         table->local.lowest_id = lowest_id;
206         table->local.highest_id = highest_id;
207         table->local.max_sessions = max_sessions;
208
209         status = smbXsrv_session_global_init();
210         if (!NT_STATUS_IS_OK(status)) {
211                 TALLOC_FREE(table);
212                 return status;
213         }
214
215         table->global.db_ctx = smbXsrv_session_global_db_ctx;
216
217         dbwrap_watch_db(table->global.db_ctx, client->msg_ctx);
218
219         subreq = messaging_read_send(table, client->ev_ctx, client->msg_ctx,
220                                      MSG_SMBXSRV_SESSION_CLOSE);
221         if (subreq == NULL) {
222                 TALLOC_FREE(table);
223                 return NT_STATUS_NO_MEMORY;
224         }
225         tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
226
227         client->session_table = table;
228         return NT_STATUS_OK;
229 }
230
231 static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq);
232
233 static void smbXsrv_session_close_loop(struct tevent_req *subreq)
234 {
235         struct smbXsrv_client *client =
236                 tevent_req_callback_data(subreq,
237                 struct smbXsrv_client);
238         struct smbXsrv_session_table *table = client->session_table;
239         int ret;
240         struct messaging_rec *rec = NULL;
241         struct smbXsrv_session_closeB close_blob;
242         enum ndr_err_code ndr_err;
243         struct smbXsrv_session_close0 *close_info0 = NULL;
244         struct smbXsrv_session *session = NULL;
245         NTSTATUS status;
246         struct timeval tv = timeval_current();
247         NTTIME now = timeval_to_nttime(&tv);
248
249         ret = messaging_read_recv(subreq, talloc_tos(), &rec);
250         TALLOC_FREE(subreq);
251         if (ret != 0) {
252                 goto next;
253         }
254
255         ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &close_blob,
256                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_closeB);
257         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
258                 status = ndr_map_error2ntstatus(ndr_err);
259                 DEBUG(1,("smbXsrv_session_close_loop: "
260                          "ndr_pull_struct_blob - %s\n",
261                          nt_errstr(status)));
262                 goto next;
263         }
264
265         DEBUG(10,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
266         if (DEBUGLVL(10)) {
267                 NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
268         }
269
270         if (close_blob.version != SMBXSRV_VERSION_0) {
271                 DEBUG(0,("smbXsrv_session_close_loop: "
272                          "ignore invalid version %u\n", close_blob.version));
273                 NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
274                 goto next;
275         }
276
277         close_info0 = close_blob.info.info0;
278         if (close_info0 == NULL) {
279                 DEBUG(0,("smbXsrv_session_close_loop: "
280                          "ignore NULL info %u\n", close_blob.version));
281                 NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
282                 goto next;
283         }
284
285         status = smb2srv_session_lookup_raw(client->session_table,
286                                             NULL, /* smbXsrv_connection */
287                                             close_info0->old_session_wire_id,
288                                             now, &session);
289         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
290                 DEBUG(4,("smbXsrv_session_close_loop: "
291                          "old_session_wire_id %llu not found\n",
292                          (unsigned long long)close_info0->old_session_wire_id));
293                 if (DEBUGLVL(4)) {
294                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
295                 }
296                 goto next;
297         }
298         if (!NT_STATUS_IS_OK(status) &&
299             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
300             !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
301                 DEBUG(1,("smbXsrv_session_close_loop: "
302                          "old_session_wire_id %llu - %s\n",
303                          (unsigned long long)close_info0->old_session_wire_id,
304                          nt_errstr(status)));
305                 if (DEBUGLVL(1)) {
306                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
307                 }
308                 goto next;
309         }
310
311         if (session->global->session_global_id != close_info0->old_session_global_id) {
312                 DEBUG(1,("smbXsrv_session_close_loop: "
313                          "old_session_wire_id %llu - global %u != %u\n",
314                          (unsigned long long)close_info0->old_session_wire_id,
315                          session->global->session_global_id,
316                          close_info0->old_session_global_id));
317                 if (DEBUGLVL(1)) {
318                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
319                 }
320                 goto next;
321         }
322
323         if (session->global->creation_time != close_info0->old_creation_time) {
324                 DEBUG(1,("smbXsrv_session_close_loop: "
325                          "old_session_wire_id %llu - "
326                          "creation %s (%llu) != %s (%llu)\n",
327                          (unsigned long long)close_info0->old_session_wire_id,
328                          nt_time_string(rec, session->global->creation_time),
329                          (unsigned long long)session->global->creation_time,
330                          nt_time_string(rec, close_info0->old_creation_time),
331                          (unsigned long long)close_info0->old_creation_time));
332                 if (DEBUGLVL(1)) {
333                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
334                 }
335                 goto next;
336         }
337
338         subreq = smb2srv_session_shutdown_send(session, client->ev_ctx,
339                                                session, NULL);
340         if (subreq == NULL) {
341                 status = NT_STATUS_NO_MEMORY;
342                 DEBUG(0, ("smbXsrv_session_close_loop: "
343                           "smb2srv_session_shutdown_send(%llu) failed: %s\n",
344                           (unsigned long long)session->global->session_wire_id,
345                           nt_errstr(status)));
346                 if (DEBUGLVL(1)) {
347                         NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
348                 }
349                 goto next;
350         }
351         tevent_req_set_callback(subreq,
352                                 smbXsrv_session_close_shutdown_done,
353                                 session);
354
355 next:
356         TALLOC_FREE(rec);
357
358         subreq = messaging_read_send(table, client->ev_ctx, client->msg_ctx,
359                                      MSG_SMBXSRV_SESSION_CLOSE);
360         if (subreq == NULL) {
361                 const char *r;
362                 r = "messaging_read_send(MSG_SMBXSRV_SESSION_CLOSE) failed";
363                 exit_server_cleanly(r);
364                 return;
365         }
366         tevent_req_set_callback(subreq, smbXsrv_session_close_loop, client);
367 }
368
369 static void smbXsrv_session_close_shutdown_done(struct tevent_req *subreq)
370 {
371         struct smbXsrv_session *session =
372                 tevent_req_callback_data(subreq,
373                 struct smbXsrv_session);
374         NTSTATUS status;
375
376         status = smb2srv_session_shutdown_recv(subreq);
377         TALLOC_FREE(subreq);
378         if (!NT_STATUS_IS_OK(status)) {
379                 DEBUG(0, ("smbXsrv_session_close_loop: "
380                           "smb2srv_session_shutdown_recv(%llu) failed: %s\n",
381                           (unsigned long long)session->global->session_wire_id,
382                           nt_errstr(status)));
383         }
384
385         status = smbXsrv_session_logoff(session);
386         if (!NT_STATUS_IS_OK(status)) {
387                 DEBUG(0, ("smbXsrv_session_close_loop: "
388                           "smbXsrv_session_logoff(%llu) failed: %s\n",
389                           (unsigned long long)session->global->session_wire_id,
390                           nt_errstr(status)));
391         }
392
393         TALLOC_FREE(session);
394 }
395
396 struct smb1srv_session_local_allocate_state {
397         const uint32_t lowest_id;
398         const uint32_t highest_id;
399         uint32_t last_id;
400         uint32_t useable_id;
401         NTSTATUS status;
402 };
403
404 static int smb1srv_session_local_allocate_traverse(struct db_record *rec,
405                                                    void *private_data)
406 {
407         struct smb1srv_session_local_allocate_state *state =
408                 (struct smb1srv_session_local_allocate_state *)private_data;
409         TDB_DATA key = dbwrap_record_get_key(rec);
410         uint32_t id = 0;
411         NTSTATUS status;
412
413         status = smbXsrv_session_local_key_to_id(key, &id);
414         if (!NT_STATUS_IS_OK(status)) {
415                 state->status = status;
416                 return -1;
417         }
418
419         if (id <= state->last_id) {
420                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
421                 return -1;
422         }
423         state->last_id = id;
424
425         if (id > state->useable_id) {
426                 state->status = NT_STATUS_OK;
427                 return -1;
428         }
429
430         if (state->useable_id == state->highest_id) {
431                 state->status = NT_STATUS_INSUFFICIENT_RESOURCES;
432                 return -1;
433         }
434
435         state->useable_id +=1;
436         return 0;
437 }
438
439 static NTSTATUS smb1srv_session_local_allocate_id(struct db_context *db,
440                                                   uint32_t lowest_id,
441                                                   uint32_t highest_id,
442                                                   TALLOC_CTX *mem_ctx,
443                                                   struct db_record **_rec,
444                                                   uint32_t *_id)
445 {
446         struct smb1srv_session_local_allocate_state state = {
447                 .lowest_id = lowest_id,
448                 .highest_id = highest_id,
449                 .last_id = 0,
450                 .useable_id = lowest_id,
451                 .status = NT_STATUS_INTERNAL_ERROR,
452         };
453         uint32_t i;
454         uint32_t range;
455         NTSTATUS status;
456         int count = 0;
457
458         *_rec = NULL;
459         *_id = 0;
460
461         if (lowest_id > highest_id) {
462                 return NT_STATUS_INSUFFICIENT_RESOURCES;
463         }
464
465         /*
466          * first we try randomly
467          */
468         range = (highest_id - lowest_id) + 1;
469
470         for (i = 0; i < (range / 2); i++) {
471                 uint32_t id;
472                 uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
473                 TDB_DATA key;
474                 TDB_DATA val;
475                 struct db_record *rec = NULL;
476
477                 id = generate_random() % range;
478                 id += lowest_id;
479
480                 if (id < lowest_id) {
481                         id = lowest_id;
482                 }
483                 if (id > highest_id) {
484                         id = highest_id;
485                 }
486
487                 key = smbXsrv_session_local_id_to_key(id, key_buf);
488
489                 rec = dbwrap_fetch_locked(db, mem_ctx, key);
490                 if (rec == NULL) {
491                         return NT_STATUS_INSUFFICIENT_RESOURCES;
492                 }
493
494                 val = dbwrap_record_get_value(rec);
495                 if (val.dsize != 0) {
496                         TALLOC_FREE(rec);
497                         continue;
498                 }
499
500                 *_rec = rec;
501                 *_id = id;
502                 return NT_STATUS_OK;
503         }
504
505         /*
506          * if the range is almost full,
507          * we traverse the whole table
508          * (this relies on sorted behavior of dbwrap_rbt)
509          */
510         status = dbwrap_traverse_read(db, smb1srv_session_local_allocate_traverse,
511                                       &state, &count);
512         if (NT_STATUS_IS_OK(status)) {
513                 if (NT_STATUS_IS_OK(state.status)) {
514                         return NT_STATUS_INTERNAL_ERROR;
515                 }
516
517                 if (!NT_STATUS_EQUAL(state.status, NT_STATUS_INTERNAL_ERROR)) {
518                         return state.status;
519                 }
520
521                 if (state.useable_id <= state.highest_id) {
522                         state.status = NT_STATUS_OK;
523                 } else {
524                         return NT_STATUS_INSUFFICIENT_RESOURCES;
525                 }
526         } else if (!NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_CORRUPTION)) {
527                 /*
528                  * Here we really expect NT_STATUS_INTERNAL_DB_CORRUPTION!
529                  *
530                  * If we get anything else it is an error, because it
531                  * means we did not manage to find a free slot in
532                  * the db.
533                  */
534                 return NT_STATUS_INSUFFICIENT_RESOURCES;
535         }
536
537         if (NT_STATUS_IS_OK(state.status)) {
538                 uint32_t id;
539                 uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
540                 TDB_DATA key;
541                 TDB_DATA val;
542                 struct db_record *rec = NULL;
543
544                 id = state.useable_id;
545
546                 key = smbXsrv_session_local_id_to_key(id, key_buf);
547
548                 rec = dbwrap_fetch_locked(db, mem_ctx, key);
549                 if (rec == NULL) {
550                         return NT_STATUS_INSUFFICIENT_RESOURCES;
551                 }
552
553                 val = dbwrap_record_get_value(rec);
554                 if (val.dsize != 0) {
555                         TALLOC_FREE(rec);
556                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
557                 }
558
559                 *_rec = rec;
560                 *_id = id;
561                 return NT_STATUS_OK;
562         }
563
564         return state.status;
565 }
566
567 struct smbXsrv_session_local_fetch_state {
568         struct smbXsrv_session *session;
569         NTSTATUS status;
570 };
571
572 static void smbXsrv_session_local_fetch_parser(TDB_DATA key, TDB_DATA data,
573                                                void *private_data)
574 {
575         struct smbXsrv_session_local_fetch_state *state =
576                 (struct smbXsrv_session_local_fetch_state *)private_data;
577         void *ptr;
578
579         if (data.dsize != sizeof(ptr)) {
580                 state->status = NT_STATUS_INTERNAL_DB_ERROR;
581                 return;
582         }
583
584         memcpy(&ptr, data.dptr, data.dsize);
585         state->session = talloc_get_type_abort(ptr, struct smbXsrv_session);
586         state->status = NT_STATUS_OK;
587 }
588
589 static NTSTATUS smbXsrv_session_local_lookup(struct smbXsrv_session_table *table,
590                                              /* conn: optional */
591                                              struct smbXsrv_connection *conn,
592                                              uint32_t session_local_id,
593                                              NTTIME now,
594                                              struct smbXsrv_session **_session)
595 {
596         struct smbXsrv_session_local_fetch_state state = {
597                 .session = NULL,
598                 .status = NT_STATUS_INTERNAL_ERROR,
599         };
600         uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
601         TDB_DATA key;
602         NTSTATUS status;
603
604         *_session = NULL;
605
606         if (session_local_id == 0) {
607                 return NT_STATUS_USER_SESSION_DELETED;
608         }
609
610         if (table == NULL) {
611                 /* this might happen before the end of negprot */
612                 return NT_STATUS_USER_SESSION_DELETED;
613         }
614
615         if (table->local.db_ctx == NULL) {
616                 return NT_STATUS_INTERNAL_ERROR;
617         }
618
619         key = smbXsrv_session_local_id_to_key(session_local_id, key_buf);
620
621         status = dbwrap_parse_record(table->local.db_ctx, key,
622                                      smbXsrv_session_local_fetch_parser,
623                                      &state);
624         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
625                 return NT_STATUS_USER_SESSION_DELETED;
626         } else if (!NT_STATUS_IS_OK(status)) {
627                 return status;
628         }
629         if (!NT_STATUS_IS_OK(state.status)) {
630                 return state.status;
631         }
632
633         if (NT_STATUS_EQUAL(state.session->status, NT_STATUS_USER_SESSION_DELETED)) {
634                 return NT_STATUS_USER_SESSION_DELETED;
635         }
636
637         /*
638          * If a connection is specified check if the session is
639          * valid on the channel.
640          */
641         if (conn != NULL) {
642                 struct smbXsrv_channel_global0 *c = NULL;
643
644                 status = smbXsrv_session_find_channel(state.session, conn, &c);
645                 if (!NT_STATUS_IS_OK(status)) {
646                         return status;
647                 }
648         }
649
650         state.session->idle_time = now;
651
652         if (!NT_STATUS_IS_OK(state.session->status)) {
653                 *_session = state.session;
654                 return state.session->status;
655         }
656
657         if (now > state.session->global->expiration_time) {
658                 state.session->status = NT_STATUS_NETWORK_SESSION_EXPIRED;
659         }
660
661         *_session = state.session;
662         return state.session->status;
663 }
664
665 static int smbXsrv_session_global_destructor(struct smbXsrv_session_global0 *global)
666 {
667         return 0;
668 }
669
670 static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
671                                         bool *is_free,
672                                         bool *was_free,
673                                         TALLOC_CTX *mem_ctx,
674                                         struct smbXsrv_session_global0 **_g);
675
676 static NTSTATUS smbXsrv_session_global_allocate(struct db_context *db,
677                                         TALLOC_CTX *mem_ctx,
678                                         struct smbXsrv_session_global0 **_global)
679 {
680         uint32_t i;
681         struct smbXsrv_session_global0 *global = NULL;
682         uint32_t last_free = 0;
683         const uint32_t min_tries = 3;
684
685         *_global = NULL;
686
687         global = talloc_zero(mem_ctx, struct smbXsrv_session_global0);
688         if (global == NULL) {
689                 return NT_STATUS_NO_MEMORY;
690         }
691         talloc_set_destructor(global, smbXsrv_session_global_destructor);
692
693         /*
694          * Here we just randomly try the whole 32-bit space
695          *
696          * We use just 32-bit, because we want to reuse the
697          * ID for SRVSVC.
698          */
699         for (i = 0; i < UINT32_MAX; i++) {
700                 bool is_free = false;
701                 bool was_free = false;
702                 uint32_t id;
703                 uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE];
704                 TDB_DATA key;
705
706                 if (i >= min_tries && last_free != 0) {
707                         id = last_free;
708                 } else {
709                         id = generate_random();
710                 }
711                 if (id == 0) {
712                         id++;
713                 }
714                 if (id == UINT32_MAX) {
715                         id--;
716                 }
717
718                 key = smbXsrv_session_global_id_to_key(id, key_buf);
719
720                 global->db_rec = dbwrap_fetch_locked(db, mem_ctx, key);
721                 if (global->db_rec == NULL) {
722                         talloc_free(global);
723                         return NT_STATUS_INSUFFICIENT_RESOURCES;
724                 }
725
726                 smbXsrv_session_global_verify_record(global->db_rec,
727                                                      &is_free,
728                                                      &was_free,
729                                                      NULL, NULL);
730
731                 if (!is_free) {
732                         TALLOC_FREE(global->db_rec);
733                         continue;
734                 }
735
736                 if (!was_free && i < min_tries) {
737                         /*
738                          * The session_id is free now,
739                          * but was not free before.
740                          *
741                          * This happens if a smbd crashed
742                          * and did not cleanup the record.
743                          *
744                          * If this is one of our first tries,
745                          * then we try to find a real free one.
746                          */
747                         if (last_free == 0) {
748                                 last_free = id;
749                         }
750                         TALLOC_FREE(global->db_rec);
751                         continue;
752                 }
753
754                 global->session_global_id = id;
755
756                 *_global = global;
757                 return NT_STATUS_OK;
758         }
759
760         /* should not be reached */
761         talloc_free(global);
762         return NT_STATUS_INTERNAL_ERROR;
763 }
764
765 static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
766                                         bool *is_free,
767                                         bool *was_free,
768                                         TALLOC_CTX *mem_ctx,
769                                         struct smbXsrv_session_global0 **_g)
770 {
771         TDB_DATA key;
772         TDB_DATA val;
773         DATA_BLOB blob;
774         struct smbXsrv_session_globalB global_blob;
775         enum ndr_err_code ndr_err;
776         struct smbXsrv_session_global0 *global = NULL;
777         bool exists;
778         TALLOC_CTX *frame = talloc_stackframe();
779
780         *is_free = false;
781
782         if (was_free) {
783                 *was_free = false;
784         }
785         if (_g) {
786                 *_g = NULL;
787         }
788
789         key = dbwrap_record_get_key(db_rec);
790
791         val = dbwrap_record_get_value(db_rec);
792         if (val.dsize == 0) {
793                 TALLOC_FREE(frame);
794                 *is_free = true;
795                 if (was_free) {
796                         *was_free = true;
797                 }
798                 return;
799         }
800
801         blob = data_blob_const(val.dptr, val.dsize);
802
803         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
804                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
805         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
806                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
807                 DEBUG(1,("smbXsrv_session_global_verify_record: "
808                          "key '%s' ndr_pull_struct_blob - %s\n",
809                          hex_encode_talloc(frame, key.dptr, key.dsize),
810                          nt_errstr(status)));
811                 TALLOC_FREE(frame);
812                 return;
813         }
814
815         DEBUG(10,("smbXsrv_session_global_verify_record\n"));
816         if (DEBUGLVL(10)) {
817                 NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
818         }
819
820         if (global_blob.version != SMBXSRV_VERSION_0) {
821                 DEBUG(0,("smbXsrv_session_global_verify_record: "
822                          "key '%s' use unsupported version %u\n",
823                          hex_encode_talloc(frame, key.dptr, key.dsize),
824                          global_blob.version));
825                 NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
826                 TALLOC_FREE(frame);
827                 return;
828         }
829
830         global = global_blob.info.info0;
831
832         exists = serverid_exists(&global->channels[0].server_id);
833         if (!exists) {
834                 struct server_id_buf idbuf;
835                 DEBUG(2,("smbXsrv_session_global_verify_record: "
836                          "key '%s' server_id %s does not exist.\n",
837                          hex_encode_talloc(frame, key.dptr, key.dsize),
838                          server_id_str_buf(global->channels[0].server_id,
839                                            &idbuf)));
840                 if (DEBUGLVL(2)) {
841                         NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
842                 }
843                 TALLOC_FREE(frame);
844                 dbwrap_record_delete(db_rec);
845                 *is_free = true;
846                 return;
847         }
848
849         if (_g) {
850                 *_g = talloc_move(mem_ctx, &global);
851         }
852         TALLOC_FREE(frame);
853 }
854
855 static NTSTATUS smbXsrv_session_global_store(struct smbXsrv_session_global0 *global)
856 {
857         struct smbXsrv_session_globalB global_blob;
858         DATA_BLOB blob = data_blob_null;
859         TDB_DATA key;
860         TDB_DATA val;
861         NTSTATUS status;
862         enum ndr_err_code ndr_err;
863
864         /*
865          * TODO: if we use other versions than '0'
866          * we would add glue code here, that would be able to
867          * store the information in the old format.
868          */
869
870         if (global->db_rec == NULL) {
871                 return NT_STATUS_INTERNAL_ERROR;
872         }
873
874         key = dbwrap_record_get_key(global->db_rec);
875         val = dbwrap_record_get_value(global->db_rec);
876
877         ZERO_STRUCT(global_blob);
878         global_blob.version = smbXsrv_version_global_current();
879         if (val.dsize >= 8) {
880                 global_blob.seqnum = IVAL(val.dptr, 4);
881         }
882         global_blob.seqnum += 1;
883         global_blob.info.info0 = global;
884
885         ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
886                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_globalB);
887         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
888                 status = ndr_map_error2ntstatus(ndr_err);
889                 DEBUG(1,("smbXsrv_session_global_store: key '%s' ndr_push - %s\n",
890                          hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
891                          nt_errstr(status)));
892                 TALLOC_FREE(global->db_rec);
893                 return status;
894         }
895
896         val = make_tdb_data(blob.data, blob.length);
897         status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
898         if (!NT_STATUS_IS_OK(status)) {
899                 DEBUG(1,("smbXsrv_session_global_store: key '%s' store - %s\n",
900                          hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
901                          nt_errstr(status)));
902                 TALLOC_FREE(global->db_rec);
903                 return status;
904         }
905
906         if (DEBUGLVL(10)) {
907                 DEBUG(10,("smbXsrv_session_global_store: key '%s' stored\n",
908                          hex_encode_talloc(global->db_rec, key.dptr, key.dsize)));
909                 NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
910         }
911
912         TALLOC_FREE(global->db_rec);
913
914         return NT_STATUS_OK;
915 }
916
917 struct smb2srv_session_close_previous_state {
918         struct tevent_context *ev;
919         struct smbXsrv_connection *connection;
920         struct dom_sid *current_sid;
921         uint64_t current_session_id;
922         struct db_record *db_rec;
923 };
924
925 static void smb2srv_session_close_previous_check(struct tevent_req *req);
926 static void smb2srv_session_close_previous_modified(struct tevent_req *subreq);
927
928 struct tevent_req *smb2srv_session_close_previous_send(TALLOC_CTX *mem_ctx,
929                                         struct tevent_context *ev,
930                                         struct smbXsrv_connection *conn,
931                                         struct auth_session_info *session_info,
932                                         uint64_t previous_session_id,
933                                         uint64_t current_session_id)
934 {
935         struct tevent_req *req;
936         struct smb2srv_session_close_previous_state *state;
937         uint32_t global_id = previous_session_id & UINT32_MAX;
938         uint64_t global_zeros = previous_session_id & 0xFFFFFFFF00000000LLU;
939         struct smbXsrv_session_table *table = conn->client->session_table;
940         struct security_token *current_token = NULL;
941         uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE];
942         TDB_DATA key;
943
944         req = tevent_req_create(mem_ctx, &state,
945                                 struct smb2srv_session_close_previous_state);
946         if (req == NULL) {
947                 return NULL;
948         }
949         state->ev = ev;
950         state->connection = conn;
951         state->current_session_id = current_session_id;
952
953         if (global_zeros != 0) {
954                 tevent_req_done(req);
955                 return tevent_req_post(req, ev);
956         }
957
958         if (session_info == NULL) {
959                 tevent_req_done(req);
960                 return tevent_req_post(req, ev);
961         }
962         current_token = session_info->security_token;
963
964         if (current_token->num_sids > PRIMARY_USER_SID_INDEX) {
965                 state->current_sid = &current_token->sids[PRIMARY_USER_SID_INDEX];
966         }
967
968         if (state->current_sid == NULL) {
969                 tevent_req_done(req);
970                 return tevent_req_post(req, ev);
971         }
972
973         if (!security_token_has_nt_authenticated_users(current_token)) {
974                 /* TODO */
975                 tevent_req_done(req);
976                 return tevent_req_post(req, ev);
977         }
978
979         key = smbXsrv_session_global_id_to_key(global_id, key_buf);
980
981         state->db_rec = dbwrap_fetch_locked(table->global.db_ctx,
982                                             state, key);
983         if (state->db_rec == NULL) {
984                 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
985                 return tevent_req_post(req, ev);
986         }
987
988         smb2srv_session_close_previous_check(req);
989         if (!tevent_req_is_in_progress(req)) {
990                 return tevent_req_post(req, ev);
991         }
992
993         return req;
994 }
995
996 static void smb2srv_session_close_previous_check(struct tevent_req *req)
997 {
998         struct smb2srv_session_close_previous_state *state =
999                 tevent_req_data(req,
1000                 struct smb2srv_session_close_previous_state);
1001         struct smbXsrv_connection *conn = state->connection;
1002         DATA_BLOB blob;
1003         struct security_token *previous_token = NULL;
1004         struct smbXsrv_session_global0 *global = NULL;
1005         enum ndr_err_code ndr_err;
1006         struct smbXsrv_session_close0 close_info0;
1007         struct smbXsrv_session_closeB close_blob;
1008         struct tevent_req *subreq = NULL;
1009         NTSTATUS status;
1010         bool is_free = false;
1011
1012         smbXsrv_session_global_verify_record(state->db_rec,
1013                                              &is_free,
1014                                              NULL,
1015                                              state,
1016                                              &global);
1017
1018         if (is_free) {
1019                 TALLOC_FREE(state->db_rec);
1020                 tevent_req_done(req);
1021                 return;
1022         }
1023
1024         if (global->auth_session_info == NULL) {
1025                 TALLOC_FREE(state->db_rec);
1026                 tevent_req_done(req);
1027                 return;
1028         }
1029
1030         previous_token = global->auth_session_info->security_token;
1031
1032         if (!security_token_is_sid(previous_token, state->current_sid)) {
1033                 TALLOC_FREE(state->db_rec);
1034                 tevent_req_done(req);
1035                 return;
1036         }
1037
1038         subreq = dbwrap_record_watch_send(state, state->ev,
1039                                           state->db_rec, conn->msg_ctx);
1040         if (tevent_req_nomem(subreq, req)) {
1041                 TALLOC_FREE(state->db_rec);
1042                 return;
1043         }
1044         tevent_req_set_callback(subreq,
1045                                 smb2srv_session_close_previous_modified,
1046                                 req);
1047
1048         close_info0.old_session_global_id = global->session_global_id;
1049         close_info0.old_session_wire_id = global->session_wire_id;
1050         close_info0.old_creation_time = global->creation_time;
1051         close_info0.new_session_wire_id = state->current_session_id;
1052
1053         ZERO_STRUCT(close_blob);
1054         close_blob.version = smbXsrv_version_global_current();
1055         close_blob.info.info0 = &close_info0;
1056
1057         ndr_err = ndr_push_struct_blob(&blob, state, &close_blob,
1058                         (ndr_push_flags_fn_t)ndr_push_smbXsrv_session_closeB);
1059         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1060                 TALLOC_FREE(state->db_rec);
1061                 status = ndr_map_error2ntstatus(ndr_err);
1062                 DEBUG(1,("smb2srv_session_close_previous_check: "
1063                          "old_session[%llu] new_session[%llu] ndr_push - %s\n",
1064                          (unsigned long long)close_info0.old_session_wire_id,
1065                          (unsigned long long)close_info0.new_session_wire_id,
1066                          nt_errstr(status)));
1067                 tevent_req_nterror(req, status);
1068                 return;
1069         }
1070
1071         status = messaging_send(conn->msg_ctx,
1072                                 global->channels[0].server_id,
1073                                 MSG_SMBXSRV_SESSION_CLOSE, &blob);
1074         TALLOC_FREE(state->db_rec);
1075         if (tevent_req_nterror(req, status)) {
1076                 return;
1077         }
1078
1079         TALLOC_FREE(global);
1080         return;
1081 }
1082
1083 static void smb2srv_session_close_previous_modified(struct tevent_req *subreq)
1084 {
1085         struct tevent_req *req =
1086                 tevent_req_callback_data(subreq,
1087                 struct tevent_req);
1088         struct smb2srv_session_close_previous_state *state =
1089                 tevent_req_data(req,
1090                 struct smb2srv_session_close_previous_state);
1091         NTSTATUS status;
1092
1093         status = dbwrap_record_watch_recv(subreq, state, &state->db_rec);
1094         TALLOC_FREE(subreq);
1095         if (tevent_req_nterror(req, status)) {
1096                 return;
1097         }
1098
1099         smb2srv_session_close_previous_check(req);
1100 }
1101
1102 NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req)
1103 {
1104         NTSTATUS status;
1105
1106         if (tevent_req_is_nterror(req, &status)) {
1107                 tevent_req_received(req);
1108                 return status;
1109         }
1110
1111         tevent_req_received(req);
1112         return NT_STATUS_OK;
1113 }
1114
1115 static NTSTATUS smbXsrv_session_clear_and_logoff(struct smbXsrv_session *session)
1116 {
1117         NTSTATUS status;
1118         struct smbXsrv_connection *xconn = NULL;
1119
1120         if (session->client != NULL) {
1121                 xconn = session->client->connections;
1122         }
1123
1124         for (; xconn != NULL; xconn = xconn->next) {
1125                 struct smbd_smb2_request *preq;
1126
1127                 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1128                         if (preq->session != session) {
1129                                 continue;
1130                         }
1131
1132                         preq->session = NULL;
1133                         /*
1134                          * If we no longer have a session we can't
1135                          * sign or encrypt replies.
1136                          */
1137                         preq->do_signing = false;
1138                         preq->do_encryption = false;
1139                         preq->preauth = NULL;
1140                 }
1141         }
1142
1143         status = smbXsrv_session_logoff(session);
1144         return status;
1145 }
1146
1147 static int smbXsrv_session_destructor(struct smbXsrv_session *session)
1148 {
1149         NTSTATUS status;
1150
1151         status = smbXsrv_session_clear_and_logoff(session);
1152         if (!NT_STATUS_IS_OK(status)) {
1153                 DEBUG(0, ("smbXsrv_session_destructor: "
1154                           "smbXsrv_session_logoff() failed: %s\n",
1155                           nt_errstr(status)));
1156         }
1157
1158         TALLOC_FREE(session->global);
1159
1160         return 0;
1161 }
1162
1163 NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn,
1164                                 NTTIME now,
1165                                 struct smbXsrv_session **_session)
1166 {
1167         struct smbXsrv_session_table *table = conn->client->session_table;
1168         struct db_record *local_rec = NULL;
1169         struct smbXsrv_session *session = NULL;
1170         void *ptr = NULL;
1171         TDB_DATA val;
1172         struct smbXsrv_session_global0 *global = NULL;
1173         struct smbXsrv_channel_global0 *channels = NULL;
1174         NTSTATUS status;
1175
1176         if (table->local.num_sessions >= table->local.max_sessions) {
1177                 return NT_STATUS_INSUFFICIENT_RESOURCES;
1178         }
1179
1180         session = talloc_zero(table, struct smbXsrv_session);
1181         if (session == NULL) {
1182                 return NT_STATUS_NO_MEMORY;
1183         }
1184         session->table = table;
1185         session->idle_time = now;
1186         session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
1187         session->client = conn->client;
1188
1189         if (conn->protocol >= PROTOCOL_SMB3_10) {
1190                 session->preauth = talloc(session, struct smbXsrv_preauth);
1191                 if (session->preauth == NULL) {
1192                         TALLOC_FREE(session);
1193                         return NT_STATUS_NO_MEMORY;
1194                 }
1195                 *session->preauth = conn->smb2.preauth;
1196         }
1197
1198         status = smbXsrv_session_global_allocate(table->global.db_ctx,
1199                                                  session,
1200                                                  &global);
1201         if (!NT_STATUS_IS_OK(status)) {
1202                 TALLOC_FREE(session);
1203                 return status;
1204         }
1205         session->global = global;
1206
1207         if (conn->protocol >= PROTOCOL_SMB2_02) {
1208                 uint64_t id = global->session_global_id;
1209                 uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
1210                 TDB_DATA key;
1211
1212                 global->connection_dialect = conn->smb2.server.dialect;
1213
1214                 global->session_wire_id = id;
1215
1216                 status = smb2srv_tcon_table_init(session);
1217                 if (!NT_STATUS_IS_OK(status)) {
1218                         TALLOC_FREE(session);
1219                         return status;
1220                 }
1221
1222                 session->local_id = global->session_global_id;
1223
1224                 key = smbXsrv_session_local_id_to_key(session->local_id, key_buf);
1225
1226                 local_rec = dbwrap_fetch_locked(table->local.db_ctx,
1227                                                 session, key);
1228                 if (local_rec == NULL) {
1229                         TALLOC_FREE(session);
1230                         return NT_STATUS_NO_MEMORY;
1231                 }
1232
1233                 val = dbwrap_record_get_value(local_rec);
1234                 if (val.dsize != 0) {
1235                         TALLOC_FREE(session);
1236                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1237                 }
1238         } else {
1239
1240                 status = smb1srv_session_local_allocate_id(table->local.db_ctx,
1241                                                         table->local.lowest_id,
1242                                                         table->local.highest_id,
1243                                                         session,
1244                                                         &local_rec,
1245                                                         &session->local_id);
1246                 if (!NT_STATUS_IS_OK(status)) {
1247                         TALLOC_FREE(session);
1248                         return status;
1249                 }
1250
1251                 global->session_wire_id = session->local_id;
1252         }
1253
1254         global->creation_time = now;
1255         global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1256
1257         global->num_channels = 1;
1258         channels = talloc_zero_array(global,
1259                                      struct smbXsrv_channel_global0,
1260                                      global->num_channels);
1261         if (channels == NULL) {
1262                 TALLOC_FREE(session);
1263                 return NT_STATUS_NO_MEMORY;
1264         }
1265         global->channels = channels;
1266
1267         channels[0].server_id = messaging_server_id(conn->msg_ctx);
1268         channels[0].local_address = tsocket_address_string(conn->local_address,
1269                                                            channels);
1270         if (channels[0].local_address == NULL) {
1271                 TALLOC_FREE(session);
1272                 return NT_STATUS_NO_MEMORY;
1273         }
1274         channels[0].remote_address = tsocket_address_string(conn->remote_address,
1275                                                             channels);
1276         if (channels[0].remote_address == NULL) {
1277                 TALLOC_FREE(session);
1278                 return NT_STATUS_NO_MEMORY;
1279         }
1280         channels[0].remote_name = talloc_strdup(channels, conn->remote_hostname);
1281         if (channels[0].remote_name == NULL) {
1282                 TALLOC_FREE(session);
1283                 return NT_STATUS_NO_MEMORY;
1284         }
1285         channels[0].signing_key = data_blob_null;
1286         channels[0].connection = conn;
1287
1288         ptr = session;
1289         val = make_tdb_data((uint8_t const *)&ptr, sizeof(ptr));
1290         status = dbwrap_record_store(local_rec, val, TDB_REPLACE);
1291         TALLOC_FREE(local_rec);
1292         if (!NT_STATUS_IS_OK(status)) {
1293                 TALLOC_FREE(session);
1294                 return status;
1295         }
1296         table->local.num_sessions += 1;
1297
1298         talloc_set_destructor(session, smbXsrv_session_destructor);
1299
1300         status = smbXsrv_session_global_store(global);
1301         if (!NT_STATUS_IS_OK(status)) {
1302                 DEBUG(0,("smbXsrv_session_create: "
1303                          "global_id (0x%08x) store failed - %s\n",
1304                          session->global->session_global_id,
1305                          nt_errstr(status)));
1306                 TALLOC_FREE(session);
1307                 return status;
1308         }
1309
1310         if (DEBUGLVL(10)) {
1311                 struct smbXsrv_sessionB session_blob;
1312
1313                 ZERO_STRUCT(session_blob);
1314                 session_blob.version = SMBXSRV_VERSION_0;
1315                 session_blob.info.info0 = session;
1316
1317                 DEBUG(10,("smbXsrv_session_create: global_id (0x%08x) stored\n",
1318                          session->global->session_global_id));
1319                 NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1320         }
1321
1322         *_session = session;
1323         return NT_STATUS_OK;
1324 }
1325
1326 NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session)
1327 {
1328         struct smbXsrv_session_table *table = session->table;
1329         NTSTATUS status;
1330         uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE];
1331         TDB_DATA key;
1332
1333         if (session->global->db_rec != NULL) {
1334                 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1335                           "Called with db_rec != NULL'\n",
1336                           session->global->session_global_id));
1337                 return NT_STATUS_INTERNAL_ERROR;
1338         }
1339
1340         key = smbXsrv_session_global_id_to_key(
1341                                         session->global->session_global_id,
1342                                         key_buf);
1343
1344         session->global->db_rec = dbwrap_fetch_locked(table->global.db_ctx,
1345                                                       session->global, key);
1346         if (session->global->db_rec == NULL) {
1347                 DEBUG(0, ("smbXsrv_session_update(0x%08x): "
1348                           "Failed to lock global key '%s'\n",
1349                           session->global->session_global_id,
1350                           hex_encode_talloc(talloc_tos(), key.dptr,
1351                                             key.dsize)));
1352                 return NT_STATUS_INTERNAL_DB_ERROR;
1353         }
1354
1355         status = smbXsrv_session_global_store(session->global);
1356         if (!NT_STATUS_IS_OK(status)) {
1357                 DEBUG(0,("smbXsrv_session_update: "
1358                          "global_id (0x%08x) store failed - %s\n",
1359                          session->global->session_global_id,
1360                          nt_errstr(status)));
1361                 return status;
1362         }
1363
1364         if (DEBUGLVL(10)) {
1365                 struct smbXsrv_sessionB session_blob;
1366
1367                 ZERO_STRUCT(session_blob);
1368                 session_blob.version = SMBXSRV_VERSION_0;
1369                 session_blob.info.info0 = session;
1370
1371                 DEBUG(10,("smbXsrv_session_update: global_id (0x%08x) stored\n",
1372                           session->global->session_global_id));
1373                 NDR_PRINT_DEBUG(smbXsrv_sessionB, &session_blob);
1374         }
1375
1376         return NT_STATUS_OK;
1377 }
1378
1379 NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session,
1380                                       const struct smbXsrv_connection *conn,
1381                                       struct smbXsrv_channel_global0 **_c)
1382 {
1383         uint32_t i;
1384
1385         for (i=0; i < session->global->num_channels; i++) {
1386                 struct smbXsrv_channel_global0 *c = &session->global->channels[i];
1387
1388                 if (c->connection == conn) {
1389                         *_c = c;
1390                         return NT_STATUS_OK;
1391                 }
1392         }
1393
1394         return NT_STATUS_USER_SESSION_DELETED;
1395 }
1396
1397 struct smb2srv_session_shutdown_state {
1398         struct tevent_queue *wait_queue;
1399 };
1400
1401 static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
1402
1403 struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
1404                                         struct tevent_context *ev,
1405                                         struct smbXsrv_session *session,
1406                                         struct smbd_smb2_request *current_req)
1407 {
1408         struct tevent_req *req;
1409         struct smb2srv_session_shutdown_state *state;
1410         struct tevent_req *subreq;
1411         struct smbXsrv_connection *xconn = NULL;
1412         size_t len = 0;
1413
1414         /*
1415          * Make sure that no new request will be able to use this session.
1416          */
1417         session->status = NT_STATUS_USER_SESSION_DELETED;
1418
1419         req = tevent_req_create(mem_ctx, &state,
1420                                 struct smb2srv_session_shutdown_state);
1421         if (req == NULL) {
1422                 return NULL;
1423         }
1424
1425         state->wait_queue = tevent_queue_create(state, "smb2srv_session_shutdown_queue");
1426         if (tevent_req_nomem(state->wait_queue, req)) {
1427                 return tevent_req_post(req, ev);
1428         }
1429
1430         for (xconn = session->client->connections; xconn != NULL; xconn = xconn->next) {
1431                 struct smbd_smb2_request *preq;
1432
1433                 for (preq = xconn->smb2.requests; preq != NULL; preq = preq->next) {
1434                         if (preq == current_req) {
1435                                 /* Can't cancel current request. */
1436                                 continue;
1437                         }
1438                         if (preq->session != session) {
1439                                 /* Request on different session. */
1440                                 continue;
1441                         }
1442
1443                         if (!NT_STATUS_IS_OK(xconn->transport.status)) {
1444                                 preq->session = NULL;
1445                                 /*
1446                                  * If we no longer have a session we can't
1447                                  * sign or encrypt replies.
1448                                  */
1449                                 preq->do_signing = false;
1450                                 preq->do_encryption = false;
1451                                 preq->preauth = NULL;
1452
1453                                 if (preq->subreq != NULL) {
1454                                         tevent_req_cancel(preq->subreq);
1455                                 }
1456                                 continue;
1457                         }
1458
1459                         /*
1460                          * Never cancel anything in a compound
1461                          * request. Way too hard to deal with
1462                          * the result.
1463                          */
1464                         if (!preq->compound_related && preq->subreq != NULL) {
1465                                 tevent_req_cancel(preq->subreq);
1466                         }
1467
1468                         /*
1469                          * Now wait until the request is finished.
1470                          *
1471                          * We don't set a callback, as we just want to block the
1472                          * wait queue and the talloc_free() of the request will
1473                          * remove the item from the wait queue.
1474                          */
1475                         subreq = tevent_queue_wait_send(preq, ev, state->wait_queue);
1476                         if (tevent_req_nomem(subreq, req)) {
1477                                 return tevent_req_post(req, ev);
1478                         }
1479                 }
1480         }
1481
1482         len = tevent_queue_length(state->wait_queue);
1483         if (len == 0) {
1484                 tevent_req_done(req);
1485                 return tevent_req_post(req, ev);
1486         }
1487
1488         /*
1489          * Now we add our own waiter to the end of the queue,
1490          * this way we get notified when all pending requests are finished
1491          * and send to the socket.
1492          */
1493         subreq = tevent_queue_wait_send(state, ev, state->wait_queue);
1494         if (tevent_req_nomem(subreq, req)) {
1495                 return tevent_req_post(req, ev);
1496         }
1497         tevent_req_set_callback(subreq, smb2srv_session_shutdown_wait_done, req);
1498
1499         return req;
1500 }
1501
1502 static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq)
1503 {
1504         struct tevent_req *req =
1505                 tevent_req_callback_data(subreq,
1506                 struct tevent_req);
1507
1508         tevent_queue_wait_recv(subreq);
1509         TALLOC_FREE(subreq);
1510
1511         tevent_req_done(req);
1512 }
1513
1514 NTSTATUS smb2srv_session_shutdown_recv(struct tevent_req *req)
1515 {
1516         return tevent_req_simple_recv_ntstatus(req);
1517 }
1518
1519 NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
1520 {
1521         struct smbXsrv_session_table *table;
1522         struct db_record *local_rec = NULL;
1523         struct db_record *global_rec = NULL;
1524         struct smbd_server_connection *sconn = NULL;
1525         NTSTATUS status;
1526         NTSTATUS error = NT_STATUS_OK;
1527
1528         if (session->table == NULL) {
1529                 return NT_STATUS_OK;
1530         }
1531
1532         table = session->table;
1533         session->table = NULL;
1534
1535         sconn = session->client->sconn;
1536         session->client = NULL;
1537         session->status = NT_STATUS_USER_SESSION_DELETED;
1538
1539         global_rec = session->global->db_rec;
1540         session->global->db_rec = NULL;
1541         if (global_rec == NULL) {
1542                 uint8_t key_buf[SMBXSRV_SESSION_GLOBAL_TDB_KEY_SIZE];
1543                 TDB_DATA key;
1544
1545                 key = smbXsrv_session_global_id_to_key(
1546                                         session->global->session_global_id,
1547                                         key_buf);
1548
1549                 global_rec = dbwrap_fetch_locked(table->global.db_ctx,
1550                                                  session->global, key);
1551                 if (global_rec == NULL) {
1552                         DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1553                                   "Failed to lock global key '%s'\n",
1554                                   session->global->session_global_id,
1555                                   hex_encode_talloc(global_rec, key.dptr,
1556                                                     key.dsize)));
1557                         error = NT_STATUS_INTERNAL_ERROR;
1558                 }
1559         }
1560
1561         if (global_rec != NULL) {
1562                 status = dbwrap_record_delete(global_rec);
1563                 if (!NT_STATUS_IS_OK(status)) {
1564                         TDB_DATA key = dbwrap_record_get_key(global_rec);
1565
1566                         DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1567                                   "failed to delete global key '%s': %s\n",
1568                                   session->global->session_global_id,
1569                                   hex_encode_talloc(global_rec, key.dptr,
1570                                                     key.dsize),
1571                                   nt_errstr(status)));
1572                         error = status;
1573                 }
1574         }
1575         TALLOC_FREE(global_rec);
1576
1577         local_rec = session->db_rec;
1578         if (local_rec == NULL) {
1579                 uint8_t key_buf[SMBXSRV_SESSION_LOCAL_TDB_KEY_SIZE];
1580                 TDB_DATA key;
1581
1582                 key = smbXsrv_session_local_id_to_key(session->local_id,
1583                                                       key_buf);
1584
1585                 local_rec = dbwrap_fetch_locked(table->local.db_ctx,
1586                                                 session, key);
1587                 if (local_rec == NULL) {
1588                         DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1589                                   "Failed to lock local key '%s'\n",
1590                                   session->global->session_global_id,
1591                                   hex_encode_talloc(local_rec, key.dptr,
1592                                                     key.dsize)));
1593                         error = NT_STATUS_INTERNAL_ERROR;
1594                 }
1595         }
1596
1597         if (local_rec != NULL) {
1598                 status = dbwrap_record_delete(local_rec);
1599                 if (!NT_STATUS_IS_OK(status)) {
1600                         TDB_DATA key = dbwrap_record_get_key(local_rec);
1601
1602                         DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1603                                   "failed to delete local key '%s': %s\n",
1604                                   session->global->session_global_id,
1605                                   hex_encode_talloc(local_rec, key.dptr,
1606                                                     key.dsize),
1607                                   nt_errstr(status)));
1608                         error = status;
1609                 }
1610                 table->local.num_sessions -= 1;
1611         }
1612         if (session->db_rec == NULL) {
1613                 TALLOC_FREE(local_rec);
1614         }
1615         session->db_rec = NULL;
1616
1617         if (session->compat) {
1618                 file_close_user(sconn, session->compat->vuid);
1619         }
1620
1621         if (session->tcon_table != NULL) {
1622                 /*
1623                  * Note: We only have a tcon_table for SMB2.
1624                  */
1625                 status = smb2srv_tcon_disconnect_all(session);
1626                 if (!NT_STATUS_IS_OK(status)) {
1627                         DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
1628                                   "smb2srv_tcon_disconnect_all() failed: %s\n",
1629                                   session->global->session_global_id,
1630                                   nt_errstr(status)));
1631                         error = status;
1632                 }
1633         }
1634
1635         if (session->compat) {
1636                 invalidate_vuid(sconn, session->compat->vuid);
1637                 session->compat = NULL;
1638         }
1639
1640         return error;
1641 }
1642
1643 struct smbXsrv_session_logoff_all_state {
1644         NTSTATUS first_status;
1645         int errors;
1646 };
1647
1648 static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1649                                                void *private_data);
1650
1651 NTSTATUS smbXsrv_session_logoff_all(struct smbXsrv_connection *conn)
1652 {
1653         struct smbXsrv_session_table *table = conn->client->session_table;
1654         struct smbXsrv_session_logoff_all_state state;
1655         NTSTATUS status;
1656         int count = 0;
1657
1658         if (table == NULL) {
1659                 DEBUG(10, ("smbXsrv_session_logoff_all: "
1660                            "empty session_table, nothing to do.\n"));
1661                 return NT_STATUS_OK;
1662         }
1663
1664         ZERO_STRUCT(state);
1665
1666         status = dbwrap_traverse(table->local.db_ctx,
1667                                  smbXsrv_session_logoff_all_callback,
1668                                  &state, &count);
1669         if (!NT_STATUS_IS_OK(status)) {
1670                 DEBUG(0, ("smbXsrv_session_logoff_all: "
1671                           "dbwrap_traverse() failed: %s\n",
1672                           nt_errstr(status)));
1673                 return status;
1674         }
1675
1676         if (!NT_STATUS_IS_OK(state.first_status)) {
1677                 DEBUG(0, ("smbXsrv_session_logoff_all: "
1678                           "count[%d] errors[%d] first[%s]\n",
1679                           count, state.errors,
1680                           nt_errstr(state.first_status)));
1681                 return state.first_status;
1682         }
1683
1684         return NT_STATUS_OK;
1685 }
1686
1687 static int smbXsrv_session_logoff_all_callback(struct db_record *local_rec,
1688                                                void *private_data)
1689 {
1690         struct smbXsrv_session_logoff_all_state *state =
1691                 (struct smbXsrv_session_logoff_all_state *)private_data;
1692         TDB_DATA val;
1693         void *ptr = NULL;
1694         struct smbXsrv_session *session = NULL;
1695         NTSTATUS status;
1696
1697         val = dbwrap_record_get_value(local_rec);
1698         if (val.dsize != sizeof(ptr)) {
1699                 status = NT_STATUS_INTERNAL_ERROR;
1700                 if (NT_STATUS_IS_OK(state->first_status)) {
1701                         state->first_status = status;
1702                 }
1703                 state->errors++;
1704                 return 0;
1705         }
1706
1707         memcpy(&ptr, val.dptr, val.dsize);
1708         session = talloc_get_type_abort(ptr, struct smbXsrv_session);
1709
1710         session->db_rec = local_rec;
1711
1712         status = smbXsrv_session_clear_and_logoff(session);
1713         if (!NT_STATUS_IS_OK(status)) {
1714                 if (NT_STATUS_IS_OK(state->first_status)) {
1715                         state->first_status = status;
1716                 }
1717                 state->errors++;
1718                 return 0;
1719         }
1720
1721         return 0;
1722 }
1723
1724 NTSTATUS smb1srv_session_table_init(struct smbXsrv_connection *conn)
1725 {
1726         /*
1727          * Allow a range from 1..65534 with 65534 values.
1728          */
1729         return smbXsrv_session_table_init(conn, 1, UINT16_MAX - 1,
1730                                           UINT16_MAX - 1);
1731 }
1732
1733 NTSTATUS smb1srv_session_lookup(struct smbXsrv_connection *conn,
1734                                 uint16_t vuid, NTTIME now,
1735                                 struct smbXsrv_session **session)
1736 {
1737         struct smbXsrv_session_table *table = conn->client->session_table;
1738         uint32_t local_id = vuid;
1739
1740         return smbXsrv_session_local_lookup(table, conn, local_id, now,
1741                                             session);
1742 }
1743
1744 NTSTATUS smb2srv_session_table_init(struct smbXsrv_connection *conn)
1745 {
1746         /*
1747          * Allow a range from 1..4294967294 with 65534 (same as SMB1) values.
1748          */
1749         return smbXsrv_session_table_init(conn, 1, UINT32_MAX - 1,
1750                                           UINT16_MAX - 1);
1751 }
1752
1753 static NTSTATUS smb2srv_session_lookup_raw(struct smbXsrv_session_table *table,
1754                                            /* conn: optional */
1755                                            struct smbXsrv_connection *conn,
1756                                            uint64_t session_id, NTTIME now,
1757                                            struct smbXsrv_session **session)
1758 {
1759         uint32_t local_id = session_id & UINT32_MAX;
1760         uint64_t local_zeros = session_id & 0xFFFFFFFF00000000LLU;
1761
1762         if (local_zeros != 0) {
1763                 return NT_STATUS_USER_SESSION_DELETED;
1764         }
1765
1766         return smbXsrv_session_local_lookup(table, conn, local_id, now,
1767                                             session);
1768 }
1769
1770 NTSTATUS smb2srv_session_lookup_conn(struct smbXsrv_connection *conn,
1771                                      uint64_t session_id, NTTIME now,
1772                                      struct smbXsrv_session **session)
1773 {
1774         struct smbXsrv_session_table *table = conn->client->session_table;
1775         return smb2srv_session_lookup_raw(table, conn, session_id, now,
1776                                           session);
1777 }
1778
1779 struct smbXsrv_session_global_traverse_state {
1780         int (*fn)(struct smbXsrv_session_global0 *, void *);
1781         void *private_data;
1782 };
1783
1784 static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
1785 {
1786         int ret = -1;
1787         struct smbXsrv_session_global_traverse_state *state =
1788                 (struct smbXsrv_session_global_traverse_state*)data;
1789         TDB_DATA key = dbwrap_record_get_key(rec);
1790         TDB_DATA val = dbwrap_record_get_value(rec);
1791         DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
1792         struct smbXsrv_session_globalB global_blob;
1793         enum ndr_err_code ndr_err;
1794         TALLOC_CTX *frame = talloc_stackframe();
1795
1796         ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
1797                         (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_globalB);
1798         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1799                 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1800                          "key '%s' ndr_pull_struct_blob - %s\n",
1801                          hex_encode_talloc(frame, key.dptr, key.dsize),
1802                          ndr_errstr(ndr_err)));
1803                 goto done;
1804         }
1805
1806         if (global_blob.version != SMBXSRV_VERSION_0) {
1807                 DEBUG(1,("Invalid record in smbXsrv_session_global.tdb:"
1808                          "key '%s' unsuported version - %d\n",
1809                          hex_encode_talloc(frame, key.dptr, key.dsize),
1810                          (int)global_blob.version));
1811                 goto done;
1812         }
1813
1814         global_blob.info.info0->db_rec = rec;
1815         ret = state->fn(global_blob.info.info0, state->private_data);
1816 done:
1817         TALLOC_FREE(frame);
1818         return ret;
1819 }
1820
1821 NTSTATUS smbXsrv_session_global_traverse(
1822                         int (*fn)(struct smbXsrv_session_global0 *, void *),
1823                         void *private_data)
1824 {
1825
1826         NTSTATUS status;
1827         int count = 0;
1828         struct smbXsrv_session_global_traverse_state state = {
1829                 .fn = fn,
1830                 .private_data = private_data,
1831         };
1832
1833         become_root();
1834         status = smbXsrv_session_global_init();
1835         if (!NT_STATUS_IS_OK(status)) {
1836                 unbecome_root();
1837                 DEBUG(0, ("Failed to initialize session_global: %s\n",
1838                           nt_errstr(status)));
1839                 return status;
1840         }
1841
1842         status = dbwrap_traverse_read(smbXsrv_session_global_db_ctx,
1843                                       smbXsrv_session_global_traverse_fn,
1844                                       &state,
1845                                       &count);
1846         unbecome_root();
1847
1848         return status;
1849 }