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

Generated by: LCOV version 1.14