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

Generated by: LCOV version 1.14