📄 cliconnect.c
字号:
/* Unix SMB/CIFS implementation. client connect/disconnect routines Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Andrew Bartlett 2001-2003 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 the Free Software Foundation; either version 2 of the License, or (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 along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"extern pstring user_socket_options;static const struct { int prot; 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_LANMAN2,"LM1.2X002"}, {PROTOCOL_LANMAN2,"DOS LANMAN2.1"}, {PROTOCOL_LANMAN2,"Samba"}, {PROTOCOL_NT1,"NT LANMAN 1.0"}, {PROTOCOL_NT1,"NT LM 0.12"}, {-1,NULL}};/** * Set the user session key for a connection * @param cli The cli structure to add it too * @param session_key The session key used. (A copy of this is taken for the cli struct) * */static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key) { cli->user_session_key = data_blob(session_key.data, session_key.length);}/**************************************************************************** Do an old lanman2 style session setup.****************************************************************************/static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user, const char *pass, size_t passlen, const char *workgroup){ DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB lm_response = data_blob(NULL, 0); fstring pword; char *p; if (passlen > sizeof(pword)-1) return False; /* LANMAN servers predate NT status codes and Unicode and ignore those smb flags so we must disable the corresponding default capabilities that would otherwise cause the Unicode and NT Status flags to be set (and even returned by the server) */ cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32); /* if in share level security then don't send a password now */ if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) passlen = 0; if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) { /* Encrypted mode needed, and non encrypted password supplied. */ lm_response = data_blob(NULL, 24); if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) { DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n")); return False; } } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) { /* Encrypted mode needed, and encrypted password supplied. */ lm_response = data_blob(pass, passlen); } else if (passlen > 0) { /* Plaintext mode needed, assume plaintext supplied. */ passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE); lm_response = data_blob(pass, passlen); } /* send a session setup command */ memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,10, 0, True); SCVAL(cli->outbuf,smb_com,SMBsesssetupX); cli_setup_packet(cli); SCVAL(cli->outbuf,smb_vwv0,0xFF); SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit); SSVAL(cli->outbuf,smb_vwv3,2); SSVAL(cli->outbuf,smb_vwv4,1); SIVAL(cli->outbuf,smb_vwv5,cli->sesskey); SSVAL(cli->outbuf,smb_vwv7,lm_response.length); p = smb_buf(cli->outbuf); memcpy(p,lm_response.data,lm_response.length); p += lm_response.length; p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER); p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER); 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; /* use the returned vuid from now on */ cli->vuid = SVAL(cli->inbuf,smb_uid); fstrcpy(cli->user_name, user); if (session_key.data) { /* Have plaintext orginal */ cli_set_session_key(cli, session_key); } return True;}/**************************************************************************** Work out suitable capabilities to offer the server.****************************************************************************/static uint32 cli_session_setup_capabilities(struct cli_state *cli){ uint32 capabilities = CAP_NT_SMBS; if (!cli->force_dos_errors) capabilities |= CAP_STATUS32; if (cli->use_level_II_oplocks) capabilities |= CAP_LEVEL_II_OPLOCKS; capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS)); 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); memset(cli->outbuf, '\0', smb_size); 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.****************************************************************************/static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user, const char *pass, const char *workgroup){ uint32 capabilities = cli_session_setup_capabilities(cli); char *p; fstring lanman; fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING); 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_vwv8,0); SIVAL(cli->outbuf,smb_vwv11,capabilities); p = smb_buf(cli->outbuf); /* check wether to send the ASCII or UNICODE version of the password */ if ( (capabilities & CAP_UNICODE) == 0 ) { p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */ SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf))); } else { p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */ SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))); } p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */ p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */ p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); p += clistr_push(cli, p, lanman, -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, user); return True;}/**************************************************************************** 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. @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear @param workgroup The user's domain.****************************************************************************/static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, const char *pass, size_t passlen, const char *ntpass, size_t ntpasslen, const char *workgroup){ uint32 capabilities = cli_session_setup_capabilities(cli); DATA_BLOB lm_response = data_blob(NULL, 0); DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); BOOL ret = False; char *p; if (passlen == 0) { /* do nothing - guest login */ } else if (passlen != 24) { 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)); /* note that the 'workgroup' here is a best guess - we don't know the server's domain at this point. The 'server name' is also dodgy... */ names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup); if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal, &names_blob, &lm_response, &nt_response, &session_key)) { data_blob_free(&names_blob); data_blob_free(&server_chal); return False; } data_blob_free(&names_blob); data_blob_free(&server_chal); } else { uchar nt_hash[16]; E_md4hash(pass, nt_hash);#ifdef LANMAN_ONLY nt_response = data_blob(NULL, 0);#else nt_response = data_blob(NULL, 24); SMBNTencrypt(pass,cli->secblob.data,nt_response.data);#endif /* non encrypted password supplied. Ignore ntpass. */ if (lp_client_lanman_auth()) { lm_response = data_blob(NULL, 24); if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) { /* Oops, the LM response is invalid, just put the NT response there instead */ data_blob_free(&lm_response); lm_response = data_blob(nt_response.data, nt_response.length); } } else { /* LM disabled, place NT# in LM field instead */ lm_response = data_blob(nt_response.data, nt_response.length); } session_key = data_blob(NULL, 16);#ifdef LANMAN_ONLY E_deshash(pass, session_key.data); memset(&session_key.data[8], '\0', 8);#else SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);#endif }#ifdef LANMAN_ONLY cli_simple_set_signing(cli, session_key, lm_response); #else cli_simple_set_signing(cli, session_key, nt_response); #endif } else { /* pre-encrypted password supplied. Only used for security=server, can't do signing because we don't have original key */ lm_response = data_blob(pass, passlen); nt_response = data_blob(ntpass, ntpasslen); } /* send a session setup command */ memset(cli->outbuf,'\0',smb_size); 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,lm_response.length); SSVAL(cli->outbuf,smb_vwv8,nt_response.length); SIVAL(cli->outbuf,smb_vwv11,capabilities); p = smb_buf(cli->outbuf); if (lm_response.length) { memcpy(p,lm_response.data, lm_response.length); p += lm_response.length; } if (nt_response.length) { memcpy(p,nt_response.data, nt_response.length); p += nt_response.length; } p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* Upper case here might help some NTLMv2 implementations */ p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER); p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE); p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE); cli_setup_bcc(cli, p); if (!cli_send_smb(cli) || !cli_receive_smb(cli)) { ret = False; goto end; } /* show_msg(cli->inbuf); */ if (cli_is_error(cli)) { ret = False; goto end; } /* use the returned vuid from now on */ 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, user); if (session_key.data) { /* Have plaintext orginal */ cli_set_session_key(cli, session_key); } ret = True;end: data_blob_free(&lm_response); data_blob_free(&nt_response); data_blob_free(&session_key); return ret;}/**************************************************************************** Send a extended security session setup blob****************************************************************************/static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob){ uint32 capabilities = cli_session_setup_capabilities(cli); char *p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -