Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/smbd/smb2_negprot.c
Line
Count
Source (jump to first uncovered line)
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_contexts out_c = { .num_contexts = 0, };
221
0
  const struct smb311_capabilities default_smb3_capabilities =
222
0
    smb311_capabilities_parse("server",
223
0
      lp_server_smb3_signing_algorithms(),
224
0
      lp_server_smb3_encryption_algorithms());
225
0
  DATA_BLOB out_negotiate_context_blob = data_blob_null;
226
0
  uint32_t out_negotiate_context_offset = 0;
227
0
  uint16_t out_negotiate_context_count = 0;
228
0
  uint16_t dialect = 0;
229
0
  uint32_t capabilities;
230
0
  DATA_BLOB out_guid_blob;
231
0
  struct GUID out_guid;
232
0
  enum protocol_types protocol = PROTOCOL_NONE;
233
0
  uint32_t max_limit;
234
0
  uint32_t max_trans = lp_smb2_max_trans();
235
0
  uint32_t max_read = lp_smb2_max_read();
236
0
  uint32_t max_write = lp_smb2_max_write();
237
0
  NTTIME now = timeval_to_nttime(&req->request_time);
238
0
  bool posix = false;
239
0
  bool ok;
240
241
0
  status = smbd_smb2_request_verify_sizes(req, 0x24);
242
0
  if (!NT_STATUS_IS_OK(status)) {
243
0
    return smbd_smb2_request_error(req, status);
244
0
  }
245
0
  inbody = SMBD_SMB2_IN_BODY_PTR(req);
246
247
0
  dialect_count = SVAL(inbody, 0x02);
248
249
0
  in_security_mode = SVAL(inbody, 0x04);
250
0
  in_capabilities = IVAL(inbody, 0x08);
251
0
  in_guid_blob = data_blob_const(inbody + 0x0C, 16);
252
253
0
  if (dialect_count == 0) {
254
0
    return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
255
0
  }
256
257
0
  status = GUID_from_ndr_blob(&in_guid_blob, &in_guid);
258
0
  if (!NT_STATUS_IS_OK(status)) {
259
0
    return smbd_smb2_request_error(req, status);
260
0
  }
261
262
0
  expected_dyn_size = dialect_count * 2;
263
0
  if (SMBD_SMB2_IN_DYN_LEN(req) < expected_dyn_size) {
264
0
    return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
265
0
  }
266
0
  indyn = SMBD_SMB2_IN_DYN_PTR(req);
267
268
0
  protocol = smbd_smb2_protocol_dialect_match(indyn,
269
0
          dialect_count,
270
0
          &dialect);
271
272
0
  for (c=0; protocol == PROTOCOL_NONE && c < dialect_count; c++) {
273
0
    if (lp_server_max_protocol() < PROTOCOL_SMB2_10) {
274
0
      break;
275
0
    }
276
277
0
    dialect = SVAL(indyn, c*2);
278
0
    if (dialect == SMB2_DIALECT_REVISION_2FF) {
279
0
      if (xconn->smb2.allow_2ff) {
280
0
        xconn->smb2.allow_2ff = false;
281
0
        protocol = PROTOCOL_SMB2_10;
282
0
        break;
283
0
      }
284
0
    }
285
0
  }
286
287
0
  if (protocol == PROTOCOL_NONE) {
288
0
    return smbd_smb2_request_error(req, NT_STATUS_NOT_SUPPORTED);
289
0
  }
290
291
0
  if (protocol >= PROTOCOL_SMB3_11) {
292
0
    uint32_t in_negotiate_context_offset = 0;
293
0
    uint16_t in_negotiate_context_count = 0;
294
0
    DATA_BLOB in_negotiate_context_blob = data_blob_null;
295
0
    size_t ofs;
296
297
0
    in_negotiate_context_offset = IVAL(inbody, 0x1C);
298
0
    in_negotiate_context_count = SVAL(inbody, 0x20);
299
300
0
    ofs = SMB2_HDR_BODY;
301
0
    ofs += SMBD_SMB2_IN_BODY_LEN(req);
302
0
    ofs += expected_dyn_size;
303
0
    if ((ofs % 8) != 0) {
304
0
      ofs += 8 - (ofs % 8);
305
0
    }
306
307
0
    if (in_negotiate_context_offset != ofs) {
308
0
      return smbd_smb2_request_error(req,
309
0
          NT_STATUS_INVALID_PARAMETER);
310
0
    }
311
312
0
    ofs -= SMB2_HDR_BODY;
313
0
    ofs -= SMBD_SMB2_IN_BODY_LEN(req);
314
315
0
    if (SMBD_SMB2_IN_DYN_LEN(req) < ofs) {
316
0
      return smbd_smb2_request_error(req,
317
0
          NT_STATUS_INVALID_PARAMETER);
318
0
    }
319
320
0
    in_negotiate_context_blob = data_blob_const(indyn,
321
0
            SMBD_SMB2_IN_DYN_LEN(req));
322
323
0
    in_negotiate_context_blob.data += ofs;
324
0
    in_negotiate_context_blob.length -= ofs;
325
326
0
    status = smb2_negotiate_context_parse(req,
327
0
                  in_negotiate_context_blob,
328
0
                  in_negotiate_context_count,
329
0
                  &in_c);
330
0
    if (!NT_STATUS_IS_OK(status)) {
331
0
      return smbd_smb2_request_error(req, status);
332
0
    }
333
334
0
    status = smb2_negotiate_context_process_posix(&in_c, &posix);
335
0
    if (!NT_STATUS_IS_OK(status)) {
336
0
      return smbd_smb2_request_error(req, status);
337
0
    }
338
0
  }
339
340
0
  if ((dialect != SMB2_DIALECT_REVISION_2FF) &&
341
0
      (protocol >= PROTOCOL_SMB2_10) &&
342
0
      !GUID_all_zero(&in_guid))
343
0
  {
344
0
    ok = remote_arch_cache_update(&in_guid);
345
0
    if (!ok) {
346
0
      return smbd_smb2_request_error(
347
0
        req, NT_STATUS_UNSUCCESSFUL);
348
0
    }
349
0
  }
350
351
0
  switch (get_remote_arch()) {
352
0
  case RA_VISTA:
353
0
  case RA_SAMBA:
354
0
  case RA_CIFSFS:
355
0
  case RA_OSX:
356
0
    break;
357
0
  default:
358
0
    set_remote_arch(RA_VISTA);
359
0
    break;
360
0
  }
361
362
0
  {
363
0
    fstring proto;
364
0
    fstr_sprintf(proto,
365
0
           "SMB%X_%02X",
366
0
           (dialect >> 8) & 0xFF, dialect & 0xFF);
367
0
    set_remote_proto(proto);
368
0
    DEBUG(3,("Selected protocol %s\n", proto));
369
0
  }
370
371
0
  reload_services(req->sconn, conn_snum_used, true);
372
373
0
  in_preauth = smb2_negotiate_context_find(&in_c,
374
0
          SMB2_PREAUTH_INTEGRITY_CAPABILITIES);
375
0
  if (protocol >= PROTOCOL_SMB3_11 && in_preauth == NULL) {
376
0
    return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
377
0
  }
378
0
  in_cipher = smb2_negotiate_context_find(&in_c,
379
0
          SMB2_ENCRYPTION_CAPABILITIES);
380
0
  in_sign_algo = smb2_negotiate_context_find(&in_c,
381
0
          SMB2_SIGNING_CAPABILITIES);
382
383
  /* negprot_spnego() returns the server guid in the first 16 bytes */
384
0
  negprot_spnego_blob = negprot_spnego(req, xconn);
385
0
  if (negprot_spnego_blob.data == NULL) {
386
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
387
0
  }
388
389
0
  if (negprot_spnego_blob.length < 16) {
390
0
    return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
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(-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
      in_capabilities & SMB2_CAP_DIRECTORY_LEASING &&
419
0
      lp_smb3_directory_leases())
420
0
  {
421
0
    capabilities |= SMB2_CAP_DIRECTORY_LEASING;
422
0
  }
423
424
  /*
425
   * 0x10000 (65536) is the maximum allowed message size
426
   * for SMB 2.0
427
   */
428
0
  max_limit = 0x10000;
429
430
0
  if (protocol >= PROTOCOL_SMB2_10) {
431
0
    int p = 0;
432
433
0
    if (tsocket_address_is_inet(req->sconn->local_address, "ip")) {
434
0
      p = tsocket_address_inet_port(req->sconn->local_address);
435
0
    }
436
437
    /* largeMTU is not supported over NBT (tcp port 139) */
438
0
    if (p != NBT_SMB_PORT) {
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
  status = smb311_capabilities_check(&default_smb3_capabilities,
691
0
             "smb2srv_negprot",
692
0
             DBGLVL_NOTICE,
693
0
             NT_STATUS_INVALID_PARAMETER,
694
0
             "server",
695
0
             protocol,
696
0
             xconn->smb2.server.sign_algo,
697
0
             xconn->smb2.server.cipher);
698
0
  if (!NT_STATUS_IS_OK(status)) {
699
0
    return smbd_smb2_request_error(req, status);
700
0
  }
701
702
0
  if (protocol >= PROTOCOL_SMB3_00 &&
703
0
      xconn->client->server_multi_channel_enabled)
704
0
  {
705
0
    if (in_capabilities & SMB2_CAP_MULTI_CHANNEL) {
706
0
      capabilities |= SMB2_CAP_MULTI_CHANNEL;
707
0
    }
708
0
  }
709
710
0
  security_offset = SMB2_HDR_BODY + 0x40;
711
712
0
#if 1
713
  /* Try SPNEGO auth... */
714
0
  security_buffer = data_blob_const(negprot_spnego_blob.data + 16,
715
0
            negprot_spnego_blob.length - 16);
716
#else
717
  /* for now we want raw NTLMSSP */
718
  security_buffer = data_blob_const(NULL, 0);
719
#endif
720
721
0
  if (posix) {
722
    /* Client correctly negotiated SMB2 unix extensions. */
723
0
    const uint8_t *buf = (const uint8_t *)SMB2_CREATE_TAG_POSIX;
724
0
    status = smb2_negotiate_context_add(
725
0
        req,
726
0
        &out_c,
727
0
        SMB2_POSIX_EXTENSIONS_AVAILABLE,
728
0
        buf,
729
0
        16);
730
0
    if (!NT_STATUS_IS_OK(status)) {
731
0
      return smbd_smb2_request_error(req, status);
732
0
    }
733
0
    xconn->smb2.server.posix_extensions_negotiated = true;
734
0
  }
735
736
0
  if (out_c.num_contexts != 0) {
737
0
    status = smb2_negotiate_context_push(req,
738
0
            &out_negotiate_context_blob,
739
0
            out_c);
740
0
    if (!NT_STATUS_IS_OK(status)) {
741
0
      return smbd_smb2_request_error(req, status);
742
0
    }
743
0
  }
744
745
0
  if (out_negotiate_context_blob.length != 0) {
746
0
    static const uint8_t zeros[8];
747
0
    size_t pad = 0;
748
0
    size_t ofs;
749
750
0
    outdyn = data_blob_dup_talloc(req, security_buffer);
751
0
    if (outdyn.length != security_buffer.length) {
752
0
      return smbd_smb2_request_error(req,
753
0
            NT_STATUS_NO_MEMORY);
754
0
    }
755
756
0
    ofs = security_offset + security_buffer.length;
757
0
    if ((ofs % 8) != 0) {
758
0
      pad = 8 - (ofs % 8);
759
0
    }
760
0
    ofs += pad;
761
762
0
    ok = data_blob_append(req, &outdyn, zeros, pad);
763
0
    if (!ok) {
764
0
      return smbd_smb2_request_error(req,
765
0
            NT_STATUS_NO_MEMORY);
766
0
    }
767
768
0
    ok = data_blob_append(req, &outdyn,
769
0
              out_negotiate_context_blob.data,
770
0
              out_negotiate_context_blob.length);
771
0
    if (!ok) {
772
0
      return smbd_smb2_request_error(req,
773
0
            NT_STATUS_NO_MEMORY);
774
0
    }
775
776
0
    out_negotiate_context_offset = ofs;
777
0
    out_negotiate_context_count = out_c.num_contexts;
778
0
  } else {
779
0
    outdyn = security_buffer;
780
0
  }
781
782
0
  out_guid_blob = data_blob_const(negprot_spnego_blob.data, 16);
783
0
  status = GUID_from_ndr_blob(&out_guid_blob, &out_guid);
784
0
  if (!NT_STATUS_IS_OK(status)) {
785
0
    return smbd_smb2_request_error(req, status);
786
0
  }
787
788
0
  outbody = smbd_smb2_generate_outbody(req, 0x40);
789
0
  if (outbody.data == NULL) {
790
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
791
0
  }
792
793
0
  SSVAL(outbody.data, 0x00, 0x40 + 1); /* struct size */
794
0
  SSVAL(outbody.data, 0x02,
795
0
        security_mode);     /* security mode */
796
0
  SSVAL(outbody.data, 0x04, dialect);  /* dialect revision */
797
0
  SSVAL(outbody.data, 0x06,
798
0
        out_negotiate_context_count); /* reserved/NegotiateContextCount */
799
0
  memcpy(outbody.data + 0x08,
800
0
         out_guid_blob.data, 16); /* server guid */
801
0
  SIVAL(outbody.data, 0x18,
802
0
        capabilities);      /* capabilities */
803
0
  SIVAL(outbody.data, 0x1C, max_trans);  /* max transact size */
804
0
  SIVAL(outbody.data, 0x20, max_read); /* max read size */
805
0
  SIVAL(outbody.data, 0x24, max_write);  /* max write size */
806
0
  SBVAL(outbody.data, 0x28, now);    /* system time */
807
0
  SBVAL(outbody.data, 0x30, 0);    /* server start time */
808
0
  SSVAL(outbody.data, 0x38,
809
0
        security_offset);     /* security buffer offset */
810
0
  SSVAL(outbody.data, 0x3A,
811
0
        security_buffer.length);    /* security buffer length */
812
0
  SIVAL(outbody.data, 0x3C,
813
0
        out_negotiate_context_offset);  /* reserved/NegotiateContextOffset */
814
815
0
  if (dialect == SMB2_DIALECT_REVISION_2FF) {
816
0
    return smbd_smb2_request_done(req, outbody, &outdyn);
817
0
  }
818
819
0
  status = smbXsrv_connection_init_tables(xconn, protocol);
820
0
  if (!NT_STATUS_IS_OK(status)) {
821
0
    return smbd_smb2_request_error(req, status);
822
0
  }
823
824
0
  xconn->smb2.client.capabilities = in_capabilities;
825
0
  xconn->smb2.client.security_mode = in_security_mode;
826
0
  xconn->smb2.client.guid = in_guid;
827
0
  xconn->smb2.client.num_dialects = dialect_count;
828
0
  xconn->smb2.client.dialects = talloc_array(xconn,
829
0
               uint16_t,
830
0
               dialect_count);
831
0
  if (xconn->smb2.client.dialects == NULL) {
832
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
833
0
  }
834
0
  for (c=0; c < dialect_count; c++) {
835
0
    xconn->smb2.client.dialects[c] = SVAL(indyn, c*2);
836
0
  }
837
838
0
  xconn->smb2.server.capabilities = capabilities;
839
0
  xconn->smb2.server.security_mode = security_mode;
840
0
  xconn->smb2.server.guid = out_guid;
841
0
  xconn->smb2.server.dialect = dialect;
842
0
  xconn->smb2.server.max_trans = max_trans;
843
0
  xconn->smb2.server.max_read  = max_read;
844
0
  xconn->smb2.server.max_write = max_write;
845
846
0
  if (xconn->protocol < PROTOCOL_SMB2_10) {
847
    /*
848
     * SMB2_02 doesn't support client guids
849
     */
850
0
    return smbd_smb2_request_done(req, outbody, &outdyn);
851
0
  }
852
853
0
  if (!xconn->client->server_multi_channel_enabled) {
854
    /*
855
     * Only deal with the client guid database
856
     * if multi-channel is enabled.
857
     *
858
     * But we still need to setup
859
     * xconn->client->global->client_guid to
860
     * the correct value.
861
     */
862
0
    xconn->client->global->client_guid =
863
0
      xconn->smb2.client.guid;
864
0
    return smbd_smb2_request_done(req, outbody, &outdyn);
865
0
  }
866
867
0
  if (xconn->smb2.client.guid_verified) {
868
    /*
869
     * The connection was passed from another
870
     * smbd process.
871
     */
872
0
    return smbd_smb2_request_done(req, outbody, &outdyn);
873
0
  }
874
875
0
  state = talloc_zero(req, struct smbd_smb2_request_process_negprot_state);
876
0
  if (state == NULL) {
877
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
878
0
  }
879
0
  *state = (struct smbd_smb2_request_process_negprot_state) {
880
0
    .req = req,
881
0
    .outbody = outbody,
882
0
    .outdyn = outdyn,
883
0
  };
884
885
0
  subreq = smb2srv_client_mc_negprot_send(state,
886
0
            req->xconn->client->raw_ev_ctx,
887
0
            req);
888
0
  if (subreq == NULL) {
889
0
    return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
890
0
  }
891
0
  tevent_req_set_callback(subreq,
892
0
        smbd_smb2_request_process_negprot_mc_done,
893
0
        state);
894
0
  return NT_STATUS_OK;
895
0
}
896
897
static void smbd_smb2_request_process_negprot_mc_done(struct tevent_req *subreq)
898
0
{
899
0
  struct smbd_smb2_request_process_negprot_state *state =
900
0
    tevent_req_callback_data(subreq,
901
0
    struct smbd_smb2_request_process_negprot_state);
902
0
  struct smbd_smb2_request *req = state->req;
903
0
  struct smbXsrv_connection *xconn = req->xconn;
904
0
  NTSTATUS status;
905
906
0
  status = smb2srv_client_mc_negprot_recv(subreq);
907
0
  TALLOC_FREE(subreq);
908
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_MESSAGE_RETRIEVED)) {
909
    /*
910
     * The connection was passed to another process
911
     *
912
     * We mark the error as NT_STATUS_CONNECTION_IN_USE,
913
     * in order to indicate to low level code if
914
     * ctdbd_unregister_ips() or ctdbd_passed_ips()
915
     * is more useful.
916
     */
917
0
    smbXsrv_connection_disconnect_transport(xconn,
918
0
            NT_STATUS_CONNECTION_IN_USE);
919
0
    smbd_server_connection_terminate(xconn,
920
0
             "passed connection");
921
0
    exit_server_cleanly("connection passed");
922
0
    return;
923
0
  }
924
0
  if (!NT_STATUS_IS_OK(status)) {
925
0
    status = smbd_smb2_request_error(req, status);
926
0
    if (NT_STATUS_IS_OK(status)) {
927
0
      return;
928
0
    }
929
930
    /*
931
     * The connection was passed to another process
932
     */
933
0
    smbd_server_connection_terminate(xconn, nt_errstr(status));
934
0
    exit_server_cleanly("connection passed");
935
0
    return;
936
0
  }
937
938
  /*
939
   * We're the first connection...
940
   */
941
0
  status = smbd_smb2_request_done(req, state->outbody, &state->outdyn);
942
0
  if (NT_STATUS_IS_OK(status)) {
943
    /*
944
     * This allows us to support starting smbd under
945
     * callgrind and only start the overhead and
946
     * instrumentation after the SMB2 negprot,
947
     * this allows us to profile only useful
948
     * stuff and not all the smbd startup, forking
949
     * and multichannel handling.
950
     *
951
     * valgrind --tool=callgrind --instr-atstart=no smbd
952
     */
953
#ifdef CALLGRIND_START_INSTRUMENTATION
954
    CALLGRIND_START_INSTRUMENTATION;
955
#endif
956
0
    return;
957
0
  }
958
959
  /*
960
   * The connection was passed to another process
961
   */
962
0
  smbd_server_connection_terminate(xconn, nt_errstr(status));
963
0
  exit_server_cleanly("connection passed");
964
0
  return;
965
0
}
966
967
/****************************************************************************
968
 Generate the spnego negprot reply blob. Return the number of bytes used.
969
****************************************************************************/
970
971
DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbXsrv_connection *xconn)
972
0
{
973
0
  DATA_BLOB blob = data_blob_null;
974
0
  DATA_BLOB blob_out = data_blob_null;
975
0
  nstring dos_name;
976
0
  fstring unix_name;
977
0
  NTSTATUS status;
978
0
#ifdef DEVELOPER
979
0
  size_t slen;
980
0
#endif
981
0
  struct gensec_security *gensec_security;
982
983
  /* See if we can get an SPNEGO blob */
984
0
  status = auth_generic_prepare(talloc_tos(),
985
0
              xconn->remote_address,
986
0
              xconn->local_address,
987
0
              "SMB",
988
0
              &gensec_security);
989
990
  /*
991
   * Despite including it above, there is no need to set a
992
   * remote address or similar as we are just interested in the
993
   * SPNEGO blob, we never keep this context.
994
   */
995
996
0
  if (NT_STATUS_IS_OK(status)) {
997
0
    status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
998
0
    if (NT_STATUS_IS_OK(status)) {
999
0
      status = gensec_update(gensec_security, ctx,
1000
0
                 data_blob_null, &blob);
1001
      /* If we get the list of OIDs, the 'OK' answer
1002
       * is NT_STATUS_MORE_PROCESSING_REQUIRED */
1003
0
      if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1004
0
        DEBUG(0, ("Failed to start SPNEGO handler for negprot OID list!\n"));
1005
0
        blob = data_blob_null;
1006
0
      }
1007
0
    }
1008
0
    TALLOC_FREE(gensec_security);
1009
0
  }
1010
1011
0
#if defined(WITH_SMB1SERVER)
1012
0
  xconn->smb1.negprot.spnego = true;
1013
0
#endif
1014
1015
  /* strangely enough, NT does not sent the single OID NTLMSSP when
1016
     not a ADS member, it sends no OIDs at all
1017
1018
     OLD COMMENT : "we can't do this until we teach our session setup parser to know
1019
       about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
1020
1021
     Our sessionsetup code now handles raw NTLMSSP connects, so we can go
1022
     back to doing what W2K3 does here. This is needed to make PocketPC 2003
1023
     CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
1024
     for details. JRA.
1025
1026
  */
1027
1028
0
  if (blob.length == 0 || blob.data == NULL) {
1029
0
    return data_blob_null;
1030
0
  }
1031
1032
0
  blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
1033
0
  if (blob_out.data == NULL) {
1034
0
    data_blob_free(&blob);
1035
0
    return data_blob_null;
1036
0
  }
1037
1038
0
  memset(blob_out.data, '\0', 16);
1039
1040
0
  checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name));
1041
0
  (void)strlower_m(unix_name);
1042
0
  push_ascii_nstring(dos_name, unix_name);
1043
0
  strlcpy((char *)blob_out.data, dos_name, 17);
1044
1045
0
#ifdef DEVELOPER
1046
  /* Fix valgrind 'uninitialized bytes' issue. */
1047
0
  slen = strlen(dos_name);
1048
0
  if (slen < 16) {
1049
0
    memset(blob_out.data+slen, '\0', 16 - slen);
1050
0
  }
1051
0
#endif
1052
1053
0
  memcpy(&blob_out.data[16], blob.data, blob.length);
1054
1055
0
  data_blob_free(&blob);
1056
1057
0
  return blob_out;
1058
0
}
1059
1060
/*
1061
 * MS-CIFS, 2.2.4.52.2 SMB_COM_NEGOTIATE Response:
1062
 * If the server does not support any of the listed dialects, it MUST return a
1063
 * DialectIndex of 0XFFFF
1064
 */
1065
#define NO_PROTOCOL_CHOSEN  0xffff
1066
1067
#define PROT_SMB_2_002        0x1000
1068
#define PROT_SMB_2_FF       0x2000
1069
1070
/* List of supported SMB1 protocols, most desired first.
1071
 * This is for enabling multi-protocol negotiation in SMB2 when SMB1
1072
 * is disabled.
1073
 */
1074
static const struct {
1075
  const char *proto_name;
1076
  const char *short_name;
1077
  NTSTATUS (*proto_reply_fn)(struct smb_request *req, uint16_t choice);
1078
  int protocol_level;
1079
} supported_protocols[] = {
1080
  {"SMB 2.???",               "SMB2_FF",  reply_smb20ff,  PROTOCOL_SMB2_10},
1081
  {"SMB 2.002",               "SMB2_02",  reply_smb2002,  PROTOCOL_SMB2_02},
1082
  {NULL,NULL,NULL,0},
1083
};
1084
1085
/****************************************************************************
1086
 Reply to a negprot.
1087
 conn POINTER CAN BE NULL HERE !
1088
****************************************************************************/
1089
1090
NTSTATUS smb2_multi_protocol_reply_negprot(struct smb_request *req)
1091
0
{
1092
0
  size_t choice = 0;
1093
0
  bool choice_set = false;
1094
0
  int protocol;
1095
0
  const char *p;
1096
0
  int num_cliprotos;
1097
0
  char **cliprotos;
1098
0
  size_t i;
1099
0
  size_t converted_size;
1100
0
  struct smbXsrv_connection *xconn = req->xconn;
1101
0
  struct smbd_server_connection *sconn = req->sconn;
1102
0
  int max_proto;
1103
0
  int min_proto;
1104
0
  NTSTATUS status;
1105
1106
0
  START_PROFILE(SMBnegprot);
1107
1108
0
  if (req->buflen == 0) {
1109
0
    DEBUG(0, ("negprot got no protocols\n"));
1110
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1111
0
    END_PROFILE(SMBnegprot);
1112
0
    return NT_STATUS_INVALID_PARAMETER;
1113
0
  }
1114
1115
0
  if (req->buf[req->buflen-1] != '\0') {
1116
0
    DEBUG(0, ("negprot protocols not 0-terminated\n"));
1117
0
    reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1118
0
    END_PROFILE(SMBnegprot);
1119
0
    return NT_STATUS_INVALID_PARAMETER;
1120
0
  }
1121
1122
0
  p = (const char *)req->buf + 1;
1123
1124
0
  num_cliprotos = 0;
1125
0
  cliprotos = NULL;
1126
1127
0
  while (smbreq_bufrem(req, p) > 0) {
1128
1129
0
    char **tmp;
1130
1131
0
    tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
1132
0
             num_cliprotos+1);
1133
0
    if (tmp == NULL) {
1134
0
      DEBUG(0, ("talloc failed\n"));
1135
0
      TALLOC_FREE(cliprotos);
1136
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
1137
0
      END_PROFILE(SMBnegprot);
1138
0
      return NT_STATUS_NO_MEMORY;
1139
0
    }
1140
1141
0
    cliprotos = tmp;
1142
1143
0
    if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
1144
0
               &converted_size)) {
1145
0
      DEBUG(0, ("pull_ascii_talloc failed\n"));
1146
0
      TALLOC_FREE(cliprotos);
1147
0
      reply_nterror(req, NT_STATUS_NO_MEMORY);
1148
0
      END_PROFILE(SMBnegprot);
1149
0
      return NT_STATUS_NO_MEMORY;
1150
0
    }
1151
1152
0
    DEBUG(3, ("Requested protocol [%s]\n",
1153
0
        cliprotos[num_cliprotos]));
1154
1155
0
    num_cliprotos += 1;
1156
0
    p += strlen(p) + 2;
1157
0
  }
1158
1159
  /* possibly reload - change of architecture */
1160
0
  reload_services(sconn, conn_snum_used, true);
1161
1162
  /*
1163
   * Anything higher than PROTOCOL_SMB2_10 still
1164
   * needs to go via "SMB 2.???", which is marked
1165
   * as PROTOCOL_SMB2_10.
1166
   *
1167
   * The real negotiation happens via reply_smb20ff()
1168
   * using SMB2 Negotiation.
1169
   */
1170
0
  max_proto = lp_server_max_protocol();
1171
0
  if (max_proto > PROTOCOL_SMB2_10) {
1172
0
    max_proto = PROTOCOL_SMB2_10;
1173
0
  }
1174
0
  min_proto = lp_server_min_protocol();
1175
0
  if (min_proto > PROTOCOL_SMB2_10) {
1176
0
    min_proto = PROTOCOL_SMB2_10;
1177
0
  }
1178
1179
  /* Check for protocols, most desirable first */
1180
0
  for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
1181
0
    i = 0;
1182
0
    if ((supported_protocols[protocol].protocol_level <= max_proto) &&
1183
0
        (supported_protocols[protocol].protocol_level >= min_proto))
1184
0
      while (i < num_cliprotos) {
1185
0
        if (strequal(cliprotos[i],supported_protocols[protocol].proto_name)) {
1186
0
          choice = i;
1187
0
          choice_set = true;
1188
0
        }
1189
0
        i++;
1190
0
      }
1191
0
    if (choice_set) {
1192
0
      break;
1193
0
    }
1194
0
  }
1195
1196
0
  if (!choice_set) {
1197
0
    bool ok;
1198
1199
0
    DBG_NOTICE("No protocol supported !\n");
1200
0
    reply_smb1_outbuf(req, 1, 0);
1201
0
    SSVAL(req->outbuf, smb_vwv0, NO_PROTOCOL_CHOSEN);
1202
1203
0
    ok = smb1_srv_send(xconn, (char *)req->outbuf, false, 0, false);
1204
0
    if (!ok) {
1205
0
      DBG_NOTICE("smb1_srv_send failed\n");
1206
0
    }
1207
0
    exit_server_cleanly("no protocol supported\n");
1208
0
  }
1209
1210
0
  set_remote_proto(supported_protocols[protocol].short_name);
1211
0
  reload_services(sconn, conn_snum_used, true);
1212
0
  status = supported_protocols[protocol].proto_reply_fn(req, choice);
1213
0
  if (!NT_STATUS_IS_OK(status)) {
1214
0
    exit_server_cleanly("negprot function failed\n");
1215
0
  }
1216
1217
0
  DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
1218
1219
0
  DBG_INFO("negprot index=%zu\n", choice);
1220
1221
0
  TALLOC_FREE(cliprotos);
1222
1223
0
  END_PROFILE(SMBnegprot);
1224
0
  return NT_STATUS_OK;
1225
0
}