diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index 010aa4d1bb4..ca492e0a1c6 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -130,6 +130,55 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli) return capabilities; } +/**************************************************************************** + Do a NT1 guest session setup. +****************************************************************************/ + +static BOOL cli_session_setup_guest(struct cli_state *cli) +{ + char *p; + uint32 capabilities = cli_session_setup_capabilities(cli); + + set_message(cli->outbuf,13,0,True); + SCVAL(cli->outbuf,smb_com,SMBsesssetupX); + cli_setup_packet(cli); + + SCVAL(cli->outbuf,smb_vwv0,0xFF); + SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE); + SSVAL(cli->outbuf,smb_vwv3,2); + SSVAL(cli->outbuf,smb_vwv4,cli->pid); + SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); + SSVAL(cli->outbuf,smb_vwv7,0); + SSVAL(cli->outbuf,smb_vwv8,0); + SIVAL(cli->outbuf,smb_vwv11,capabilities); + p = smb_buf(cli->outbuf); + p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */ + p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */ + p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); + p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); + cli_setup_bcc(cli, p); + + cli_send_smb(cli); + if (!cli_receive_smb(cli)) + return False; + + show_msg(cli->inbuf); + + if (cli_is_error(cli)) + return False; + + cli->vuid = SVAL(cli->inbuf,smb_uid); + + p = smb_buf(cli->inbuf); + p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE); + p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE); + p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE); + + fstrcpy(cli->user_name, ""); + + return True; +} + /**************************************************************************** Do a NT1 plaintext session setup. ****************************************************************************/ @@ -198,7 +247,8 @@ static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key) } /**************************************************************************** - do a NT1 NTLM/LM encrypted session setup + do a NT1 NTLM/LM encrypted session setup - for when extended security + is not negotiated. @param cli client state to create do session setup on @param user username @param pass *either* cleartext password (passlen !=24) or LM response. @@ -221,7 +271,10 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, if (passlen == 0) { /* do nothing - guest login */ } else if (passlen != 24) { - if ((cli->capabilities & CAP_EXTENDED_SECURITY) && lp_client_ntlmv2_auth()) { + /* if client ntlmv2 auth is set, then don't use it on a + connection without extended security. This isn't a very + good check, but it is a start */ + if (lp_client_ntlmv2_auth()) { DATA_BLOB server_chal; DATA_BLOB names_blob; server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); @@ -573,7 +626,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) { return False; } - + return (NT_STATUS_IS_OK(nt_status)); } @@ -581,8 +634,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, Do a spnego encrypted session setup. ****************************************************************************/ -static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, - const char *pass, const char *workgroup) +BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, + const char *pass, const char *workgroup) { char *principal; char *OIDs[ASN1_MAX_OIDS]; @@ -704,6 +757,12 @@ BOOL cli_session_setup(struct cli_state *cli, return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup); } + /* if no user is supplied then we have to do an anonymous connection. + passwords are ignored */ + + if (!user || !*user) + return cli_session_setup_guest(cli); + /* if the server is share level then send a plaintext null password at this point. The password is sent in the tree connect */ @@ -711,17 +770,6 @@ BOOL cli_session_setup(struct cli_state *cli, if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) return cli_session_setup_plaintext(cli, user, "", workgroup); - /* if no user is supplied then we have to do an anonymous connection. - passwords are ignored */ - - if (!user || !*user) { - user = ""; - pass = NULL; - ntpass = NULL; - passlen = 0; - ntpasslen = 0; - } - /* if the server doesn't support encryption then we have to use plaintext. The second password is ignored */ @@ -1187,7 +1235,7 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) Initialise client credentials for authenticated pipe access. ****************************************************************************/ -static void init_creds(struct ntuser_creds *creds, const char* username, +void init_creds(struct ntuser_creds *creds, const char* username, const char* domain, const char* password) { ZERO_STRUCTP(creds); @@ -1203,30 +1251,21 @@ static void init_creds(struct ntuser_creds *creds, const char* username, } /** - establishes a connection right up to doing tconX, password specified. + establishes a connection to after the negprot. @param output_cli A fully initialised cli structure, non-null only on success @param dest_host The netbios name of the remote host @param dest_ip (optional) The the destination IP, NULL for name based lookup @param port (optional) The destination port (0 for default) - @param service (optional) The share to make the connection to. Should be 'unqualified' in any way. - @param service_type The 'type' of serivice. - @param user Username, unix string - @param domain User's domain - @param password User's password, unencrypted unix string. @param retry BOOL. Did this connection fail with a retryable error ? -*/ -NTSTATUS cli_full_connection(struct cli_state **output_cli, - const char *my_name, - const char *dest_host, - struct in_addr *dest_ip, int port, - const char *service, const char *service_type, - const char *user, const char *domain, - const char *password, int flags, - int signing_state, - BOOL *retry) +*/ +NTSTATUS cli_start_connection(struct cli_state **output_cli, + const char *my_name, + const char *dest_host, + struct in_addr *dest_ip, int port, + int signing_state, int flags, + BOOL *retry) { - struct ntuser_creds creds; NTSTATUS nt_status; struct nmb_name calling; struct nmb_name called; @@ -1259,7 +1298,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, again: - DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service)); + DEBUG(3,("Connecting to host=%s\n", dest_host)); if (!cli_connect(cli, dest_host, &ip)) { DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n", @@ -1300,6 +1339,46 @@ again: return nt_status; } + *output_cli = cli; + return NT_STATUS_OK; +} + + +/** + establishes a connection right up to doing tconX, password specified. + @param output_cli A fully initialised cli structure, non-null only on success + @param dest_host The netbios name of the remote host + @param dest_ip (optional) The the destination IP, NULL for name based lookup + @param port (optional) The destination port (0 for default) + @param service (optional) The share to make the connection to. Should be 'unqualified' in any way. + @param service_type The 'type' of serivice. + @param user Username, unix string + @param domain User's domain + @param password User's password, unencrypted unix string. + @param retry BOOL. Did this connection fail with a retryable error ? +*/ + +NTSTATUS cli_full_connection(struct cli_state **output_cli, + const char *my_name, + const char *dest_host, + struct in_addr *dest_ip, int port, + const char *service, const char *service_type, + const char *user, const char *domain, + const char *password, int flags, + int signing_state, + BOOL *retry) +{ + struct ntuser_creds creds; + NTSTATUS nt_status; + struct cli_state *cli = NULL; + + nt_status = cli_start_connection(&cli, my_name, dest_host, + dest_ip, port, signing_state, flags, retry); + + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + if (!cli_session_setup(cli, user, password, strlen(password)+1, password, strlen(password)+1, domain)) {