2003-08-13 01:53:07 +00:00
/*
Unix SMB / CIFS implementation .
2005-01-15 11:58:52 +00:00
2003-08-13 01:53:07 +00:00
SMB client negotiate context management functions
2005-01-15 11:58:52 +00:00
Copyright ( C ) Andrew Tridgell 1994 - 2005
2003-08-13 01:53:07 +00:00
Copyright ( C ) James Myers 2003 < myersjj @ samba . org >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 01:53:07 +00:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 01:53:07 +00:00
*/
# include "includes.h"
2004-11-01 01:03:22 +00:00
# include "libcli/raw/libcliraw.h"
2004-11-02 00:24:21 +00:00
# include "system/time.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2003-08-13 01:53:07 +00:00
static const struct {
2003-08-15 18:33:43 +00:00
enum protocol_types prot ;
2003-08-13 01:53:07 +00:00
const char * name ;
} prots [ ] = {
{ PROTOCOL_CORE , " PC NETWORK PROGRAM 1.0 " } ,
{ PROTOCOL_COREPLUS , " MICROSOFT NETWORKS 1.03 " } ,
{ PROTOCOL_LANMAN1 , " MICROSOFT NETWORKS 3.0 " } ,
{ PROTOCOL_LANMAN1 , " LANMAN1.0 " } ,
{ PROTOCOL_LANMAN1 , " Windows for Workgroups 3.1a " } ,
{ PROTOCOL_LANMAN2 , " LM1.2X002 " } ,
{ PROTOCOL_LANMAN2 , " DOS LANMAN2.1 " } ,
2004-07-05 23:28:49 +00:00
{ PROTOCOL_LANMAN2 , " LANMAN2.1 " } ,
2003-08-13 01:53:07 +00:00
{ PROTOCOL_LANMAN2 , " Samba " } ,
{ PROTOCOL_NT1 , " NT LANMAN 1.0 " } ,
{ PROTOCOL_NT1 , " NT LM 0.12 " } ,
} ;
2005-01-15 11:58:52 +00:00
/*
Send a negprot command .
*/
struct smbcli_request * smb_raw_negotiate_send ( struct smbcli_transport * transport ,
int maxprotocol )
2003-08-13 01:53:07 +00:00
{
2004-08-04 13:23:35 +00:00
struct smbcli_request * req ;
2003-08-13 01:53:07 +00:00
int i ;
2004-07-05 23:28:49 +00:00
uint16_t flags2 = 0 ;
2003-08-13 01:53:07 +00:00
2004-08-04 13:23:35 +00:00
req = smbcli_request_setup_transport ( transport , SMBnegprot , 0 , 0 ) ;
2003-08-13 01:53:07 +00:00
if ( ! req ) {
return NULL ;
}
2004-07-05 23:28:49 +00:00
flags2 | = FLAGS2_32_BIT_ERROR_CODES ;
2007-09-28 01:17:46 +00:00
if ( lp_unicode ( global_loadparm ) ) {
2004-08-11 21:09:36 +00:00
flags2 | = FLAGS2_UNICODE_STRINGS ;
}
2004-07-05 23:28:49 +00:00
flags2 | = FLAGS2_EXTENDED_ATTRIBUTES ;
flags2 | = FLAGS2_LONG_PATH_COMPONENTS ;
flags2 | = FLAGS2_IS_LONG_NAME ;
if ( transport - > options . use_spnego ) {
flags2 | = FLAGS2_EXTENDED_SECURITY ;
}
SSVAL ( req - > out . hdr , HDR_FLG2 , flags2 ) ;
2003-08-13 01:53:07 +00:00
/* setup the protocol strings */
for ( i = 0 ; i < ARRAY_SIZE ( prots ) & & prots [ i ] . prot < = maxprotocol ; i + + ) {
2004-12-04 13:56:25 +00:00
smbcli_req_append_bytes ( req , ( const uint8_t * ) " \2 " , 1 ) ;
2004-08-04 13:23:35 +00:00
smbcli_req_append_string ( req , prots [ i ] . name , STR_TERMINATE | STR_ASCII ) ;
2003-08-13 01:53:07 +00:00
}
2004-08-04 13:23:35 +00:00
if ( ! smbcli_request_send ( req ) ) {
smbcli_request_destroy ( req ) ;
2003-08-13 01:53:07 +00:00
return NULL ;
}
return req ;
}
2005-01-15 11:58:52 +00:00
/*
2003-08-13 01:53:07 +00:00
Send a negprot command .
2005-01-15 11:58:52 +00:00
*/
NTSTATUS smb_raw_negotiate_recv ( struct smbcli_request * req )
2003-08-13 01:53:07 +00:00
{
2005-01-15 11:58:52 +00:00
struct smbcli_transport * transport = req - > transport ;
2003-08-13 01:53:07 +00:00
int protocol ;
2004-08-04 13:23:35 +00:00
if ( ! smbcli_request_receive ( req ) | |
smbcli_request_is_error ( req ) ) {
return smbcli_request_destroy ( req ) ;
2003-08-13 01:53:07 +00:00
}
2004-08-04 13:23:35 +00:00
SMBCLI_CHECK_MIN_WCT ( req , 1 ) ;
2003-08-13 01:53:07 +00:00
protocol = SVALS ( req - > in . vwv , VWV ( 0 ) ) ;
if ( protocol > = ARRAY_SIZE ( prots ) | | protocol < 0 ) {
req - > status = NT_STATUS_UNSUCCESSFUL ;
2004-08-04 13:23:35 +00:00
return smbcli_request_destroy ( req ) ;
2003-08-13 01:53:07 +00:00
}
transport - > negotiate . protocol = prots [ protocol ] . prot ;
if ( transport - > negotiate . protocol > = PROTOCOL_NT1 ) {
NTTIME ntt ;
/* NT protocol */
2004-08-04 13:23:35 +00:00
SMBCLI_CHECK_WCT ( req , 17 ) ;
2003-08-13 01:53:07 +00:00
transport - > negotiate . sec_mode = CVAL ( req - > in . vwv , VWV ( 1 ) ) ;
transport - > negotiate . max_mux = SVAL ( req - > in . vwv , VWV ( 1 ) + 1 ) ;
transport - > negotiate . max_xmit = IVAL ( req - > in . vwv , VWV ( 3 ) + 1 ) ;
transport - > negotiate . sesskey = IVAL ( req - > in . vwv , VWV ( 7 ) + 1 ) ;
2004-07-05 23:28:49 +00:00
transport - > negotiate . capabilities = IVAL ( req - > in . vwv , VWV ( 9 ) + 1 ) ;
2003-08-13 01:53:07 +00:00
/* this time arrives in real GMT */
2004-08-04 13:23:35 +00:00
ntt = smbcli_pull_nttime ( req - > in . vwv , VWV ( 11 ) + 1 ) ;
2004-07-05 23:28:49 +00:00
transport - > negotiate . server_time = nt_time_to_unix ( ntt ) ;
transport - > negotiate . server_zone = SVALS ( req - > in . vwv , VWV ( 15 ) + 1 ) * 60 ;
transport - > negotiate . key_len = CVAL ( req - > in . vwv , VWV ( 16 ) + 1 ) ;
if ( transport - > negotiate . capabilities & CAP_EXTENDED_SECURITY ) {
if ( req - > in . data_size < 16 ) {
goto failed ;
}
2004-08-21 07:43:29 +00:00
transport - > negotiate . server_guid = smbcli_req_pull_blob ( req , transport , req - > in . data , 16 ) ;
transport - > negotiate . secblob = smbcli_req_pull_blob ( req , transport , req - > in . data + 16 , req - > in . data_size - 16 ) ;
2004-07-05 23:28:49 +00:00
} else {
if ( req - > in . data_size < ( transport - > negotiate . key_len ) ) {
goto failed ;
}
2004-08-21 07:43:29 +00:00
transport - > negotiate . secblob = smbcli_req_pull_blob ( req , transport , req - > in . data , transport - > negotiate . key_len ) ;
smbcli_req_pull_string ( req , transport , & transport - > negotiate . server_domain ,
2004-07-05 23:28:49 +00:00
req - > in . data + transport - > negotiate . key_len ,
req - > in . data_size - transport - > negotiate . key_len , STR_UNICODE | STR_NOALIGN ) ;
/* here comes the server name */
}
2003-08-13 01:53:07 +00:00
if ( transport - > negotiate . capabilities & CAP_RAW_MODE ) {
2007-10-06 22:28:14 +00:00
transport - > negotiate . readbraw_supported = true ;
transport - > negotiate . writebraw_supported = true ;
2003-08-13 01:53:07 +00:00
}
} else if ( transport - > negotiate . protocol > = PROTOCOL_LANMAN1 ) {
2004-08-04 13:23:35 +00:00
SMBCLI_CHECK_WCT ( req , 13 ) ;
2003-08-13 01:53:07 +00:00
transport - > negotiate . sec_mode = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
transport - > negotiate . max_xmit = SVAL ( req - > in . vwv , VWV ( 2 ) ) ;
transport - > negotiate . sesskey = IVAL ( req - > in . vwv , VWV ( 6 ) ) ;
transport - > negotiate . server_zone = SVALS ( req - > in . vwv , VWV ( 10 ) ) * 60 ;
2004-04-10 20:18:22 +00:00
/* this time is converted to GMT by raw_pull_dos_date */
transport - > negotiate . server_time = raw_pull_dos_date ( transport ,
req - > in . vwv + VWV ( 8 ) ) ;
2003-08-13 01:53:07 +00:00
if ( ( SVAL ( req - > in . vwv , VWV ( 5 ) ) & 0x1 ) ) {
transport - > negotiate . readbraw_supported = 1 ;
}
if ( ( SVAL ( req - > in . vwv , VWV ( 5 ) ) & 0x2 ) ) {
transport - > negotiate . writebraw_supported = 1 ;
}
2004-08-21 07:43:29 +00:00
transport - > negotiate . secblob = smbcli_req_pull_blob ( req , transport ,
2003-08-13 01:53:07 +00:00
req - > in . data , req - > in . data_size ) ;
} else {
/* the old core protocol */
transport - > negotiate . sec_mode = 0 ;
transport - > negotiate . server_time = time ( NULL ) ;
2004-10-29 06:01:00 +00:00
transport - > negotiate . max_xmit = transport - > options . max_xmit ;
2004-04-10 20:18:22 +00:00
transport - > negotiate . server_zone = get_time_zone ( transport - > negotiate . server_time ) ;
2003-08-13 01:53:07 +00:00
}
/* a way to force ascii SMB */
2007-09-28 01:17:46 +00:00
if ( ! lp_unicode ( global_loadparm ) ) {
2003-08-13 01:53:07 +00:00
transport - > negotiate . capabilities & = ~ CAP_UNICODE ;
}
2007-09-28 01:17:46 +00:00
if ( ! lp_nt_status_support ( global_loadparm ) ) {
2005-07-04 01:23:38 +00:00
transport - > negotiate . capabilities & = ~ CAP_STATUS32 ;
}
2003-08-13 01:53:07 +00:00
failed :
2004-08-04 13:23:35 +00:00
return smbcli_request_destroy ( req ) ;
2003-08-13 01:53:07 +00:00
}
2005-01-15 11:58:52 +00:00
/*
Send a negprot command ( sync interface )
*/
NTSTATUS smb_raw_negotiate ( struct smbcli_transport * transport , int maxprotocol )
{
struct smbcli_request * req = smb_raw_negotiate_send ( transport , maxprotocol ) ;
return smb_raw_negotiate_recv ( req ) ;
}