Coverage Report

Created: 2025-12-31 06:20

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