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