Coverage Report

Created: 2026-09-03 07:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/smbd/smb2_negprot.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Core SMB2 server
4
5
   Copyright (C) Stefan Metzmacher 2009
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 "smbd/smbd.h"
23
#include "smbd/globals.h"
24
#include "../libcli/smb/smb_common.h"
25
#include "../libcli/smb/smb2_negotiate_context.h"
26
#include "../lib/tsocket/tsocket.h"
27
#include "../librpc/ndr/libndr.h"
28
#include "../libcli/smb/smb_signing.h"
29
#include "auth.h"
30
#include "auth/gensec/gensec.h"
31
#include "lib/util/string_wrappers.h"
32
#include "source3/lib/substitute.h"
33
#ifdef HAVE_VALGRIND_CALLGRIND_H
34
#include <valgrind/callgrind.h>
35
#endif /* HAVE_VALGRIND_CALLGRIND_H */
36
37
#undef DBGC_CLASS
38
0
#define DBGC_CLASS DBGC_SMB2
39
40
/*
41
 * this is the entry point if SMB2 is selected via
42
 * the SMB negprot and the given dialect.
43
 */
44
static NTSTATUS reply_smb20xx(struct smb_request *req, uint16_t dialect)
45
0
{
46
0
  uint8_t *smb2_inpdu;
47
0
  uint8_t *smb2_hdr;
48
0
  uint8_t *smb2_body;
49
0
  uint8_t *smb2_dyn;
50
0
  size_t len = SMB2_HDR_BODY + 0x24 + 2;
51
52
0
  smb2_inpdu = talloc_zero_array(talloc_tos(), uint8_t, len);
53
0
  if (smb2_inpdu == NULL) {
54
0
    DEBUG(0, ("Could not push spnego blob\n"));
55
0
    reply_nterror(req, NT_STATUS_NO_MEMORY);
56
0
    return NT_STATUS_NO_MEMORY;
57
0
  }
58
0
  smb2_hdr = smb2_inpdu;
59
0
  smb2_body = smb2_hdr + SMB2_HDR_BODY;
60
0
  smb2_dyn = smb2_body + 0x24;
61
62
0
  SIVAL(smb2_hdr, SMB2_HDR_PROTOCOL_ID,  SMB2_MAGIC);
63
0
  SIVAL(smb2_hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
64
65
0
  SSVAL(smb2_body, 0x00, 0x0024);  /* struct size */
66
0
  SSVAL(smb2_body, 0x02, 0x0001);  /* dialect count */
67
68
0
  SSVAL(smb2_dyn,  0x00, dialect);
69
70
0
  req->outbuf = NULL;
71
72
0
  return smbd_smb2_process_negprot(req->xconn, 0, smb2_inpdu, len);
73
0
}
74
75
/*
76
 * this is the entry point if SMB2 is selected via
77
 * the SMB negprot and the "SMB 2.002" dialect.
78
 */
79
NTSTATUS reply_smb2002(struct smb_request *req, uint16_t choice)
80
0
{
81
0
  return reply_smb20xx(req, SMB2_DIALECT_REVISION_202);
82
0
}
83
84
/*
85
 * this is the entry point if SMB2 is selected via
86
 * the SMB negprot and the "SMB 2.???" dialect.
87
 */
88
NTSTATUS reply_smb20ff(struct smb_request *req, uint16_t choice)
89
0
{
90
0
  struct smbXsrv_connection *xconn = req->xconn;
91
0
  xconn->smb2.allow_2ff = true;
92
0
  return reply_smb20xx(req, SMB2_DIALECT_REVISION_2FF);
93
0
}
94
95
enum protocol_types smbd_smb2_protocol_dialect_match(const uint8_t *indyn,
96
        const int dialect_count,
97
        uint16_t *dialect)
98
0
{
99
0
  static const struct {
100
0
    enum protocol_types proto;
101
0
    uint16_t dialect;
102
0
  } pd[] = {
103
0
    { PROTOCOL_SMB3_11, SMB3_DIALECT_REVISION_311 },
104
0
    { PROTOCOL_SMB3_02, SMB3_DIALECT_REVISION_302 },
105
0
    { PROTOCOL_SMB3_00, SMB3_DIALECT_REVISION_300 },
106
0
    { PROTOCOL_SMB2_10, SMB2_DIALECT_REVISION_210 },
107
0
    { PROTOCOL_SMB2_02, SMB2_DIALECT_REVISION_202 },
108
0
  };
109
0
  size_t i;
110
111
0
  for (i = 0; i < ARRAY_SIZE(pd); i ++) {
112
0
    int c = 0;
113
114
0
    if (lp_server_max_protocol() < pd[i].proto) {
115
0
      continue;
116
0
    }
117
0
    if (lp_server_min_protocol() > pd[i].proto) {
118
0
      continue;
119
0
    }
120
121
0
    for (c = 0; c < dialect_count; c++) {
122
0
      *dialect = SVAL(indyn, c*2);
123
0
      if (*dialect == pd[i].dialect) {
124
0
        return pd[i].proto;
125
0
      }
126
0
    }
127
0
  }
128
129
0
  return PROTOCOL_NONE;
130
0
}
131
132
static NTSTATUS smb2_negotiate_context_process_posix(
133
  const struct smb2_negotiate_contexts *in_c,
134
  bool *posix)
135
0
{
136
0
  struct smb2_negotiate_context *in_posix = NULL;
137
0
  const uint8_t *inbuf = NULL;
138
0
  size_t inbuflen;
139
0
  bool posix_found = false;
140
0
  size_t ofs;
141
0
  int cmp;
142
143
0
  *posix = false;
144
145
0
  if (!lp_smb3_unix_extensions(GLOBAL_SECTION_SNUM)) {
146
0
    return NT_STATUS_OK;
147
0
  }
148
149
0
  in_posix = smb2_negotiate_context_find(in_c,
150
0
                 SMB2_POSIX_EXTENSIONS_AVAILABLE);
151
0
  if (in_posix == NULL) {
152
0
    return NT_STATUS_OK;
153
0
  }
154
155
0
  inbuf = in_posix->data.data;
156
0
  inbuflen = in_posix->data.length;
157
158
  /*
159
   * For now the server only supports one variant.
160
   * Check it's the right one.
161
   */
162
0
  if ((inbuflen % 16) != 0) {
163
0
    return NT_STATUS_INVALID_PARAMETER;
164
0
  }
165
166
0
  SMB_ASSERT(strlen(SMB2_CREATE_TAG_POSIX) == 16);
167
168
0
  for (ofs = 0; ofs < inbuflen; ofs += 16) {
169
0
    cmp = memcmp(inbuf+ofs, SMB2_CREATE_TAG_POSIX, 16);
170
0
    if (cmp == 0) {
171
0
      posix_found = true;
172
0
      break;
173
0
    }
174
0
  }
175
176
0
  if (!posix_found) {
177
0
    DBG_DEBUG("Client requested unknown SMB3 Unix extensions:\n");
178
0
    dump_data(10, inbuf, inbuflen);
179
0
    return NT_STATUS_OK;
180
0
  }
181
182
0
  DBG_DEBUG("Client requested SMB3 Unix extensions\n");
183
0
  *posix = true;
184
0
  return NT_STATUS_OK;
185
0
}
186
187
struct smbd_smb2_request_process_negprot_state {
188
  struct smbd_smb2_request *req;
189
  DATA_BLOB outbody;
190
  DATA_BLOB outdyn;
191
};
192
193
static void smbd_smb2_request_process_negprot_mc_done(struct tevent_req *subreq);
194
195
NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
196
0
{
197
0
  struct smbd_smb2_request_process_negprot_state *state = NULL;
198
0
  struct smbXsrv_connection *xconn = req->xconn;
199
0
  struct tevent_req *subreq = NULL;
200
0
  NTSTATUS status;
201
0
  const uint8_t *inbody;
202
0
  const uint8_t *indyn = NULL;
203
0
  DATA_BLOB outbody;
204
0
  DATA_BLOB outdyn;
205
0
  DATA_BLOB negprot_spnego_blob;
206
0
  uint16_t security_offset;
207
0
  DATA_BLOB security_buffer;
208
0
  size_t expected_dyn_size = 0;
209
0
  size_t c;
210
0
  uint16_t security_mode;
211
0
  uint16_t dialect_count;
212
0
  uint16_t in_security_mode;
213
0
  uint32_t in_capabilities;
214
0
  DATA_BLOB in_guid_blob;
215
0
  struct GUID in_guid;
216
0
  struct smb2_negotiate_contexts in_c = { .num_contexts = 0, };
217
0
  struct smb2_negotiate_context *in_preauth = NULL;
218
0
  struct smb2_negotiate_context *in_cipher = NULL;
219
0
  struct smb2_negotiate_context *in_sign_algo = NULL;
220
0
  struct smb2_negotiate_context *in_transport_caps = NULL;
221
0
  struct smb2_negotiate_contexts out_c = { .num_contexts = 0, };
222
0
  const struct smb311_capabilities default_smb3_capabilities =
223
0
    smb311_capabilities_parse(
224
0
      "server",
225
0
      lp_server_smb3_signing_algorithms(),
226
0
      lp_server_smb3_encryption_algorithms(),
227
0
      true);
228
0
  DATA_BLOB out_negotiate_context_blob = data_blob_null;
229
0
  uint32_t out_negotiate_context_offset = 0;
230
0
  uint16_t out_negotiate_context_count = 0;
231
0
  uint16_t dialect = 0;
232
0
  uint32_t capabilities;
233
0
  struct GUID_ndr_buf out_guid_buf;
234
0
  struct GUID out_guid;
235
0
  enum protocol_types protocol = PROTOCOL_NONE;
236
0
  uint32_t max_limit;
237
0
  uint32_t max_trans = lp_smb2_max_trans();
238
0
  uint32_t max_read = lp_smb2_max_read();
239
0
  uint32_t max_write = lp_smb2_max_write();
240
0
  NTTIME now = timeval_to_nttime(&req->request_time);
241
0
  bool posix = false;
242
0
  bool ok;
243
244
0
  status = smbd_smb2_request_verify_sizes(req, 0x24);
245
0
  if (!NT_STATUS_IS_OK(status)) {
246
0
    return smbd_smb2_request_error(req, status);
247
0
  }
248
0
  inbody = SMBD_SMB2_IN_BODY_PTR(req);
249
250
0
  dialect_count = SVAL(inbody, 0x02);
251
252
0
  in_security_mode = SVAL(inbody, 0x04);
253
0
  in_capabilities = IVAL(inbody, 0x08);
254
0
  in_guid_blob = data_blob_const(inbody + 0x0C, 16);
255
256
0
  if (dialect_count == 0) {
257
0
    return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
258
0
  }
259
260
0
  status = GUID_from_ndr_blob(&in_guid_blob, &in_guid);
261
0
  if (!NT_STATUS_IS_OK(status)) {
262
0
    return smbd_smb2_request_error(req, status);
263
0
  }
264
265
0
  expected_dyn_size = dialect_count * 2;
266
0
  if (SMBD_SMB2_IN_DYN_LEN(req) < expected_dyn_size) {
267
0
    return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
268
0
  }
269
0
  indyn = SMBD_SMB2_IN_DYN_PTR(req);
270
271
0
  protocol = smbd_smb2_protocol_dialect_match(indyn,
272
0
          dialect_count,
273
0
          &dialect);
274
275
0
  for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) {
276
0
    if (lp_server_max_protocol() < PROTOCOL_SMB2_10) {
277
0
      break;
278
0
    }
279
280
0
    dialect = SVAL(indyn, c*2);
281
0
    if (dialect == SMB2_DIALECT_REVISION_2FF) {
282
0
      if (xconn->smb2.allow_2ff) {
283
0
        xconn->smb2.allow_2ff = false;
284
0
        protocol = PROTOCOL_SMB2_10;
285
0
        break;
286
0
      }
287
0
    }
288
0
  }
289
290
0
  if (protocol == PROTOCOL_NONE) {
291
0
    return smbd_smb2_request_error(req, NT_STATUS_NOT_SUPPORTED);
292
0
  }
293
294
0
  if (protocol >= PROTOCOL_SMB3_11) {
295
0
    uint32_t in_negotiate_context_offset = 0;
296
0
    uint16_t in_negotiate_context_count = 0;
297
0
    DATA_BLOB in_negotiate_context_blob = data_blob_null;
298
0
    size_t ofs;
299
300
0
    in_negotiate_context_offset = IVAL(inbody, 0x1C);
301
0
    in_negotiate_context_count = SVAL(inbody, 0x20);
302
303
0
    ofs = SMB2_HDR_BODY;
304
0
    ofs += SMBD_SMB2_IN_BODY_LEN(req);
305
0
    ofs += expected_dyn_size;
306
0
    if ((ofs % 8) != 0) {
307
0
      ofs += 8 - (ofs % 8);
308
0
    }
309
310
0
    if (in_negotiate_context_offset != ofs) {
311
0
      return smbd_smb2_request_error(req,
312
0
          NT_STATUS_INVALID_PARAMETER);
313
0
    }
314
315
0
    ofs -= SMB2_HDR_BODY;
316
0
    ofs -= SMBD_SMB2_IN_BODY_LEN(req);
317
318
0
    if (SMBD_SMB2_IN_DYN_LEN(req) < ofs) {
319
0
      return smbd_smb2_request_error(req,
320
0
          NT_STATUS_INVALID_PARAMETER);
321
0
    }
322
323
0
    in_negotiate_context_blob = data_blob_const(indyn,
324
0
            SMBD_SMB2_IN_DYN_LEN(req));
325
326
0
    in_negotiate_context_blob.data += ofs;
327
0
    in_negotiate_context_blob.length -= ofs;
328
329
0
    status = smb2_negotiate_context_parse(req,
330
0
                  in_negotiate_context_blob,
331
0
                  in_negotiate_context_count,
332
0
                  &in_c);
333
0
    if (!NT_STATUS_IS_OK(status)) {
334
0
      return smbd_smb2_request_error(req, status);
335
0
    }
336
337
0
    status = smb2_negotiate_context_process_posix(&in_c, &posix);
338
0
    if (!NT_STATUS_IS_OK(status)) {
339
0
      return smbd_smb2_request_error(req, status);
340
0
    }
341
0
  }
342
343
0
  if ((dialect != SMB2_DIALECT_REVISION_2FF) &&
344
0
      (protocol >= PROTOCOL_SMB2_10) &&
345
0
      !GUID_all_zero(&in_guid))
346
0
  {
347
0
    ok = remote_arch_cache_update(&in_guid);
348
0
    if (!ok) {
349
0
      return smbd_smb2_request_error(
350
0
        req, NT_STATUS_UNSUCCESSFUL);
351
0
    }
352
0
  }
353
354
0
  switch (get_remote_arch()) {
355
0
  case RA_VISTA:
356
0
  case RA_SAMBA:
357
0
  case RA_CIFSFS:
358
0
  case RA_OSX:
359
0
    break;
360
0
  default:
361
0
    set_remote_arch(RA_VISTA);
362
0
    break;
363
0
  }
364
365
0
  {
366
0
    fstring proto;
367
0
    fstr_sprintf(proto,
368
0
           "SMB%X_%02X",
369
0
           (dialect >> 8) & 0xFF, dialect & 0xFF);
370
0
    set_remote_proto(proto);
371
0
    DEBUG(3,("Selected protocol %s\n", proto));
372
0
  }
373
374
0
  reload_services(req->sconn, conn_snum_used, true);
375
376
0
  in_preauth = smb2_negotiate_context_find(&in_c,
377
0
          SMB2_PREAUTH_INTEGRITY_CAPABILITIES);
378
0
  if (protocol >= PROTOCOL_SMB3_11 && in_preauth == NULL) {
379
0
    return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
380
0
  }
381
0
  in_cipher = smb2_negotiate_context_find(&in_c,
382
0
          SMB2_ENCRYPTION_CAPABILITIES);
383
0
  in_sign_algo = smb2_negotiate_context_find(&in_c,
384
0
          SMB2_SIGNING_CAPABILITIES);
385
0
  in_transport_caps =  smb2_negotiate_context_find(&in_c,
386
0
          SMB2_TRANSPORT_CAPABILITIES);
387
388
0
  negprot_spnego_blob = negprot_spnego(req, xconn);
389
0
  if (negprot_spnego_blob.data == NULL) {
390
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
391
0
  }
392
393
0
  security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
394
0
  if (xconn->smb2.signing_mandatory) {
395
0
    security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
396
0
  }
397
398
0
  capabilities = 0;
399
0
  if (lp_host_msdfs()) {
400
0
    capabilities |= SMB2_CAP_DFS;
401
0
  }
402
403
0
  if (protocol >= PROTOCOL_SMB2_10 &&
404
0
      lp_smb2_leases() &&
405
0
      lp_oplocks(GLOBAL_SECTION_SNUM) &&
406
0
      !lp_kernel_oplocks(GLOBAL_SECTION_SNUM))
407
0
  {
408
0
    capabilities |= SMB2_CAP_LEASING;
409
0
  }
410
411
0
  if ((protocol >= PROTOCOL_SMB3_00) &&
412
0
      (lp_server_smb_encrypt(xconn, -1) != SMB_ENCRYPTION_OFF) &&
413
0
      (in_capabilities & SMB2_CAP_ENCRYPTION)) {
414
0
    capabilities |= SMB2_CAP_ENCRYPTION;
415
0
  }
416
417
0
  if (protocol >= PROTOCOL_SMB3_00) {
418
0
    if (in_capabilities & SMB2_CAP_DIRECTORY_LEASING &&
419
0
        lp_smb3_directory_leases())
420
0
    {
421
0
      capabilities |= SMB2_CAP_DIRECTORY_LEASING;
422
0
    }
423
0
    if (in_capabilities & SMB2_CAP_PERSISTENT_HANDLES &&
424
0
        lp_persistent_handles())
425
0
    {
426
0
      capabilities |= SMB2_CAP_PERSISTENT_HANDLES;
427
0
    }
428
0
  }
429
430
  /*
431
   * 0x10000 (65536) is the maximum allowed message size
432
   * for SMB 2.0
433
   */
434
0
  max_limit = 0x10000;
435
436
0
  if (protocol >= PROTOCOL_SMB2_10) {
437
    /* largeMTU is not supported over NBT (tcp port 139) */
438
0
    if (xconn->transport.type != SMB_TRANSPORT_TYPE_NBT) {
439
0
      capabilities |= SMB2_CAP_LARGE_MTU;
440
0
      xconn->smb2.credits.multicredit = true;
441
442
      /*
443
       * We allow up to almost 16MB.
444
       *
445
       * The maximum PDU size is 0xFFFFFF (16776960)
446
       * and we need some space for the header.
447
       */
448
0
      max_limit = 0xFFFF00;
449
0
    }
450
0
  }
451
452
  /*
453
   * the defaults are 8MB, but we'll limit this to max_limit based on
454
   * the dialect (64kb for SMB 2.0, 8MB for SMB >= 2.1 with LargeMTU)
455
   *
456
   * user configured values exceeding the limits will be overwritten,
457
   * only smaller values will be accepted
458
   */
459
460
0
  max_trans = MIN(max_limit, lp_smb2_max_trans());
461
0
  max_read = MIN(max_limit, lp_smb2_max_read());
462
0
  max_write = MIN(max_limit, lp_smb2_max_write());
463
464
0
  if (in_preauth != NULL) {
465
0
    size_t needed = 4;
466
0
    uint16_t hash_count;
467
0
    uint16_t salt_length;
468
0
    uint16_t selected_preauth = 0;
469
0
    const uint8_t *p;
470
0
    uint8_t buf[38];
471
0
    size_t i;
472
473
0
    if (in_preauth->data.length < needed) {
474
0
      return smbd_smb2_request_error(req,
475
0
          NT_STATUS_INVALID_PARAMETER);
476
0
    }
477
478
0
    hash_count = SVAL(in_preauth->data.data, 0);
479
0
    salt_length = SVAL(in_preauth->data.data, 2);
480
481
0
    if (hash_count == 0) {
482
0
      return smbd_smb2_request_error(req,
483
0
          NT_STATUS_INVALID_PARAMETER);
484
0
    }
485
486
0
    p = in_preauth->data.data + needed;
487
0
    needed += hash_count * 2;
488
0
    needed += salt_length;
489
490
0
    if (in_preauth->data.length < needed) {
491
0
      return smbd_smb2_request_error(req,
492
0
          NT_STATUS_INVALID_PARAMETER);
493
0
    }
494
495
0
    for (i=0; i < hash_count; i++) {
496
0
      uint16_t v;
497
498
0
      v = SVAL(p, 0);
499
0
      p += 2;
500
501
0
      if (v == SMB2_PREAUTH_INTEGRITY_SHA512) {
502
0
        selected_preauth = v;
503
0
        break;
504
0
      }
505
0
    }
506
507
0
    if (selected_preauth == 0) {
508
0
      return smbd_smb2_request_error(req,
509
0
        NT_STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP);
510
0
    }
511
512
0
    SSVAL(buf, 0,  1); /* HashAlgorithmCount */
513
0
    SSVAL(buf, 2, 32); /* SaltLength */
514
0
    SSVAL(buf, 4, selected_preauth);
515
0
    generate_random_buffer(buf + 6, 32);
516
517
0
    status = smb2_negotiate_context_add(
518
0
      req,
519
0
      &out_c,
520
0
      SMB2_PREAUTH_INTEGRITY_CAPABILITIES,
521
0
      buf,
522
0
      sizeof(buf));
523
0
    if (!NT_STATUS_IS_OK(status)) {
524
0
      return smbd_smb2_request_error(req, status);
525
0
    }
526
527
0
    req->preauth = &req->xconn->smb2.preauth;
528
0
  }
529
530
0
  if (protocol >= PROTOCOL_SMB3_00) {
531
0
    xconn->smb2.server.sign_algo = SMB2_SIGNING_AES128_CMAC;
532
0
  } else {
533
0
    xconn->smb2.server.sign_algo = SMB2_SIGNING_HMAC_SHA256;
534
0
  }
535
536
0
  if ((capabilities & SMB2_CAP_ENCRYPTION) && (in_cipher != NULL)) {
537
0
    const struct smb3_encryption_capabilities *srv_ciphers =
538
0
      &default_smb3_capabilities.encryption;
539
0
    uint16_t srv_preferred_idx = UINT16_MAX;
540
0
    size_t needed = 2;
541
0
    uint16_t cipher_count;
542
0
    const uint8_t *p;
543
0
    uint8_t buf[4];
544
0
    size_t i;
545
546
0
    capabilities &= ~SMB2_CAP_ENCRYPTION;
547
548
0
    if (in_cipher->data.length < needed) {
549
0
      return smbd_smb2_request_error(req,
550
0
          NT_STATUS_INVALID_PARAMETER);
551
0
    }
552
553
0
    cipher_count = SVAL(in_cipher->data.data, 0);
554
0
    if (cipher_count == 0) {
555
0
      return smbd_smb2_request_error(req,
556
0
          NT_STATUS_INVALID_PARAMETER);
557
0
    }
558
559
0
    p = in_cipher->data.data + needed;
560
0
    needed += cipher_count * 2;
561
562
0
    if (in_cipher->data.length < needed) {
563
0
      return smbd_smb2_request_error(req,
564
0
          NT_STATUS_INVALID_PARAMETER);
565
0
    }
566
567
0
    for (i=0; i < cipher_count; i++) {
568
0
      uint16_t si;
569
0
      uint16_t v;
570
571
0
      v = SVAL(p, 0);
572
0
      p += 2;
573
574
0
      for (si = 0; si < srv_ciphers->num_algos; si++) {
575
0
        if (srv_ciphers->algos[si] != v) {
576
0
          continue;
577
0
        }
578
579
        /*
580
         * The server ciphers are listed
581
         * with the lowest idx being preferred.
582
         */
583
0
        if (si < srv_preferred_idx) {
584
0
          srv_preferred_idx = si;
585
0
        }
586
0
        break;
587
0
      }
588
0
    }
589
590
0
    if (srv_preferred_idx != UINT16_MAX) {
591
0
      xconn->smb2.server.cipher =
592
0
        srv_ciphers->algos[srv_preferred_idx];
593
0
    }
594
595
0
    SSVAL(buf, 0, 1); /* ChiperCount */
596
0
    SSVAL(buf, 2, xconn->smb2.server.cipher);
597
598
0
    status = smb2_negotiate_context_add(
599
0
      req,
600
0
      &out_c,
601
0
      SMB2_ENCRYPTION_CAPABILITIES,
602
0
      buf,
603
0
      sizeof(buf));
604
0
    if (!NT_STATUS_IS_OK(status)) {
605
0
      return smbd_smb2_request_error(req, status);
606
0
    }
607
0
  }
608
609
0
  if (capabilities & SMB2_CAP_ENCRYPTION) {
610
0
    xconn->smb2.server.cipher = SMB2_ENCRYPTION_AES128_CCM;
611
0
  }
612
613
0
  if (in_sign_algo != NULL) {
614
0
    const struct smb3_signing_capabilities *srv_sign_algos =
615
0
      &default_smb3_capabilities.signing;
616
0
    uint16_t srv_preferred_idx = UINT16_MAX;
617
0
    size_t needed = 2;
618
0
    uint16_t sign_algo_count;
619
0
    const uint8_t *p;
620
0
    size_t i;
621
622
0
    if (in_sign_algo->data.length < needed) {
623
0
      return smbd_smb2_request_error(req,
624
0
          NT_STATUS_INVALID_PARAMETER);
625
0
    }
626
627
0
    sign_algo_count = SVAL(in_sign_algo->data.data, 0);
628
0
    if (sign_algo_count == 0) {
629
0
      return smbd_smb2_request_error(req,
630
0
          NT_STATUS_INVALID_PARAMETER);
631
0
    }
632
633
0
    p = in_sign_algo->data.data + needed;
634
0
    needed += sign_algo_count * 2;
635
636
0
    if (in_sign_algo->data.length < needed) {
637
0
      return smbd_smb2_request_error(req,
638
0
          NT_STATUS_INVALID_PARAMETER);
639
0
    }
640
641
0
    for (i=0; i < sign_algo_count; i++) {
642
0
      uint16_t si;
643
0
      uint16_t v;
644
645
0
      v = SVAL(p, 0);
646
0
      p += 2;
647
648
0
      for (si = 0; si < srv_sign_algos->num_algos; si++) {
649
0
        if (srv_sign_algos->algos[si] != v) {
650
0
          continue;
651
0
        }
652
653
        /*
654
         * The server sign_algos are listed
655
         * with the lowest idx being preferred.
656
         */
657
0
        if (si < srv_preferred_idx) {
658
0
          srv_preferred_idx = si;
659
0
        }
660
0
        break;
661
0
      }
662
0
    }
663
664
    /*
665
     * If we found a match announce it
666
     * otherwise we'll keep the default
667
     * of SMB2_SIGNING_AES128_CMAC
668
     */
669
0
    if (srv_preferred_idx != UINT16_MAX) {
670
0
      uint8_t buf[4];
671
672
0
      xconn->smb2.server.sign_algo =
673
0
        srv_sign_algos->algos[srv_preferred_idx];
674
675
0
      SSVAL(buf, 0, 1); /* SigningAlgorithmCount */
676
0
      SSVAL(buf, 2, xconn->smb2.server.sign_algo);
677
678
0
      status = smb2_negotiate_context_add(
679
0
        req,
680
0
        &out_c,
681
0
        SMB2_SIGNING_CAPABILITIES,
682
0
        buf,
683
0
        sizeof(buf));
684
0
      if (!NT_STATUS_IS_OK(status)) {
685
0
        return smbd_smb2_request_error(req, status);
686
0
      }
687
0
    }
688
0
  }
689
690
0
  if (in_transport_caps != NULL) {
691
0
    uint32_t caps_flags;
692
693
0
    if (in_transport_caps->data.length != 4) {
694
0
      return smbd_smb2_request_error(
695
0
        req, NT_STATUS_INVALID_PARAMETER);
696
0
    }
697
698
0
    caps_flags = PULL_LE_U32(in_transport_caps->data.data, 0);
699
700
0
    if ((xconn->transport.type == SMB_TRANSPORT_TYPE_QUIC) &&
701
0
        (caps_flags & SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY) &&
702
0
        !lp_server_smb_encryption_over_quic())
703
0
    {
704
0
      uint8_t buf[4];
705
706
0
      PUSH_LE_U32(buf,
707
0
            0,
708
0
            SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY);
709
710
0
      status = smb2_negotiate_context_add(
711
0
        req,
712
0
        &out_c,
713
0
        SMB2_TRANSPORT_CAPABILITIES,
714
0
        buf,
715
0
        sizeof(buf));
716
0
      if (!NT_STATUS_IS_OK(status)) {
717
0
        return smbd_smb2_request_error(req, status);
718
0
      }
719
720
0
      xconn->transport.trusted_quic = true;
721
0
    }
722
0
  }
723
724
0
  status = smb311_capabilities_check(&default_smb3_capabilities,
725
0
             "smb2srv_negprot",
726
0
             DBGLVL_NOTICE,
727
0
             NT_STATUS_INVALID_PARAMETER,
728
0
             "server",
729
0
             protocol,
730
0
             xconn->smb2.server.sign_algo,
731
0
             xconn->smb2.server.cipher);
732
0
  if (!NT_STATUS_IS_OK(status)) {
733
0
    return smbd_smb2_request_error(req, status);
734
0
  }
735
736
0
  if (protocol >= PROTOCOL_SMB3_00 &&
737
0
      xconn->client->server_multi_channel_enabled)
738
0
  {
739
0
    if (in_capabilities & SMB2_CAP_MULTI_CHANNEL) {
740
0
      capabilities |= SMB2_CAP_MULTI_CHANNEL;
741
0
    }
742
0
  }
743
744
0
  security_offset = SMB2_HDR_BODY + 0x40;
745
746
0
  security_buffer = negprot_spnego_blob;
747
748
0
  if (posix) {
749
    /* Client correctly negotiated SMB2 unix extensions. */
750
0
    const uint8_t *buf = (const uint8_t *)SMB2_CREATE_TAG_POSIX;
751
0
    status = smb2_negotiate_context_add(
752
0
        req,
753
0
        &out_c,
754
0
        SMB2_POSIX_EXTENSIONS_AVAILABLE,
755
0
        buf,
756
0
        16);
757
0
    if (!NT_STATUS_IS_OK(status)) {
758
0
      return smbd_smb2_request_error(req, status);
759
0
    }
760
0
    xconn->smb2.server.posix_extensions_negotiated = true;
761
0
  }
762
763
0
  if (out_c.num_contexts != 0) {
764
0
    status = smb2_negotiate_context_push(req,
765
0
            &out_negotiate_context_blob,
766
0
            out_c);
767
0
    if (!NT_STATUS_IS_OK(status)) {
768
0
      return smbd_smb2_request_error(req, status);
769
0
    }
770
0
  }
771
772
0
  if (out_negotiate_context_blob.length != 0) {
773
0
    static const uint8_t zeros[8];
774
0
    size_t pad = 0;
775
0
    size_t ofs;
776
777
0
    outdyn = data_blob_dup_talloc(req, security_buffer);
778
0
    if (outdyn.length != security_buffer.length) {
779
0
      return smbd_smb2_request_error(req,
780
0
            NT_STATUS_NO_MEMORY);
781
0
    }
782
783
0
    ofs = security_offset + security_buffer.length;
784
0
    if ((ofs % 8) != 0) {
785
0
      pad = 8 - (ofs % 8);
786
0
    }
787
0
    ofs += pad;
788
789
0
    ok = data_blob_append(req, &outdyn, zeros, pad);
790
0
    if (!ok) {
791
0
      return smbd_smb2_request_error(req,
792
0
            NT_STATUS_NO_MEMORY);
793
0
    }
794
795
0
    ok = data_blob_append(req, &outdyn,
796
0
              out_negotiate_context_blob.data,
797
0
              out_negotiate_context_blob.length);
798
0
    if (!ok) {
799
0
      return smbd_smb2_request_error(req,
800
0
            NT_STATUS_NO_MEMORY);
801
0
    }
802
803
0
    out_negotiate_context_offset = ofs;
804
0
    out_negotiate_context_count = out_c.num_contexts;
805
0
  } else {
806
0
    outdyn = security_buffer;
807
0
  }
808
809
0
  smbd_server_guid(&out_guid);
810
0
  GUID_to_ndr_buf(&out_guid, &out_guid_buf);
811
812
0
  outbody = smbd_smb2_generate_outbody(req, 0x40);
813
0
  if (outbody.data == NULL) {
814
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
815
0
  }
816
817
0
  SSVAL(outbody.data, 0x00, 0x40 + 1); /* struct size */
818
0
  SSVAL(outbody.data, 0x02,
819
0
        security_mode);     /* security mode */
820
0
  SSVAL(outbody.data, 0x04, dialect);  /* dialect revision */
821
0
  SSVAL(outbody.data, 0x06,
822
0
        out_negotiate_context_count); /* reserved/NegotiateContextCount */
823
0
  memcpy(outbody.data + 0x08,
824
0
         out_guid_buf.buf,
825
0
         sizeof(out_guid_buf.buf)); /* server guid */
826
0
  SIVAL(outbody.data, 0x18,
827
0
        capabilities);      /* capabilities */
828
0
  SIVAL(outbody.data, 0x1C, max_trans);  /* max transact size */
829
0
  SIVAL(outbody.data, 0x20, max_read); /* max read size */
830
0
  SIVAL(outbody.data, 0x24, max_write);  /* max write size */
831
0
  SBVAL(outbody.data, 0x28, now);    /* system time */
832
0
  SBVAL(outbody.data, 0x30, 0);    /* server start time */
833
0
  SSVAL(outbody.data, 0x38,
834
0
        security_offset);     /* security buffer offset */
835
0
  SSVAL(outbody.data, 0x3A,
836
0
        security_buffer.length);    /* security buffer length */
837
0
  SIVAL(outbody.data, 0x3C,
838
0
        out_negotiate_context_offset);  /* reserved/NegotiateContextOffset */
839
840
0
  if (dialect == SMB2_DIALECT_REVISION_2FF) {
841
0
    return smbd_smb2_request_done(req, outbody, &outdyn);
842
0
  }
843
844
0
  status = smbXsrv_connection_init_tables(xconn, protocol);
845
0
  if (!NT_STATUS_IS_OK(status)) {
846
0
    return smbd_smb2_request_error(req, status);
847
0
  }
848
849
0
  xconn->smb2.client.capabilities = in_capabilities;
850
0
  xconn->smb2.client.security_mode = in_security_mode;
851
0
  xconn->smb2.client.guid = in_guid;
852
0
  xconn->smb2.client.num_dialects = dialect_count;
853
0
  xconn->smb2.client.dialects = talloc_array(xconn,
854
0
               uint16_t,
855
0
               dialect_count);
856
0
  if (xconn->smb2.client.dialects == NULL) {
857
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
858
0
  }
859
0
  for (c=0; c < dialect_count; c++) {
860
0
    xconn->smb2.client.dialects[c] = SVAL(indyn, c*2);
861
0
  }
862
863
0
  xconn->smb2.server.capabilities = capabilities;
864
0
  xconn->smb2.server.security_mode = security_mode;
865
0
  xconn->smb2.server.guid = out_guid;
866
0
  xconn->smb2.server.dialect = dialect;
867
0
  xconn->smb2.server.max_trans = max_trans;
868
0
  xconn->smb2.server.max_read  = max_read;
869
0
  xconn->smb2.server.max_write = max_write;
870
871
0
  if (xconn->protocol < PROTOCOL_SMB2_10) {
872
    /*
873
     * SMB2_02 doesn't support client guids
874
     */
875
0
    return smbd_smb2_request_done(req, outbody, &outdyn);
876
0
  }
877
878
0
  if (!xconn->client->server_multi_channel_enabled) {
879
    /*
880
     * Only deal with the client guid database
881
     * if multi-channel is enabled.
882
     *
883
     * But we still need to setup
884
     * xconn->client->global->client_guid to
885
     * the correct value.
886
     */
887
0
    xconn->client->global->client_guid =
888
0
      xconn->smb2.client.guid;
889
0
    return smbd_smb2_request_done(req, outbody, &outdyn);
890
0
  }
891
892
0
  if (xconn->smb2.client.guid_verified) {
893
    /*
894
     * The connection was passed from another
895
     * smbd process.
896
     */
897
0
    return smbd_smb2_request_done(req, outbody, &outdyn);
898
0
  }
899
900
0
  state = talloc_zero(req, struct smbd_smb2_request_process_negprot_state);
901
0
  if (state == NULL) {
902
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
903
0
  }
904
0
  *state = (struct smbd_smb2_request_process_negprot_state) {
905
0
    .req = req,
906
0
    .outbody = outbody,
907
0
    .outdyn = outdyn,
908
0
  };
909
910
0
  subreq = smb2srv_client_mc_negprot_send(state,
911
0
            req->xconn->client->raw_ev_ctx,
912
0
            req);
913
0
  if (subreq == NULL) {
914
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
915
0
  }
916
0
  tevent_req_set_callback(subreq,
917
0
        smbd_smb2_request_process_negprot_mc_done,
918
0
        state);
919
0
  return NT_STATUS_OK;
920
0
}
921
922
static void smbd_smb2_request_process_negprot_mc_done(struct tevent_req *subreq)
923
0
{
924
0
  struct smbd_smb2_request_process_negprot_state *state =
925
0
    tevent_req_callback_data(subreq,
926
0
    struct smbd_smb2_request_process_negprot_state);
927
0
  struct smbd_smb2_request *req = state->req;
928
0
  struct smbXsrv_connection *xconn = req->xconn;
929
0
  NTSTATUS status;
930
931
0
  status = smb2srv_client_mc_negprot_recv(subreq);
932
0
  TALLOC_FREE(subreq);
933
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_MESSAGE_RETRIEVED)) {
934
    /*
935
     * The connection was passed to another process
936
     *
937
     * We mark the error as NT_STATUS_CONNECTION_IN_USE,
938
     * in order to indicate to low level code if
939
     * ctdbd_unregister_ips() or ctdbd_passed_ips()
940
     * is more useful.
941
     */
942
0
    smbXsrv_connection_disconnect_transport(xconn,
943
0
            NT_STATUS_CONNECTION_IN_USE);
944
0
    smbd_server_connection_terminate(xconn,
945
0
             "passed connection");
946
0
    exit_server_cleanly("connection passed");
947
0
    return;
948
0
  }
949
0
  if (!NT_STATUS_IS_OK(status)) {
950
0
    status = smbd_smb2_request_error(req, status);
951
0
    if (NT_STATUS_IS_OK(status)) {
952
0
      return;
953
0
    }
954
955
    /*
956
     * The connection was passed to another process
957
     */
958
0
    smbd_server_connection_terminate(xconn, nt_errstr(status));
959
0
    exit_server_cleanly("connection passed");
960
0
    return;
961
0
  }
962
963
  /*
964
   * We're the first connection...
965
   */
966
0
  status = smbd_smb2_request_done(req, state->outbody, &state->outdyn);
967
0
  if (NT_STATUS_IS_OK(status)) {
968
    /*
969
     * This allows us to support starting smbd under
970
     * callgrind and only start the overhead and
971
     * instrumentation after the SMB2 negprot,
972
     * this allows us to profile only useful
973
     * stuff and not all the smbd startup, forking
974
     * and multichannel handling.
975
     *
976
     * valgrind --tool=callgrind --instr-atstart=no smbd
977
     */
978
#ifdef CALLGRIND_START_INSTRUMENTATION
979
    CALLGRIND_START_INSTRUMENTATION;
980
#endif
981
0
    return;
982
0
  }
983
984
  /*
985
   * The connection was passed to another process
986
   */
987
0
  smbd_server_connection_terminate(xconn, nt_errstr(status));
988
0
  exit_server_cleanly("connection passed");
989
0
  return;
990
0
}
991
992
/****************************************************************************
993
 Generate the spnego negprot reply blob. Return the number of bytes used.
994
****************************************************************************/
995
996
DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbXsrv_connection *xconn)
997
0
{
998
0
  DATA_BLOB blob = data_blob_null;
999
0
  NTSTATUS status;
1000
0
  struct gensec_security *gensec_security;
1001
1002
  /* See if we can get an SPNEGO blob */
1003
0
  status = auth_generic_prepare(talloc_tos(),
1004
0
              xconn->remote_address,
1005
0
              xconn->local_address,
1006
0
              "SMB",
1007
0
              &gensec_security);
1008
1009
  /*
1010
   * Despite including it above, there is no need to set a
1011
   * remote address or similar as we are just interested in the
1012
   * SPNEGO blob, we never keep this context.
1013
   */
1014
1015
0
  if (NT_STATUS_IS_OK(status)) {
1016
0
    status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
1017
0
    if (NT_STATUS_IS_OK(status)) {
1018
0
      status = gensec_update(gensec_security, ctx,
1019
0
                 data_blob_null, &blob);
1020
      /* If we get the list of OIDs, the 'OK' answer
1021
       * is NT_STATUS_MORE_PROCESSING_REQUIRED */
1022
0
      if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1023
0
        DEBUG(0, ("Failed to start SPNEGO handler for negprot OID list!\n"));
1024
0
        blob = data_blob_null;
1025
0
      }
1026
0
    }
1027
0
    TALLOC_FREE(gensec_security);
1028
0
  }
1029
1030
  /* strangely enough, NT does not sent the single OID NTLMSSP when
1031
     not a ADS member, it sends no OIDs at all
1032
1033
     OLD COMMENT : "we can't do this until we teach our session setup parser to know
1034
       about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
1035
1036
     Our sessionsetup code now handles raw NTLMSSP connects, so we can go
1037
     back to doing what W2K3 does here. This is needed to make PocketPC 2003
1038
     CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
1039
     for details. JRA.
1040
1041
  */
1042
1043
0
  if (blob.length == 0 || blob.data == NULL) {
1044
0
    return data_blob_null;
1045
0
  }
1046
1047
0
  return blob;
1048
0
}
1049
1050
void smbd_server_guid(struct GUID *server_guid)
1051
0
{
1052
0
  fstring unix_name = {};
1053
0
  nstring dos_name = {};
1054
0
  DATA_BLOB blob = {
1055
0
    .data = (uint8_t *)dos_name,
1056
0
    .length = sizeof(dos_name),
1057
0
  };
1058
0
  NTSTATUS status;
1059
1060
  /*
1061
   * Strange way to create a GUID, but this is what
1062
   * negprot_spnego() did.
1063
   */
1064
0
  fstrcpy(unix_name, lp_netbios_name());
1065
0
  (void)strlower_m(unix_name);
1066
0
  push_ascii_nstring(dos_name, unix_name);
1067
1068
  /*
1069
   * "nstring" is 16 bytes, i.e. exactly a GUID
1070
   */
1071
0
  status = GUID_from_ndr_blob(&blob, server_guid);
1072
0
  SMB_ASSERT(NT_STATUS_IS_OK(status));
1073
0
}
1074
1075
/*
1076
 * MS-CIFS, 2.2.4.52.2 SMB_COM_NEGOTIATE Response:
1077
 * If the server does not support any of the listed dialects, it MUST return a
1078
 * DialectIndex of 0XFFFF
1079
 */
1080
#define NO_PROTOCOL_CHOSEN  0xffff
1081
1082
#define PROT_SMB_2_002        0x1000
1083
#define PROT_SMB_2_FF       0x2000
1084
1085
/* List of supported SMB1 protocols, most desired first.
1086
 * This is for enabling multi-protocol negotiation in SMB2 when SMB1
1087
 * is disabled.
1088
 */
1089
static const struct {
1090
  const char *proto_name;
1091
  const char *short_name;
1092
  NTSTATUS (*proto_reply_fn)(struct smb_request *req, uint16_t choice);
1093
  int protocol_level;
1094
} supported_protocols[] = {
1095
  {"SMB 2.???",               "SMB2_FF",  reply_smb20ff,  PROTOCOL_SMB2_10},
1096
  {"SMB 2.002",               "SMB2_02",  reply_smb2002,  PROTOCOL_SMB2_02},
1097
  {NULL,NULL,NULL,0},
1098
};
1099
1100
/****************************************************************************
1101
 Reply to a negprot.
1102
 conn POINTER CAN BE NULL HERE !
1103
****************************************************************************/
1104
1105
NTSTATUS smb2_multi_protocol_reply_negprot(struct smb_request *req)
1106
0
{
1107
0
  size_t choice = 0;
1108
0
  bool choice_set = false;
1109
0
  int protocol;
1110
0
  const char *p;
1111
0
  size_t num_cliprotos;
1112
0
  char **cliprotos;
1113
0
  size_t i;
1114
0
  size_t converted_size;
1115
0
  struct smbXsrv_connection *xconn = req->xconn;
1116
0
  struct smbd_server_connection *sconn = req->sconn;
1117
0
  int max_proto;
1118
0
  int min_proto;
1119
0
  NTSTATUS status;
1120
1121
0
  START_PROFILE(SMBnegprot);
1122
1123
0
  if (req->buflen == 0) {
1124
0
    DEBUG(0, ("negprot got no protocols\n"));
1125
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1126
0
    END_PROFILE(SMBnegprot);
1127
0
    return NT_STATUS_INVALID_PARAMETER;
1128
0
  }
1129
1130
0
  if (req->buf[req->buflen-1] != '\0') {
1131
0
    DEBUG(0, ("negprot protocols not 0-terminated\n"));
1132
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1133
0
    END_PROFILE(SMBnegprot);
1134
0
    return NT_STATUS_INVALID_PARAMETER;
1135
0
  }
1136
1137
0
  p = (const char *)req->buf + 1;
1138
1139
0
  num_cliprotos = 0;
1140
0
  cliprotos = NULL;
1141
1142
0
  while (smbreq_bufrem(req, p) > 0) {
1143
1144
0
    char **tmp;
1145
1146
0
    tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
1147
0
             num_cliprotos+1);
1148
0
    if (tmp == NULL) {
1149
0
      DEBUG(0, ("talloc failed\n"));
1150
0
      TALLOC_FREE(cliprotos);
1151
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
1152
0
      END_PROFILE(SMBnegprot);
1153
0
      return NT_STATUS_NO_MEMORY;
1154
0
    }
1155
1156
0
    cliprotos = tmp;
1157
1158
0
    if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
1159
0
               &converted_size)) {
1160
0
      DEBUG(0, ("pull_ascii_talloc failed\n"));
1161
0
      TALLOC_FREE(cliprotos);
1162
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
1163
0
      END_PROFILE(SMBnegprot);
1164
0
      return NT_STATUS_NO_MEMORY;
1165
0
    }
1166
1167
0
    DEBUG(3, ("Requested protocol [%s]\n",
1168
0
        cliprotos[num_cliprotos]));
1169
1170
0
    num_cliprotos += 1;
1171
0
    p += strlen(p) + 2;
1172
0
  }
1173
1174
  /* possibly reload - change of architecture */
1175
0
  reload_services(sconn, conn_snum_used, true);
1176
1177
  /*
1178
   * Anything higher than PROTOCOL_SMB2_10 still
1179
   * needs to go via "SMB 2.???", which is marked
1180
   * as PROTOCOL_SMB2_10.
1181
   *
1182
   * The real negotiation happens via reply_smb20ff()
1183
   * using SMB2 Negotiation.
1184
   */
1185
0
  max_proto = lp_server_max_protocol();
1186
0
  if (max_proto > PROTOCOL_SMB2_10) {
1187
0
    max_proto = PROTOCOL_SMB2_10;
1188
0
  }
1189
0
  min_proto = lp_server_min_protocol();
1190
0
  if (min_proto > PROTOCOL_SMB2_10) {
1191
0
    min_proto = PROTOCOL_SMB2_10;
1192
0
  }
1193
1194
  /* Check for protocols, most desirable first */
1195
0
  for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
1196
0
    i = 0;
1197
0
    if ((supported_protocols[protocol].protocol_level <= max_proto) &&
1198
0
        (supported_protocols[protocol].protocol_level >= min_proto))
1199
0
      while (i < num_cliprotos) {
1200
0
        if (strequal(cliprotos[i],supported_protocols[protocol].proto_name)) {
1201
0
          choice = i;
1202
0
          choice_set = true;
1203
0
        }
1204
0
        i++;
1205
0
      }
1206
0
    if (choice_set) {
1207
0
      break;
1208
0
    }
1209
0
  }
1210
1211
0
  if (!choice_set) {
1212
0
    bool ok;
1213
1214
0
    DBG_NOTICE("No protocol supported !\n");
1215
0
    reply_smb1_outbuf(req, 1, 0);
1216
0
    SSVAL(req->outbuf, smb_vwv0, NO_PROTOCOL_CHOSEN);
1217
1218
0
    ok = smb1_srv_send(xconn, (char *)req->outbuf, false, 0, false);
1219
0
    if (!ok) {
1220
0
      DBG_NOTICE("smb1_srv_send failed\n");
1221
0
    }
1222
0
    exit_server_cleanly("no protocol supported\n");
1223
0
  }
1224
1225
0
  set_remote_proto(supported_protocols[protocol].short_name);
1226
0
  reload_services(sconn, conn_snum_used, true);
1227
0
  status = supported_protocols[protocol].proto_reply_fn(req, choice);
1228
0
  if (!NT_STATUS_IS_OK(status)) {
1229
0
    exit_server_cleanly("negprot function failed\n");
1230
0
  }
1231
1232
0
  DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
1233
1234
0
  DBG_INFO("negprot index=%zu\n", choice);
1235
1236
0
  TALLOC_FREE(cliprotos);
1237
1238
0
  END_PROFILE(SMBnegprot);
1239
0
  return NT_STATUS_OK;
1240
0
}