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