LCOV - code coverage report
Current view: top level - source3/smbd - smb1_negprot.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 159 317 50.2 %
Date: 2024-06-13 04:01:37 Functions: 2 5 40.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    negprot reply code
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Volker Lendecke 2007
       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 "serverid.h"
      25             : #include "auth.h"
      26             : #include "messages.h"
      27             : #include "smbprofile.h"
      28             : #include "auth/gensec/gensec.h"
      29             : #include "../libcli/smb/smb_signing.h"
      30             : #include "lib/util/string_wrappers.h"
      31             : 
      32             : /*
      33             :  * MS-CIFS, 2.2.4.52.2 SMB_COM_NEGOTIATE Response:
      34             :  * If the server does not support any of the listed dialects, it MUST return a
      35             :  * DialectIndex of 0XFFFF
      36             :  */
      37             : #define NO_PROTOCOL_CHOSEN      0xffff
      38             : 
      39             : extern fstring remote_proto;
      40             : 
      41           0 : static void get_challenge(struct smbXsrv_connection *xconn, uint8_t buff[8])
      42             : {
      43             :         NTSTATUS nt_status;
      44             : 
      45             :         /* We might be called more than once, multiple negprots are
      46             :          * permitted */
      47           0 :         if (xconn->smb1.negprot.auth_context) {
      48           0 :                 DEBUG(3, ("get challenge: is this a secondary negprot? "
      49             :                           "sconn->negprot.auth_context is non-NULL!\n"));
      50           0 :                 TALLOC_FREE(xconn->smb1.negprot.auth_context);
      51             :         }
      52             : 
      53           0 :         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
      54           0 :         nt_status = make_auth4_context(
      55             :                 xconn, &xconn->smb1.negprot.auth_context);
      56           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
      57           0 :                 DEBUG(0, ("make_auth_context_subsystem returned %s",
      58             :                           nt_errstr(nt_status)));
      59           0 :                 smb_panic("cannot make_negprot_global_auth_context!");
      60             :         }
      61           0 :         DEBUG(10, ("get challenge: getting challenge\n"));
      62           0 :         xconn->smb1.negprot.auth_context->get_ntlm_challenge(
      63             :                 xconn->smb1.negprot.auth_context, buff);
      64           0 : }
      65             : 
      66             : /****************************************************************************
      67             :  Reply for the lanman 1.0 protocol.
      68             : ****************************************************************************/
      69             : 
      70           0 : static NTSTATUS reply_lanman1(struct smb_request *req, uint16_t choice)
      71             : {
      72           0 :         int secword=0;
      73           0 :         time_t t = time(NULL);
      74           0 :         struct smbXsrv_connection *xconn = req->xconn;
      75             :         uint16_t raw;
      76             :         NTSTATUS status;
      77             : 
      78           0 :         if (lp_async_smb_echo_handler()) {
      79           0 :                 raw = 0;
      80             :         } else {
      81           0 :                 raw = (lp_read_raw()?1:0) | (lp_write_raw()?2:0);
      82             :         }
      83             : 
      84           0 :         xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
      85             : 
      86           0 :         secword |= NEGOTIATE_SECURITY_USER_LEVEL;
      87           0 :         if (xconn->smb1.negprot.encrypted_passwords) {
      88           0 :                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
      89             :         }
      90             : 
      91           0 :         reply_smb1_outbuf(req, 13, xconn->smb1.negprot.encrypted_passwords?8:0);
      92             : 
      93           0 :         SSVAL(req->outbuf,smb_vwv0,choice);
      94           0 :         SSVAL(req->outbuf,smb_vwv1,secword);
      95             :         /* Create a token value and add it to the outgoing packet. */
      96           0 :         if (xconn->smb1.negprot.encrypted_passwords) {
      97           0 :                 get_challenge(xconn, (uint8_t *)smb_buf(req->outbuf));
      98           0 :                 SSVAL(req->outbuf,smb_vwv11, 8);
      99             :         }
     100             : 
     101           0 :         status = smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN1);
     102           0 :         if (!NT_STATUS_IS_OK(status)) {
     103           0 :                 reply_nterror(req, status);
     104           0 :                 return status;
     105             :         }
     106             : 
     107             :         /* Reply, SMBlockread, SMBwritelock supported. */
     108           0 :         SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
     109           0 :         SSVAL(req->outbuf,smb_vwv2, xconn->smb1.negprot.max_recv);
     110           0 :         SSVAL(req->outbuf,smb_vwv3, lp_max_mux()); /* maxmux */
     111           0 :         SSVAL(req->outbuf,smb_vwv4, 1);
     112           0 :         SSVAL(req->outbuf,smb_vwv5, raw); /* tell redirector we support
     113             :                 readbraw writebraw (possibly) */
     114           0 :         SIVAL(req->outbuf,smb_vwv6, getpid());
     115           0 :         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
     116             : 
     117           0 :         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
     118             : 
     119           0 :         return NT_STATUS_OK;
     120             : }
     121             : 
     122             : /****************************************************************************
     123             :  Reply for the lanman 2.0 protocol.
     124             : ****************************************************************************/
     125             : 
     126           0 : static NTSTATUS reply_lanman2(struct smb_request *req, uint16_t choice)
     127             : {
     128           0 :         int secword=0;
     129           0 :         time_t t = time(NULL);
     130           0 :         struct smbXsrv_connection *xconn = req->xconn;
     131             :         uint16_t raw;
     132             :         NTSTATUS status;
     133             : 
     134           0 :         if (lp_async_smb_echo_handler()) {
     135           0 :                 raw = 0;
     136             :         } else {
     137           0 :                 raw = (lp_read_raw()?1:0) | (lp_write_raw()?2:0);
     138             :         }
     139             : 
     140           0 :         xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
     141             : 
     142           0 :         secword |= NEGOTIATE_SECURITY_USER_LEVEL;
     143           0 :         if (xconn->smb1.negprot.encrypted_passwords) {
     144           0 :                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
     145             :         }
     146             : 
     147           0 :         reply_smb1_outbuf(req, 13, xconn->smb1.negprot.encrypted_passwords?8:0);
     148             : 
     149           0 :         SSVAL(req->outbuf,smb_vwv0, choice);
     150           0 :         SSVAL(req->outbuf,smb_vwv1, secword);
     151           0 :         SIVAL(req->outbuf,smb_vwv6, getpid());
     152             : 
     153             :         /* Create a token value and add it to the outgoing packet. */
     154           0 :         if (xconn->smb1.negprot.encrypted_passwords) {
     155           0 :                 get_challenge(xconn, (uint8_t *)smb_buf(req->outbuf));
     156           0 :                 SSVAL(req->outbuf,smb_vwv11, 8);
     157             :         }
     158             : 
     159           0 :         status = smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN2);
     160           0 :         if (!NT_STATUS_IS_OK(status)) {
     161           0 :                 reply_nterror(req, status);
     162           0 :                 return status;
     163             :         }
     164             : 
     165             :         /* Reply, SMBlockread, SMBwritelock supported. */
     166           0 :         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
     167           0 :         SSVAL(req->outbuf,smb_vwv2,xconn->smb1.negprot.max_recv);
     168           0 :         SSVAL(req->outbuf,smb_vwv3,lp_max_mux());
     169           0 :         SSVAL(req->outbuf,smb_vwv4,1);
     170           0 :         SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
     171           0 :         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
     172           0 :         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
     173           0 :         return NT_STATUS_OK;
     174             : }
     175             : 
     176             : /****************************************************************************
     177             :  Reply for the nt protocol.
     178             : ****************************************************************************/
     179             : 
     180          38 : static NTSTATUS reply_nt1(struct smb_request *req, uint16_t choice)
     181             : {
     182             :         /* dual names + lock_and_read + nt SMBs + remote API calls */
     183          38 :         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
     184             :                 CAP_LEVEL_II_OPLOCKS;
     185             : 
     186          38 :         int secword=0;
     187          38 :         bool negotiate_spnego = False;
     188             :         struct timespec ts;
     189             :         ssize_t ret;
     190          38 :         struct smbXsrv_connection *xconn = req->xconn;
     191          38 :         bool signing_desired = false;
     192          38 :         bool signing_required = false;
     193             :         NTSTATUS status;
     194             : 
     195          38 :         xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
     196             : 
     197             :         /* Check the flags field to see if this is Vista.
     198             :            WinXP sets it and Vista does not. But we have to 
     199             :            distinguish from NT which doesn't set it either. */
     200             : 
     201          66 :         if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
     202          38 :                 ((req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) == 0) )
     203             :         {
     204          56 :                 if ((get_remote_arch() != RA_SAMBA) &&
     205          18 :                                 (get_remote_arch() != RA_CIFSFS)) {
     206           0 :                         set_remote_arch( RA_VISTA );
     207             :                 }
     208             :         }
     209             : 
     210          38 :         reply_smb1_outbuf(req,17,0);
     211             : 
     212             :         /* do spnego in user level security if the client
     213             :            supports it and we can do encrypted passwords */
     214             : 
     215          66 :         if (xconn->smb1.negprot.encrypted_passwords &&
     216          38 :             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
     217          38 :                 negotiate_spnego = True;
     218          38 :                 capabilities |= CAP_EXTENDED_SECURITY;
     219          38 :                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
     220             :                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
     221             :                    (already partially constructed. */
     222          38 :                 SSVAL(req->outbuf, smb_flg2,
     223             :                       req->flags2 | FLAGS2_EXTENDED_SECURITY);
     224             :         }
     225             : 
     226          38 :         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
     227             : 
     228          38 :         if (lp_unicode()) {
     229          38 :                 capabilities |= CAP_UNICODE;
     230             :         }
     231             : 
     232          38 :         if (lp_smb1_unix_extensions()) {
     233          38 :                 capabilities |= CAP_UNIX;
     234             :         }
     235             : 
     236          38 :         if (lp_large_readwrite())
     237          38 :                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
     238             : 
     239          38 :         capabilities |= CAP_LARGE_FILES;
     240             : 
     241          38 :         if (!lp_async_smb_echo_handler() && lp_read_raw() && lp_write_raw())
     242          38 :                 capabilities |= CAP_RAW_MODE;
     243             : 
     244          38 :         if (lp_nt_status_support())
     245          38 :                 capabilities |= CAP_STATUS32;
     246             : 
     247          38 :         if (lp_host_msdfs())
     248          38 :                 capabilities |= CAP_DFS;
     249             : 
     250          38 :         secword |= NEGOTIATE_SECURITY_USER_LEVEL;
     251          38 :         if (xconn->smb1.negprot.encrypted_passwords) {
     252          38 :                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
     253             :         }
     254             : 
     255          38 :         signing_desired = smb1_signing_is_desired(xconn->smb1.signing_state);
     256          38 :         signing_required = smb1_signing_is_mandatory(xconn->smb1.signing_state);
     257             : 
     258          38 :         if (signing_desired) {
     259          18 :                 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
     260             :                 /* No raw mode with smb signing. */
     261          18 :                 capabilities &= ~CAP_RAW_MODE;
     262          18 :                 if (signing_required) {
     263          18 :                         secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
     264             :                 }
     265             :         }
     266             : 
     267          38 :         SSVAL(req->outbuf,smb_vwv0,choice);
     268          38 :         SCVAL(req->outbuf,smb_vwv1,secword);
     269             : 
     270          38 :         status = smbXsrv_connection_init_tables(xconn, PROTOCOL_NT1);
     271          38 :         if (!NT_STATUS_IS_OK(status)) {
     272           0 :                 reply_nterror(req, status);
     273           0 :                 return status;
     274             :         }
     275             : 
     276          38 :         SSVAL(req->outbuf,smb_vwv1+1, lp_max_mux()); /* maxmpx */
     277          38 :         SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */
     278          38 :         SIVAL(req->outbuf,smb_vwv3+1,
     279             :               xconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
     280          38 :         SIVAL(req->outbuf,smb_vwv5+1, 0x10000); /* raw size. full 64k */
     281          38 :         SIVAL(req->outbuf,smb_vwv7+1, getpid()); /* session key */
     282          38 :         SIVAL(req->outbuf,smb_vwv9+1, capabilities); /* capabilities */
     283          38 :         clock_gettime(CLOCK_REALTIME,&ts);
     284          38 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,&ts);
     285          38 :         SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60);
     286             : 
     287          38 :         if (!negotiate_spnego) {
     288             :                 /* Create a token value and add it to the outgoing packet. */
     289           0 :                 if (xconn->smb1.negprot.encrypted_passwords) {
     290             :                         uint8_t chal[8];
     291             :                         /* note that we do not send a challenge at all if
     292             :                            we are using plaintext */
     293           0 :                         get_challenge(xconn, chal);
     294           0 :                         ret = message_push_blob(
     295             :                                 &req->outbuf, data_blob_const(chal, sizeof(chal)));
     296           0 :                         if (ret == -1) {
     297           0 :                                 DEBUG(0, ("Could not push challenge\n"));
     298           0 :                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
     299           0 :                                 return NT_STATUS_NO_MEMORY;
     300             :                         }
     301           0 :                         SCVAL(req->outbuf, smb_vwv16+1, ret);
     302             :                 }
     303           0 :                 ret = message_push_string(&req->outbuf, lp_workgroup(),
     304             :                                           STR_UNICODE|STR_TERMINATE
     305             :                                           |STR_NOALIGN);
     306           0 :                 if (ret == -1) {
     307           0 :                         DEBUG(0, ("Could not push workgroup string\n"));
     308           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     309           0 :                         return NT_STATUS_NO_MEMORY;
     310             :                 }
     311           0 :                 ret = message_push_string(&req->outbuf, lp_netbios_name(),
     312             :                                           STR_UNICODE|STR_TERMINATE
     313             :                                           |STR_NOALIGN);
     314           0 :                 if (ret == -1) {
     315           0 :                         DEBUG(0, ("Could not push netbios name string\n"));
     316           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     317           0 :                         return NT_STATUS_NO_MEMORY;
     318             :                 }
     319           0 :                 DEBUG(3,("not using SPNEGO\n"));
     320             :         } else {
     321          38 :                 DATA_BLOB spnego_blob = negprot_spnego(req, xconn);
     322             : 
     323          38 :                 if (spnego_blob.data == NULL) {
     324           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     325           0 :                         return NT_STATUS_NO_MEMORY;
     326             :                 }
     327             : 
     328          38 :                 ret = message_push_blob(&req->outbuf, spnego_blob);
     329          38 :                 if (ret == -1) {
     330           0 :                         DEBUG(0, ("Could not push spnego blob\n"));
     331           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     332           0 :                         return NT_STATUS_NO_MEMORY;
     333             :                 }
     334          38 :                 data_blob_free(&spnego_blob);
     335             : 
     336          38 :                 SCVAL(req->outbuf,smb_vwv16+1, 0);
     337          38 :                 DEBUG(3,("using SPNEGO\n"));
     338             :         }
     339             : 
     340          38 :         return NT_STATUS_OK;
     341             : }
     342             : 
     343             : /* these are the protocol lists used for auto architecture detection:
     344             : 
     345             : WinNT 3.51:
     346             : protocol [PC NETWORK PROGRAM 1.0]
     347             : protocol [XENIX CORE]
     348             : protocol [MICROSOFT NETWORKS 1.03]
     349             : protocol [LANMAN1.0]
     350             : protocol [Windows for Workgroups 3.1a]
     351             : protocol [LM1.2X002]
     352             : protocol [LANMAN2.1]
     353             : protocol [NT LM 0.12]
     354             : 
     355             : Win95:
     356             : protocol [PC NETWORK PROGRAM 1.0]
     357             : protocol [XENIX CORE]
     358             : protocol [MICROSOFT NETWORKS 1.03]
     359             : protocol [LANMAN1.0]
     360             : protocol [Windows for Workgroups 3.1a]
     361             : protocol [LM1.2X002]
     362             : protocol [LANMAN2.1]
     363             : protocol [NT LM 0.12]
     364             : 
     365             : Win2K:
     366             : protocol [PC NETWORK PROGRAM 1.0]
     367             : protocol [LANMAN1.0]
     368             : protocol [Windows for Workgroups 3.1a]
     369             : protocol [LM1.2X002]
     370             : protocol [LANMAN2.1]
     371             : protocol [NT LM 0.12]
     372             : 
     373             : Vista:
     374             : protocol [PC NETWORK PROGRAM 1.0]
     375             : protocol [LANMAN1.0]
     376             : protocol [Windows for Workgroups 3.1a]
     377             : protocol [LM1.2X002]
     378             : protocol [LANMAN2.1]
     379             : protocol [NT LM 0.12]
     380             : protocol [SMB 2.001]
     381             : 
     382             : OS/2:
     383             : protocol [PC NETWORK PROGRAM 1.0]
     384             : protocol [XENIX CORE]
     385             : protocol [LANMAN1.0]
     386             : protocol [LM1.2X002]
     387             : protocol [LANMAN2.1]
     388             : 
     389             : OSX:
     390             : protocol [NT LM 0.12]
     391             : protocol [SMB 2.002]
     392             : protocol [SMB 2.???]
     393             : */
     394             : 
     395             : /*
     396             :   * Modified to recognize the architecture of the remote machine better.
     397             :   *
     398             :   * This appears to be the matrix of which protocol is used by which
     399             :   * product.
     400             :        Protocol                       WfWg Win95 WinNT Win2K OS/2 Vista OSX
     401             :        PC NETWORK PROGRAM 1.0          1     1     1     1     1    1
     402             :        XENIX CORE                                  2           2
     403             :        MICROSOFT NETWORKS 3.0          2     2
     404             :        DOS LM1.2X002                   3     3
     405             :        MICROSOFT NETWORKS 1.03                     3
     406             :        DOS LANMAN2.1                   4     4
     407             :        LANMAN1.0                                   4     2     3    2
     408             :        Windows for Workgroups 3.1a     5     5     5     3          3
     409             :        LM1.2X002                                   6     4     4    4
     410             :        LANMAN2.1                                   7     5     5    5
     411             :        NT LM 0.12                            6     8     6     6    6    1
     412             :        SMB 2.001                                                    7
     413             :        SMB 2.002                                                         2
     414             :        SMB 2.???                                                         3
     415             :   *
     416             :   *  tim@fsg.com 09/29/95
     417             :   *  Win2K added by matty 17/7/99
     418             :   */
     419             : 
     420             : #define PROT_PC_NETWORK_PROGRAM_1_0             0x0001
     421             : #define PROT_XENIX_CORE                         0x0002
     422             : #define PROT_MICROSOFT_NETWORKS_3_0             0x0004
     423             : #define PROT_DOS_LM1_2X002                      0x0008
     424             : #define PROT_MICROSOFT_NETWORKS_1_03            0x0010
     425             : #define PROT_DOS_LANMAN2_1                      0x0020
     426             : #define PROT_LANMAN1_0                          0x0040
     427             : #define PROT_WFWG                               0x0080
     428             : #define PROT_LM1_2X002                          0x0100
     429             : #define PROT_LANMAN2_1                          0x0200
     430             : #define PROT_NT_LM_0_12                         0x0400
     431             : #define PROT_SMB_2_001                          0x0800
     432             : #define PROT_SMB_2_002                          0x1000
     433             : #define PROT_SMB_2_FF                           0x2000
     434             : #define PROT_SAMBA                              0x4000
     435             : #define PROT_POSIX_2                            0x8000
     436             : 
     437             : #define ARCH_WFWG     ( PROT_PC_NETWORK_PROGRAM_1_0 | PROT_MICROSOFT_NETWORKS_3_0 | \
     438             :                         PROT_DOS_LM1_2X002 | PROT_DOS_LANMAN2_1 | PROT_WFWG )
     439             : #define ARCH_WIN95    ( ARCH_WFWG | PROT_NT_LM_0_12 )
     440             : #define ARCH_WINNT    ( PROT_PC_NETWORK_PROGRAM_1_0 | PROT_XENIX_CORE | \
     441             :                         PROT_MICROSOFT_NETWORKS_1_03 | PROT_LANMAN1_0 | PROT_WFWG | \
     442             :                         PROT_LM1_2X002 | PROT_LANMAN2_1 | PROT_NT_LM_0_12 )
     443             : #define ARCH_WIN2K    ( ARCH_WINNT & ~(PROT_XENIX_CORE | PROT_MICROSOFT_NETWORKS_1_03) )
     444             : #define ARCH_OS2      ( ARCH_WINNT & ~(PROT_MICROSOFT_NETWORKS_1_03 | PROT_WFWG) )
     445             : #define ARCH_VISTA    ( ARCH_WIN2K | PROT_SMB_2_001 )
     446             : #define ARCH_SAMBA    ( PROT_SAMBA )
     447             : #define ARCH_CIFSFS   ( PROT_POSIX_2 )
     448             : #define ARCH_OSX      ( PROT_NT_LM_0_12 | PROT_SMB_2_002 | PROT_SMB_2_FF )
     449             : 
     450             : /* List of supported protocols, most desired first */
     451             : static const struct {
     452             :         const char *proto_name;
     453             :         const char *short_name;
     454             :         NTSTATUS (*proto_reply_fn)(struct smb_request *req, uint16_t choice);
     455             :         int protocol_level;
     456             : } supported_protocols[] = {
     457             :         {"SMB 2.???",               "SMB2_FF",  reply_smb20ff,  PROTOCOL_SMB2_10},
     458             :         {"SMB 2.002",               "SMB2_02",  reply_smb2002,  PROTOCOL_SMB2_02},
     459             :         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
     460             :         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
     461             :         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
     462             :         {"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
     463             :         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
     464             :         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
     465             :         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
     466             :         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
     467             :         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
     468             :         {NULL,NULL,NULL,0},
     469             : };
     470             : 
     471             : /****************************************************************************
     472             :  Reply to a negprot.
     473             :  conn POINTER CAN BE NULL HERE !
     474             : ****************************************************************************/
     475             : 
     476          98 : void reply_negprot(struct smb_request *req)
     477             : {
     478          98 :         size_t choice = 0;
     479          98 :         int chosen_level = -1;
     480          98 :         bool choice_set = false;
     481             :         int protocol;
     482             :         const char *p;
     483          98 :         int protocols = 0;
     484             :         int num_cliprotos;
     485             :         char **cliprotos;
     486             :         size_t i;
     487             :         size_t converted_size;
     488          98 :         struct smbXsrv_connection *xconn = req->xconn;
     489          98 :         struct smbd_server_connection *sconn = req->sconn;
     490          98 :         bool signing_required = true;
     491             :         int max_proto;
     492             :         int min_proto;
     493             :         NTSTATUS status;
     494             : 
     495          98 :         START_PROFILE(SMBnegprot);
     496             : 
     497          98 :         if (xconn->smb1.negprot.done) {
     498           0 :                 END_PROFILE(SMBnegprot);
     499           0 :                 exit_server_cleanly("multiple negprot's are not permitted");
     500             :         }
     501             : 
     502          98 :         if (req->buflen == 0) {
     503           0 :                 DEBUG(0, ("negprot got no protocols\n"));
     504           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     505           0 :                 END_PROFILE(SMBnegprot);
     506           0 :                 return;
     507             :         }
     508             : 
     509          98 :         if (req->buf[req->buflen-1] != '\0') {
     510           0 :                 DEBUG(0, ("negprot protocols not 0-terminated\n"));
     511           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
     512           0 :                 END_PROFILE(SMBnegprot);
     513           0 :                 return;
     514             :         }
     515             : 
     516          98 :         p = (const char *)req->buf + 1;
     517             : 
     518          98 :         num_cliprotos = 0;
     519          98 :         cliprotos = NULL;
     520             : 
     521         885 :         while (smbreq_bufrem(req, p) > 0) {
     522             : 
     523             :                 char **tmp;
     524             : 
     525         708 :                 tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
     526             :                                            num_cliprotos+1);
     527         708 :                 if (tmp == NULL) {
     528           0 :                         DEBUG(0, ("talloc failed\n"));
     529           0 :                         TALLOC_FREE(cliprotos);
     530           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     531           0 :                         END_PROFILE(SMBnegprot);
     532           0 :                         return;
     533             :                 }
     534             : 
     535         708 :                 cliprotos = tmp;
     536             : 
     537         708 :                 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
     538             :                                        &converted_size)) {
     539           0 :                         DEBUG(0, ("pull_ascii_talloc failed\n"));
     540           0 :                         TALLOC_FREE(cliprotos);
     541           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
     542           0 :                         END_PROFILE(SMBnegprot);
     543           0 :                         return;
     544             :                 }
     545             : 
     546         708 :                 DEBUG(3, ("Requested protocol [%s]\n",
     547             :                           cliprotos[num_cliprotos]));
     548             : 
     549         708 :                 num_cliprotos += 1;
     550         708 :                 p += strlen(p) + 2;
     551             :         }
     552             : 
     553         601 :         for (i=0; i<num_cliprotos; i++) {
     554         552 :                 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a")) {
     555           0 :                         protocols |= PROT_WFWG;
     556         552 :                 } else if (strcsequal(cliprotos[i], "DOS LM1.2X002")) {
     557           0 :                         protocols |= PROT_DOS_LM1_2X002;
     558         552 :                 } else if (strcsequal(cliprotos[i], "DOS LANMAN2.1")) {
     559          49 :                         protocols |= PROT_DOS_LANMAN2_1;
     560         503 :                 } else if (strcsequal(cliprotos[i], "LANMAN1.0")) {
     561          49 :                         protocols |= PROT_LANMAN1_0;
     562         454 :                 } else if (strcsequal(cliprotos[i], "NT LM 0.12")) {
     563          49 :                         protocols |= PROT_NT_LM_0_12;
     564         405 :                 } else if (strcsequal(cliprotos[i], "SMB 2.001")) {
     565           0 :                         protocols |= PROT_SMB_2_001;
     566         405 :                 } else if (strcsequal(cliprotos[i], "SMB 2.002")) {
     567          31 :                         protocols |= PROT_SMB_2_002;
     568         374 :                 } else if (strcsequal(cliprotos[i], "SMB 2.???")) {
     569          31 :                         protocols |= PROT_SMB_2_FF;
     570         343 :                 } else if (strcsequal(cliprotos[i], "LANMAN2.1")) {
     571          49 :                         protocols |= PROT_LANMAN2_1;
     572         294 :                 } else if (strcsequal(cliprotos[i], "LM1.2X002")) {
     573          49 :                         protocols |= PROT_LM1_2X002;
     574         245 :                 } else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03")) {
     575          49 :                         protocols |= PROT_MICROSOFT_NETWORKS_1_03;
     576         196 :                 } else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 3.0")) {
     577          49 :                         protocols |= PROT_MICROSOFT_NETWORKS_3_0;
     578         147 :                 } else if (strcsequal(cliprotos[i], "PC NETWORK PROGRAM 1.0")) {
     579          49 :                         protocols |= PROT_PC_NETWORK_PROGRAM_1_0;
     580          98 :                 } else if (strcsequal(cliprotos[i], "XENIX CORE")) {
     581           0 :                         protocols |= PROT_XENIX_CORE;
     582          98 :                 } else if (strcsequal(cliprotos[i], "Samba")) {
     583          49 :                         protocols = PROT_SAMBA;
     584          49 :                         break;
     585          49 :                 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
     586           0 :                         protocols = PROT_POSIX_2;
     587           0 :                         break;
     588             :                 }
     589             :         }
     590             : 
     591          98 :         switch ( protocols ) {
     592             :                 /* Old CIFSFS can send one arch only, NT LM 0.12. */
     593          18 :                 case PROT_NT_LM_0_12:
     594             :                 case ARCH_CIFSFS:
     595          18 :                         set_remote_arch(RA_CIFSFS);
     596          18 :                         break;
     597          49 :                 case ARCH_SAMBA:
     598          49 :                         set_remote_arch(RA_SAMBA);
     599          49 :                         break;
     600           0 :                 case ARCH_WFWG:
     601           0 :                         set_remote_arch(RA_WFWG);
     602           0 :                         break;
     603           0 :                 case ARCH_WIN95:
     604           0 :                         set_remote_arch(RA_WIN95);
     605           0 :                         break;
     606           0 :                 case ARCH_WINNT:
     607           0 :                         set_remote_arch(RA_WINNT);
     608           0 :                         break;
     609           0 :                 case ARCH_WIN2K:
     610           0 :                         set_remote_arch(RA_WIN2K);
     611           0 :                         break;
     612           0 :                 case ARCH_VISTA:
     613           0 :                         set_remote_arch(RA_VISTA);
     614           0 :                         break;
     615           0 :                 case ARCH_OS2:
     616           0 :                         set_remote_arch(RA_OS2);
     617           0 :                         break;
     618          31 :                 case ARCH_OSX:
     619          31 :                         set_remote_arch(RA_OSX);
     620          31 :                         break;
     621           0 :                 default:
     622           0 :                         set_remote_arch(RA_UNKNOWN);
     623           0 :                 break;
     624             :         }
     625             : 
     626             :         /* possibly reload - change of architecture */
     627          98 :         reload_services(sconn, conn_snum_used, true);
     628             : 
     629             :         /*
     630             :          * Anything higher than PROTOCOL_SMB2_10 still
     631             :          * needs to go via "SMB 2.???", which is marked
     632             :          * as PROTOCOL_SMB2_10.
     633             :          *
     634             :          * The real negotiation happens via reply_smb20ff()
     635             :          * using SMB2 Negotiation.
     636             :          */
     637          98 :         max_proto = lp_server_max_protocol();
     638          98 :         if (max_proto > PROTOCOL_SMB2_10) {
     639          98 :                 max_proto = PROTOCOL_SMB2_10;
     640             :         }
     641          98 :         min_proto = lp_server_min_protocol();
     642          98 :         if (min_proto > PROTOCOL_SMB2_10) {
     643           0 :                 min_proto = PROTOCOL_SMB2_10;
     644             :         }
     645             : 
     646             :         /* Check for protocols, most desirable first */
     647         174 :         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
     648         174 :                 i = 0;
     649         309 :                 if ((supported_protocols[protocol].protocol_level <= max_proto) &&
     650         174 :                     (supported_protocols[protocol].protocol_level >= min_proto))
     651        1489 :                         while (i < num_cliprotos) {
     652        1180 :                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name)) {
     653          98 :                                         choice = i;
     654          98 :                                         chosen_level = supported_protocols[protocol].protocol_level;
     655          98 :                                         choice_set = true;
     656             :                                 }
     657        1180 :                                 i++;
     658             :                         }
     659         174 :                 if (choice_set) {
     660          98 :                         break;
     661             :                 }
     662             :         }
     663             : 
     664          98 :         if (!choice_set) {
     665             :                 bool ok;
     666             : 
     667           0 :                 DBG_NOTICE("No protocol supported !\n");
     668           0 :                 reply_smb1_outbuf(req, 1, 0);
     669           0 :                 SSVAL(req->outbuf, smb_vwv0, NO_PROTOCOL_CHOSEN);
     670             : 
     671           0 :                 ok = smb1_srv_send(xconn, (char *)req->outbuf,
     672             :                                   false, 0, false, NULL);
     673           0 :                 if (!ok) {
     674           0 :                         DBG_NOTICE("smb1_srv_send failed\n");
     675             :                 }
     676           0 :                 exit_server_cleanly("no protocol supported\n");
     677             :         }
     678             : 
     679          98 :         fstrcpy(remote_proto,supported_protocols[protocol].short_name);
     680          98 :         reload_services(sconn, conn_snum_used, true);
     681          98 :         status = supported_protocols[protocol].proto_reply_fn(req, choice);
     682          98 :         if (!NT_STATUS_IS_OK(status)) {
     683           0 :                 exit_server_cleanly("negprot function failed\n");
     684             :         }
     685             : 
     686          98 :         DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
     687             : 
     688          98 :         DBG_INFO("negprot index=%zu\n", choice);
     689             : 
     690          98 :         xconn->smb1.negprot.done = true;
     691             : 
     692             :         /* We always have xconn->smb1.signing_state also for >= SMB2_02 */
     693          98 :         signing_required = smb1_signing_is_mandatory(xconn->smb1.signing_state);
     694          98 :         if (signing_required && (chosen_level < PROTOCOL_NT1)) {
     695           0 :                 exit_server_cleanly("SMB signing is required and "
     696             :                         "client negotiated a downlevel protocol");
     697             :         }
     698             : 
     699          98 :         TALLOC_FREE(cliprotos);
     700             : 
     701          98 :         if (lp_async_smb_echo_handler() && (chosen_level < PROTOCOL_SMB2_02) &&
     702           0 :             !fork_echo_handler(xconn)) {
     703           0 :                 exit_server("Failed to fork echo handler");
     704             :         }
     705             : 
     706          98 :         END_PROFILE(SMBnegprot);
     707          98 :         return;
     708             : }

Generated by: LCOV version 1.13