LCOV - code coverage report
Current view: top level - source3/smbd - smb2_negprot.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 407 506 80.4 %
Date: 2024-06-13 04:01:37 Functions: 7 8 87.5 %

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

Generated by: LCOV version 1.13