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