#include "includes.h"
#include "libsmb/libsmb.h"
-#include "popt_common.h"
+#include "auth_info.h"
#include "../libcli/auth/libcli_auth.h"
#include "../libcli/auth/spnego.h"
#include "smb_krb5.h"
-#include "../libcli/auth/ntlmssp.h"
+#include "../auth/ntlmssp/ntlmssp.h"
#include "libads/kerberos_proto.h"
#include "krb5_env.h"
#include "../lib/util/tevent_ntstatus.h"
#include "async_smb.h"
#include "libsmb/nmblib.h"
-#include "read_smb.h"
-
-static const struct {
- int prot;
- const char name[24];
-} prots[10] = {
- {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, "LANMAN2.1"},
- {PROTOCOL_LANMAN2, "Samba"},
- {PROTOCOL_NT1, "NT LANMAN 1.0"},
- {PROTOCOL_NT1, "NT LM 0.12"},
-};
+#include "librpc/ndr/libndr.h"
+#include "../libcli/smb/smbXcli_base.h"
+#include "smb2cli.h"
#define STAR_SMBSERVER "*SMBSERVER"
strings.
*******************************************************/
-static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
+static NTSTATUS smb_bytes_talloc_string(TALLOC_CTX *mem_ctx,
char *inbuf,
char **dest,
uint8_t *src,
size_t srclen,
ssize_t *destlen)
{
- *destlen = clistr_pull_talloc(cli,
+ *destlen = clistr_pull_talloc(mem_ctx,
inbuf,
SVAL(inbuf, smb_flg2),
dest,
}
if (*dest == NULL) {
- *dest = talloc_strdup(cli, "");
+ *dest = talloc_strdup(mem_ctx, "");
if (*dest == NULL) {
return NT_STATUS_NO_MEMORY;
}
uint16_t *vwv;
uint8_t *bytes;
char *tmp;
+ uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
req = tevent_req_create(mem_ctx, &state,
struct cli_session_setup_lanman2_state);
state->user = user;
vwv = state->vwv;
- /*
- * 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)) {
+ if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
passlen = 0;
}
if (passlen > 0
- && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
+ && (sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
&& passlen != 24) {
/*
* Encrypted mode needed, and non encrypted password
return tevent_req_post(req, ev);
}
- if (!SMBencrypt(pass, cli->secblob.data,
+ if (!SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
(uint8_t *)lm_response.data)) {
DEBUG(1, ("Password is > 14 chars in length, and is "
"therefore incompatible with Lanman "
tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
return tevent_req_post(req, ev);
}
- } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
+ } else if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
&& passlen == 24) {
/*
* Encrypted mode needed, and encrypted password
SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
SSVAL(vwv+3, 0, 2);
SSVAL(vwv+4, 0, 1);
- SIVAL(vwv+5, 0, cli->sesskey);
+ SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
SSVAL(vwv+7, 0, lm_response.length);
bytes = talloc_array(state, uint8_t, lm_response.length);
inbuf = (char *)in;
p = bytes;
- cli->vuid = SVAL(inbuf, smb_uid);
+ cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
status = smb_bytes_talloc_string(cli,
}
p += ret;
- if (strstr(cli->server_type, "Samba")) {
- cli->is_samba = True;
- }
status = cli_set_username(cli, state->user);
if (tevent_req_nterror(req, status)) {
return;
Work out suitable capabilities to offer the server.
****************************************************************************/
-static uint32 cli_session_setup_capabilities(struct cli_state *cli)
+static uint32_t cli_session_setup_capabilities(struct cli_state *cli,
+ uint32_t sesssetup_capabilities)
{
- uint32 capabilities = CAP_NT_SMBS;
+ uint32_t client_capabilities = smb1cli_conn_capabilities(cli->conn);
- if (!cli->force_dos_errors)
- capabilities |= CAP_STATUS32;
+ /*
+ * We only send capabilities based on the mask for:
+ * - client only flags
+ * - flags used in both directions
+ *
+ * We do not echo the server only flags.
+ */
+ client_capabilities &= (SMB_CAP_BOTH_MASK | SMB_CAP_CLIENT_MASK);
- if (cli->use_level_II_oplocks)
- capabilities |= CAP_LEVEL_II_OPLOCKS;
+ /*
+ * Session Setup specific flags CAP_DYNAMIC_REAUTH
+ * and CAP_EXTENDED_SECURITY are passed by the caller.
+ * We need that in order to do guest logins even if
+ * CAP_EXTENDED_SECURITY is negotiated.
+ */
+ client_capabilities &= ~(CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
+ sesssetup_capabilities &= (CAP_DYNAMIC_REAUTH|CAP_EXTENDED_SECURITY);
+ client_capabilities |= sesssetup_capabilities;
- capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
- return capabilities;
+ return client_capabilities;
}
/****************************************************************************
SSVAL(vwv+1, 0, 0);
SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
SSVAL(vwv+3, 0, 2);
- SSVAL(vwv+4, 0, cli->pid);
- SIVAL(vwv+5, 0, cli->sesskey);
+ SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
+ SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
SSVAL(vwv+7, 0, 0);
SSVAL(vwv+8, 0, 0);
SSVAL(vwv+9, 0, 0);
SSVAL(vwv+10, 0, 0);
- SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
+ SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
bytes = talloc_array(state, uint8_t, 0);
inbuf = (char *)in;
p = bytes;
- cli->vuid = SVAL(inbuf, smb_uid);
+ cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
status = smb_bytes_talloc_string(cli,
}
p += ret;
- if (strstr(cli->server_type, "Samba")) {
- cli->is_samba = True;
- }
-
status = cli_set_username(cli, "");
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
SSVAL(vwv+1, 0, 0);
SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
SSVAL(vwv+3, 0, 2);
- SSVAL(vwv+4, 0, cli->pid);
- SIVAL(vwv+5, 0, cli->sesskey);
+ SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
+ SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
SSVAL(vwv+7, 0, 0);
SSVAL(vwv+8, 0, 0);
SSVAL(vwv+9, 0, 0);
SSVAL(vwv+10, 0, 0);
- SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
+ SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
bytes = talloc_array(state, uint8_t, 0);
bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
inbuf = (char *)in;
p = bytes;
- cli->vuid = SVAL(inbuf, smb_uid);
+ cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
status = smb_bytes_talloc_string(cli,
if (tevent_req_nterror(req, status)) {
return;
}
- if (strstr(cli->server_type, "Samba")) {
- cli->is_samba = True;
- }
+
tevent_req_done(req);
}
DATA_BLOB server_chal;
DATA_BLOB names_blob;
- server_chal = data_blob(cli->secblob.data,
- MIN(cli->secblob.length, 8));
- if (tevent_req_nomem(server_chal.data, req)) {
- return tevent_req_post(req, ev);
- }
+ server_chal =
+ data_blob_const(smb1cli_conn_server_challenge(cli->conn),
+ 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...
+ * at this point. Windows clients also don't
+ * use hostname...
*/
names_blob = NTLMv2_generate_names_blob(
- NULL, cli->called.name, workgroup);
+ NULL, NULL, workgroup);
if (tevent_req_nomem(names_blob.data, req)) {
return tevent_req_post(req, ev);
&lm_response, &nt_response,
NULL, &session_key)) {
data_blob_free(&names_blob);
- data_blob_free(&server_chal);
tevent_req_nterror(
req, NT_STATUS_ACCESS_DENIED);
return tevent_req_post(req, ev);
}
data_blob_free(&names_blob);
- data_blob_free(&server_chal);
} else {
uchar nt_hash[16];
return tevent_req_post(req, ev);
}
- SMBNTencrypt(pass, cli->secblob.data,
+ SMBNTencrypt(pass, smb1cli_conn_server_challenge(cli->conn),
nt_response.data);
#endif
/* non encrypted password supplied. Ignore ntpass. */
return tevent_req_post(req, ev);
}
- if (!SMBencrypt(pass,cli->secblob.data,
+ if (!SMBencrypt(pass,
+ smb1cli_conn_server_challenge(cli->conn),
lm_response.data)) {
/*
* Oops, the LM response is
SMBsesskeygen_ntv1(nt_hash, session_key.data);
#endif
}
- cli_temp_set_signing(cli);
} else {
/* pre-encrypted password supplied. Only used for
security=server, can't do
SSVAL(vwv+1, 0, 0);
SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
SSVAL(vwv+3, 0, 2);
- SSVAL(vwv+4, 0, cli->pid);
- SIVAL(vwv+5, 0, cli->sesskey);
+ SSVAL(vwv+4, 0, cli_state_get_vc_num(cli));
+ SIVAL(vwv+5, 0, smb1cli_conn_server_session_key(cli->conn));
SSVAL(vwv+7, 0, lm_response.length);
SSVAL(vwv+8, 0, nt_response.length);
SSVAL(vwv+9, 0, 0);
SSVAL(vwv+10, 0, 0);
- SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
+ SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli, 0));
bytes = talloc_array(state, uint8_t,
lm_response.length + nt_response.length);
inbuf = (char *)in;
p = bytes;
- cli->vuid = SVAL(inbuf, smb_uid);
+ cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
status = smb_bytes_talloc_string(cli,
}
p += ret;
- if (strstr(cli->server_type, "Samba")) {
- cli->is_samba = True;
- }
-
status = cli_set_username(cli, state->user);
if (tevent_req_nterror(req, status)) {
return;
uint16_t vwv[12];
uint8_t *buf;
+ DATA_BLOB smb2_blob;
+ struct iovec *recv_iov;
+
NTSTATUS status;
char *inbuf;
DATA_BLOB ret_blob;
{
struct tevent_req *req, *subreq;
struct cli_sesssetup_blob_state *state;
+ uint32_t usable_space;
req = tevent_req_create(mem_ctx, &state,
struct cli_sesssetup_blob_state);
state->blob = blob;
state->cli = cli;
- if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ usable_space = UINT16_MAX;
+ } else {
+ usable_space = cli_state_available_size(cli,
+ BASE_SESSSETUP_BLOB_PACKET_SIZE);
+ }
+
+ if (usable_space == 0) {
DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
- "(was %u, need minimum %u)\n",
- (unsigned int)cli->max_xmit,
- BASE_SESSSETUP_BLOB_PACKET_SIZE));
+ "(not possible to send %u bytes)\n",
+ BASE_SESSSETUP_BLOB_PACKET_SIZE + 1));
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
- state->max_blob_size =
- MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
+ state->max_blob_size = MIN(usable_space, 0xFFFF);
if (!cli_sesssetup_blob_next(state, &subreq)) {
tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
struct tevent_req *subreq;
uint16_t thistime;
+ thistime = MIN(state->blob.length, state->max_blob_size);
+
+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
+
+ state->smb2_blob.data = state->blob.data;
+ state->smb2_blob.length = thistime;
+
+ state->blob.data += thistime;
+ state->blob.length -= thistime;
+
+ subreq = smb2cli_session_setup_send(state, state->ev,
+ state->cli->conn,
+ state->cli->timeout,
+ state->cli->smb2.session,
+ 0, /* in_flags */
+ SMB2_CAP_DFS, /* in_capabilities */
+ 0, /* in_channel */
+ 0, /* in_previous_session_id */
+ &state->smb2_blob);
+ if (subreq == NULL) {
+ return false;
+ }
+ *psubreq = subreq;
+ return true;
+ }
+
SCVAL(state->vwv+0, 0, 0xFF);
SCVAL(state->vwv+0, 1, 0);
SSVAL(state->vwv+1, 0, 0);
SSVAL(state->vwv+4, 0, 1);
SIVAL(state->vwv+5, 0, 0);
- thistime = MIN(state->blob.length, state->max_blob_size);
SSVAL(state->vwv+7, 0, thistime);
SSVAL(state->vwv+8, 0, 0);
SSVAL(state->vwv+9, 0, 0);
SIVAL(state->vwv+10, 0,
- cli_session_setup_capabilities(state->cli)
- | CAP_EXTENDED_SECURITY);
+ cli_session_setup_capabilities(state->cli, CAP_EXTENDED_SECURITY));
state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
thistime);
uint8_t *inbuf;
ssize_t ret;
- status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
- &num_bytes, &bytes);
+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
+ status = smb2cli_session_setup_recv(subreq, state,
+ &state->recv_iov,
+ &state->ret_blob);
+ } else {
+ status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
+ &num_bytes, &bytes);
+ TALLOC_FREE(state->buf);
+ }
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)
&& !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
}
state->status = status;
- TALLOC_FREE(state->buf);
+
+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
+ goto next;
+ }
state->inbuf = (char *)inbuf;
- cli->vuid = SVAL(state->inbuf, smb_uid);
+ cli_state_set_uid(state->cli, SVAL(inbuf, smb_uid));
cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
blob_length = SVAL(vwv+3, 0);
}
p += ret;
- if (strstr(cli->server_type, "Samba")) {
- cli->is_samba = True;
- }
-
+next:
if (state->blob.length != 0) {
/*
* More to send
*/
if (!cli_sesssetup_blob_next(state, &subreq)) {
- tevent_req_nomem(NULL, req);
+ tevent_req_oom(req);
return;
}
tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
DATA_BLOB *pblob,
- char **pinbuf)
+ char **pinbuf,
+ struct iovec **precv_iov)
{
struct cli_sesssetup_blob_state *state = tevent_req_data(
req, struct cli_sesssetup_blob_state);
NTSTATUS status;
char *inbuf;
+ struct iovec *recv_iov;
if (tevent_req_is_nterror(req, &status)) {
- state->cli->vuid = 0;
+ TALLOC_FREE(state->cli->smb2.session);
+ cli_state_set_uid(state->cli, UID_FIELD_INVALID);
return status;
}
inbuf = talloc_move(mem_ctx, &state->inbuf);
+ recv_iov = talloc_move(mem_ctx, &state->recv_iov);
if (pblob != NULL) {
*pblob = state->ret_blob;
}
if (pinbuf != NULL) {
*pinbuf = inbuf;
}
+ if (precv_iov != NULL) {
+ *precv_iov = recv_iov;
+ }
/* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
return state->status;
}
state->cli = cli;
state->ads_status = ADS_SUCCESS;
- cli_temp_set_signing(cli);
-
/*
* Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
* we have to acquire a ticket. To be fixed later :-)
state->negTokenTarg.length);
#endif
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ state->cli->smb2.session = smbXcli_session_create(cli,
+ cli->conn);
+ if (tevent_req_nomem(state->cli->smb2.session, req)) {
+ return tevent_req_post(req, ev);
+ }
+ }
+
subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
struct cli_session_setup_kerberos_state *state = tevent_req_data(
req, struct cli_session_setup_kerberos_state);
char *inbuf = NULL;
+ struct iovec *recv_iov = NULL;
NTSTATUS status;
- status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
+ status = cli_sesssetup_blob_recv(subreq, state,
+ NULL, &inbuf, &recv_iov);
+ TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(subreq);
tevent_req_nterror(req, status);
return;
}
cli_set_session_key(state->cli, state->session_key_krb5);
- if (cli_simple_set_signing(state->cli, state->session_key_krb5,
- data_blob_null)
- && !cli_check_sign_mac(state->cli, inbuf, 1)) {
- TALLOC_FREE(subreq);
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return;
+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
+ struct smbXcli_session *session = state->cli->smb2.session;
+ status = smb2cli_session_set_session_key(session,
+ state->session_key_krb5,
+ recv_iov);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ } else {
+ if (cli_simple_set_signing(state->cli, state->session_key_krb5,
+ data_blob_null)
+ && !cli_check_sign_mac(state->cli, inbuf, 1)) {
+ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
}
- TALLOC_FREE(subreq);
+
tevent_req_done(req);
}
talloc_set_destructor(
state, cli_session_setup_ntlmssp_state_destructor);
- cli_temp_set_signing(cli);
-
status = ntlmssp_client_start(state,
- global_myname(),
+ lp_netbios_name(),
lp_workgroup(),
lp_client_ntlmv2_auth(),
&state->ntlmssp_state);
state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
data_blob_free(&blob_out);
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ state->cli->smb2.session = smbXcli_session_create(cli,
+ cli->conn);
+ if (tevent_req_nomem(state->cli->smb2.session, req)) {
+ return tevent_req_post(req, ev);
+ }
+ }
+
subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
req, struct cli_session_setup_ntlmssp_state);
DATA_BLOB blob_in, msg_in, blob_out;
char *inbuf = NULL;
+ struct iovec *recv_iov = NULL;
bool parse_ret;
NTSTATUS status;
status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
- &inbuf);
+ &inbuf, &recv_iov);
TALLOC_FREE(subreq);
data_blob_free(&state->blob_out);
state->cli->server_domain = talloc_strdup(state->cli,
state->ntlmssp_state->server.netbios_domain);
if (state->cli->server_domain == NULL) {
- TALLOC_FREE(subreq);
tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
cli_set_session_key(
state->cli, state->ntlmssp_state->session_key);
- if (cli_simple_set_signing(
- state->cli, state->ntlmssp_state->session_key,
- data_blob_null)
- && !cli_check_sign_mac(state->cli, inbuf, 1)) {
- TALLOC_FREE(subreq);
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return;
+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
+ struct smbXcli_session *session = state->cli->smb2.session;
+
+ if (ntlmssp_is_anonymous(state->ntlmssp_state)) {
+ /*
+ * Windows server does not set the
+ * SMB2_SESSION_FLAG_IS_GUEST nor
+ * SMB2_SESSION_FLAG_IS_NULL flag.
+ *
+ * This fix makes sure we do not try
+ * to verify a signature on the final
+ * session setup response.
+ */
+ TALLOC_FREE(state->ntlmssp_state);
+ tevent_req_done(req);
+ return;
+ }
+
+ status = smb2cli_session_set_session_key(session,
+ state->ntlmssp_state->session_key,
+ recv_iov);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ } else {
+ if (cli_simple_set_signing(
+ state->cli, state->ntlmssp_state->session_key,
+ data_blob_null)
+ && !cli_check_sign_mac(state->cli, inbuf, 1)) {
+ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
}
- TALLOC_FREE(subreq);
TALLOC_FREE(state->ntlmssp_state);
tevent_req_done(req);
return;
if (!NT_STATUS_IS_OK(status)
&& !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- TALLOC_FREE(subreq);
TALLOC_FREE(state->ntlmssp_state);
tevent_req_nterror(req, status);
return;
}
state->blob_out = spnego_gen_auth(state, blob_out);
- TALLOC_FREE(subreq);
if (tevent_req_nomem(state->blob_out.data, req)) {
return;
}
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
- state->cli->vuid = 0;
+ cli_state_set_uid(state->cli, UID_FIELD_INVALID);
return status;
}
return NT_STATUS_OK;
dest_realm: The realm we're connecting to, if NULL we use our default realm.
****************************************************************************/
-ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
- const char *pass, const char *user_domain,
+static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli,
+ const char *user,
+ const char *pass,
+ const char *user_domain,
const char * dest_realm)
{
char *principal = NULL;
char *OIDs[ASN1_MAX_OIDS];
int i;
- DATA_BLOB blob;
+ const DATA_BLOB *server_blob;
+ DATA_BLOB blob = data_blob_null;
const char *p = NULL;
char *account = NULL;
NTSTATUS status;
- DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
+ server_blob = smbXcli_conn_server_gss_blob(cli->conn);
+ if (server_blob) {
+ blob = data_blob(server_blob->data, server_blob->length);
+ }
+
+ DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)blob.length));
/* the server might not even do spnego */
- if (cli->secblob.length <= 16) {
+ if (blob.length == 0) {
DEBUG(3,("server didn't supply a full spnego negprot\n"));
goto ntlmssp;
}
file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
#endif
- /* there is 16 bytes of GUID before the real spnego packet starts */
- blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
-
/* The server sent us the first part of the SPNEGO exchange in the
* negprot reply. It is WRONG to depend on the principal sent in the
* negprot reply, but right now we do it. If we don't receive one,
/* If password is set we reauthenticate to kerberos server
* and do not store results */
- if (cli->got_kerberos_mechanism && cli->use_kerberos) {
+ if (user && *user && cli->got_kerberos_mechanism && cli->use_kerberos) {
ADS_STATUS rc;
+ const char *remote_name = smbXcli_conn_remote_name(cli->conn);
if (pass && *pass) {
int ret;
}
if (principal == NULL &&
- !is_ipaddress(cli->desthost) &&
+ !is_ipaddress(remote_name) &&
!strequal(STAR_SMBSERVER,
- cli->desthost)) {
- char *realm = NULL;
- char *host = NULL;
+ remote_name)) {
DEBUG(3,("cli_session_setup_spnego: using target "
"hostname not SPNEGO principal\n"));
- host = strchr_m(cli->desthost, '.');
if (dest_realm) {
- realm = SMB_STRDUP(dest_realm);
- if (!realm) {
- return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ char *realm = strupper_talloc(talloc_tos(), dest_realm);
+ if (realm) {
+ principal = talloc_asprintf(talloc_tos(),
+ "cifs/%s@%s",
+ remote_name,
+ realm);
+ TALLOC_FREE(realm);
}
- strupper_m(realm);
} else {
- if (host) {
- /* DNS name. */
- realm = kerberos_get_realm_from_hostname(cli->desthost);
- } else {
- /* NetBIOS name - use our realm. */
- realm = kerberos_get_default_realm_from_ccache();
- }
- }
-
- if (realm == NULL || *realm == '\0') {
- realm = SMB_STRDUP(lp_realm());
- if (!realm) {
- return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- }
- strupper_m(realm);
- DEBUG(3,("cli_session_setup_spnego: cannot "
- "get realm from dest_realm %s, "
- "desthost %s. Using default "
- "smb.conf realm %s\n",
- dest_realm ? dest_realm : "<null>",
- cli->desthost,
- realm));
+ principal = kerberos_get_principal_from_service_hostname(talloc_tos(),
+ "cifs",
+ remote_name,
+ lp_realm());
}
- principal = talloc_asprintf(talloc_tos(),
- "cifs/%s@%s",
- cli->desthost,
- realm);
if (!principal) {
- SAFE_FREE(realm);
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
DEBUG(3,("cli_session_setup_spnego: guessed "
"server principal=%s\n",
principal ? principal : "<null>"));
-
- SAFE_FREE(realm);
}
if (principal) {
{
char *p;
char *user2;
+ uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
if (user) {
user2 = talloc_strdup(talloc_tos(), user);
workgroup = user2;
}
- if (cli->protocol < PROTOCOL_LANMAN1) {
+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
return NT_STATUS_OK;
}
/* if its an older server then we have to use the older request format */
- if (cli->protocol < PROTOCOL_NT1) {
+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1) {
if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
" or 'client ntlmv2 auth = yes'\n"));
return NT_STATUS_ACCESS_DENIED;
}
- if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
+ if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
!lp_client_plaintext_auth() && (*pass)) {
DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
" or 'client ntlmv2 auth = yes'\n"));
workgroup);
}
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ const char *remote_realm = cli_state_remote_realm(cli);
+ ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
+ workgroup,
+ remote_realm);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(3, ("SMB2-SPNEGO login failed: %s\n", ads_errstr(status)));
+ return ads_ntstatus(status);
+ }
+ return NT_STATUS_OK;
+ }
+
/* if no user is supplied then we have to do an anonymous connection.
passwords are ignored */
password at this point. The password is sent in the tree
connect */
- if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
+ if ((sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
return cli_session_setup_plain(cli, user, "", workgroup);
/* if the server doesn't support encryption then we have to use
plaintext. The second password is ignored */
- if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
+ if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
if (!lp_client_plaintext_auth() && (*pass)) {
DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
" or 'client ntlmv2 auth = yes'\n"));
/* if the server supports extended security then use SPNEGO */
- if (cli->capabilities & CAP_EXTENDED_SECURITY) {
+ if (smb1cli_conn_capabilities(cli->conn) & CAP_EXTENDED_SECURITY) {
+ const char *remote_realm = cli_state_remote_realm(cli);
ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
- workgroup, NULL);
+ workgroup,
+ remote_realm);
if (!ADS_ERR_OK(status)) {
DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
return ads_ntstatus(status);
}
}
- if (strstr(cli->server_type, "Samba")) {
- cli->is_samba = True;
- }
-
return NT_STATUS_OK;
}
tevent_req_nterror(req, status);
return;
}
- state->cli->vuid = -1;
+ cli_state_set_uid(state->cli, UID_FIELD_INVALID);
tevent_req_done(req);
}
uint16_t *vwv;
char *tmp = NULL;
uint8_t *bytes;
+ uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
*psmbreq = NULL;
}
/* in user level security don't send a password now */
- if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
+ if (sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
passlen = 1;
pass = "";
} else if (pass == NULL) {
goto access_denied;
}
- if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
+ if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
*pass && passlen != 24) {
if (!lp_client_lanman_auth()) {
DEBUG(1, ("Server requested LANMAN password "
* Non-encrypted passwords - convert to DOS codepage before
* encryption.
*/
- SMBencrypt(pass, cli->secblob.data, p24);
+ SMBencrypt(pass, smb1cli_conn_server_challenge(cli->conn), p24);
passlen = 24;
pass = (const char *)p24;
} else {
- if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
+ if((sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
== 0) {
- char *tmp_pass;
+ uint8_t *tmp_pass;
if (!lp_client_plaintext_auth() && (*pass)) {
DEBUG(1, ("Server requested plaintext "
* Non-encrypted passwords - convert to DOS codepage
* before using.
*/
- tmp_pass = talloc_array(talloc_tos(), char, 128);
- if (tmp_pass == NULL) {
- tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ tmp_pass = talloc_array(talloc_tos(), uint8, 0);
+ if (tevent_req_nomem(tmp_pass, req)) {
return tevent_req_post(req, ev);
}
- passlen = clistr_push(cli,
- tmp_pass,
- pass,
- talloc_get_size(tmp_pass),
- STR_TERMINATE);
- if (passlen == -1) {
- tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ tmp_pass = trans2_bytes_push_str(tmp_pass,
+ false, /* always DOS */
+ pass,
+ passlen,
+ NULL);
+ if (tevent_req_nomem(tmp_pass, req)) {
return tevent_req_post(req, ev);
}
- pass = tmp_pass;
+ pass = (const char *)tmp_pass;
+ passlen = talloc_get_size(tmp_pass);
}
}
* Add the sharename
*/
tmp = talloc_asprintf_strupper_m(talloc_tos(), "\\\\%s\\%s",
- cli->desthost, share);
+ smbXcli_conn_remote_name(cli->conn), share);
if (tmp == NULL) {
TALLOC_FREE(req);
return NULL;
}
}
- if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
+ if ((smbXcli_conn_protocol(cli->conn) >= PROTOCOL_NT1) && (num_bytes == 3)) {
/* almost certainly win95 - enable bug fixes */
cli->win95 = True;
}
cli->dfsroot = false;
- if ((wct > 2) && (cli->protocol >= PROTOCOL_LANMAN2)) {
+ if ((wct > 2) && (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN2)) {
cli->dfsroot = ((SVAL(vwv+2, 0) & SMB_SHARE_IN_DFS) != 0);
}
- cli->cnum = SVAL(inbuf,smb_tid);
+ cli->smb1.tid = SVAL(inbuf,smb_tid);
tevent_req_done(req);
}
return status;
}
+NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share,
+ const char *dev, const char *pass, int passlen)
+{
+ cli->share = talloc_strdup(cli, share);
+ if (!cli->share) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
+ return smb2cli_tcon(cli, share);
+ }
+
+ return cli_tcon_andx(cli, share, dev, pass, passlen);
+}
+
/****************************************************************************
Send a tree disconnect.
****************************************************************************/
tevent_req_nterror(req, status);
return;
}
- state->cli->cnum = -1;
+ state->cli->smb1.tid = UINT16_MAX;
tevent_req_done(req);
}
return status;
}
-/****************************************************************************
- Send a negprot command.
-****************************************************************************/
-
-struct cli_negprot_state {
- struct cli_state *cli;
-};
-
-static void cli_negprot_done(struct tevent_req *subreq);
-
-struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx,
- struct event_context *ev,
- struct cli_state *cli)
-{
- struct tevent_req *req, *subreq;
- struct cli_negprot_state *state;
- uint8_t *bytes = NULL;
- int numprots;
- uint16_t cnum;
-
- req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state);
- if (req == NULL) {
- return NULL;
- }
- state->cli = cli;
-
- if (cli->protocol < PROTOCOL_NT1)
- cli->use_spnego = False;
-
- /* setup the protocol strings */
- for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
- uint8_t c = 2;
- if (prots[numprots].prot > cli->protocol) {
- break;
- }
- bytes = (uint8_t *)talloc_append_blob(
- state, bytes, data_blob_const(&c, sizeof(c)));
- if (tevent_req_nomem(bytes, req)) {
- return tevent_req_post(req, ev);
- }
- bytes = smb_bytes_push_str(bytes, false,
- prots[numprots].name,
- strlen(prots[numprots].name)+1,
- NULL);
- if (tevent_req_nomem(bytes, req)) {
- return tevent_req_post(req, ev);
- }
- }
-
- cnum = cli->cnum;
-
- cli->cnum = 0;
- subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL,
- talloc_get_size(bytes), bytes);
- cli->cnum = cnum;
-
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, cli_negprot_done, req);
- return req;
-}
-
-static void cli_negprot_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(
- subreq, struct tevent_req);
- struct cli_negprot_state *state = tevent_req_data(
- req, struct cli_negprot_state);
- struct cli_state *cli = state->cli;
- uint8_t wct;
- uint16_t *vwv;
- uint32_t num_bytes;
- uint8_t *bytes;
- NTSTATUS status;
- uint16_t protnum;
- uint8_t *inbuf;
-
- status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
- &num_bytes, &bytes);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- }
-
- protnum = SVAL(vwv, 0);
-
- if ((protnum >= ARRAY_SIZE(prots))
- || (prots[protnum].prot > cli->protocol)) {
- tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
- return;
- }
-
- cli->protocol = prots[protnum].prot;
-
- if ((cli->protocol < PROTOCOL_NT1) &&
- client_is_signing_mandatory(cli)) {
- DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
- if (cli->protocol >= PROTOCOL_NT1) {
- struct timespec ts;
- bool negotiated_smb_signing = false;
-
- /* NT protocol */
- cli->sec_mode = CVAL(vwv + 1, 0);
- cli->max_mux = SVAL(vwv + 1, 1);
- cli->max_xmit = IVAL(vwv + 3, 1);
- cli->sesskey = IVAL(vwv + 7, 1);
- cli->serverzone = SVALS(vwv + 15, 1);
- cli->serverzone *= 60;
- /* this time arrives in real GMT */
- ts = interpret_long_date(((char *)(vwv+11))+1);
- cli->servertime = ts.tv_sec;
- cli->secblob = data_blob(bytes, num_bytes);
- cli->capabilities = IVAL(vwv + 9, 1);
- if (cli->capabilities & CAP_RAW_MODE) {
- cli->readbraw_supported = True;
- cli->writebraw_supported = True;
- }
- /* work out if they sent us a workgroup */
- if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
- smb_buflen(inbuf) > 8) {
- ssize_t ret;
- status = smb_bytes_talloc_string(
- cli, (char *)inbuf, &cli->server_domain,
- bytes + 8, num_bytes - 8, &ret);
- if (tevent_req_nterror(req, status)) {
- return;
- }
- }
-
- /*
- * As signing is slow we only turn it on if either the client or
- * the server require it. JRA.
- */
-
- if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
- /* Fail if server says signing is mandatory and we don't want to support it. */
- if (!client_is_signing_allowed(cli)) {
- DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
- tevent_req_nterror(req,
- NT_STATUS_ACCESS_DENIED);
- return;
- }
- negotiated_smb_signing = true;
- } else if (client_is_signing_mandatory(cli) && client_is_signing_allowed(cli)) {
- /* Fail if client says signing is mandatory and the server doesn't support it. */
- if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
- DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
- tevent_req_nterror(req,
- NT_STATUS_ACCESS_DENIED);
- return;
- }
- negotiated_smb_signing = true;
- } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
- negotiated_smb_signing = true;
- }
-
- if (negotiated_smb_signing) {
- cli_set_signing_negotiated(cli);
- }
-
- if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
- SAFE_FREE(cli->outbuf);
- SAFE_FREE(cli->inbuf);
- cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
- cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
- if (!cli->outbuf || !cli->inbuf) {
- tevent_req_nterror(req,
- NT_STATUS_NO_MEMORY);
- return;
- }
- cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
- }
-
- } else if (cli->protocol >= PROTOCOL_LANMAN1) {
- cli->use_spnego = False;
- cli->sec_mode = SVAL(vwv + 1, 0);
- cli->max_xmit = SVAL(vwv + 2, 0);
- cli->max_mux = SVAL(vwv + 3, 0);
- cli->sesskey = IVAL(vwv + 6, 0);
- cli->serverzone = SVALS(vwv + 10, 0);
- cli->serverzone *= 60;
- /* this time is converted to GMT by make_unix_date */
- cli->servertime = make_unix_date(
- (char *)(vwv + 8), cli->serverzone);
- cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
- cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
- cli->secblob = data_blob(bytes, num_bytes);
- } else {
- /* the old core protocol */
- cli->use_spnego = False;
- cli->sec_mode = 0;
- cli->serverzone = get_time_zone(time(NULL));
- }
-
- cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
-
- /* a way to force ascii SMB */
- if (getenv("CLI_FORCE_ASCII"))
- cli->capabilities &= ~CAP_UNICODE;
-
- tevent_req_done(req);
-}
-
-NTSTATUS cli_negprot_recv(struct tevent_req *req)
-{
- return tevent_req_simple_recv_ntstatus(req);
-}
-
-NTSTATUS cli_negprot(struct cli_state *cli)
-{
- TALLOC_CTX *frame = talloc_stackframe();
- struct event_context *ev;
- struct tevent_req *req;
- NTSTATUS status = NT_STATUS_OK;
-
- if (cli_has_async_calls(cli)) {
- /*
- * Can't use sync call while an async call is in flight
- */
- status = NT_STATUS_INVALID_PARAMETER;
- goto fail;
- }
-
- ev = event_context_init(frame);
- if (ev == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
-
- req = cli_negprot_send(frame, ev, cli);
- if (req == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
-
- if (!tevent_req_poll(req, ev)) {
- status = map_nt_error_from_unix(errno);
- goto fail;
- }
-
- status = cli_negprot_recv(req);
- fail:
- TALLOC_FREE(frame);
- return status;
-}
-
-/****************************************************************************
- Send a session request. See rfc1002.txt 4.3 and 4.3.2.
-****************************************************************************/
-
-bool cli_session_request(struct cli_state *cli,
- struct nmb_name *calling, struct nmb_name *called)
-{
- TALLOC_CTX *frame;
- uint8_t len_buf[4];
- struct iovec iov[3];
- ssize_t len;
- uint8_t *inbuf;
- int err;
- bool ret = false;
-
- /* 445 doesn't have session request */
- if (cli->port == 445)
- return True;
-
- memcpy(&(cli->calling), calling, sizeof(*calling));
- memcpy(&(cli->called ), called , sizeof(*called ));
-
- /* put in the destination name */
-
- frame = talloc_stackframe();
-
- iov[0].iov_base = len_buf;
- iov[0].iov_len = sizeof(len_buf);
-
- /* put in the destination name */
-
- iov[1].iov_base = name_mangle(talloc_tos(), called->name,
- called->name_type);
- if (iov[1].iov_base == NULL) {
- goto fail;
- }
- iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
- talloc_get_size(iov[1].iov_base));
-
- /* and my name */
-
- iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
- calling->name_type);
- if (iov[2].iov_base == NULL) {
- goto fail;
- }
- iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
- talloc_get_size(iov[2].iov_base));
-
- /* send a session request (RFC 1002) */
- /* setup the packet length
- * Remove four bytes from the length count, since the length
- * field in the NBT Session Service header counts the number
- * of bytes which follow. The cli_send_smb() function knows
- * about this and accounts for those four bytes.
- * CRH.
- */
-
- _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
- SCVAL(len_buf,0,0x81);
-
- len = write_data_iov(cli->fd, iov, 3);
- if (len == -1) {
- goto fail;
- }
- len = read_smb(cli->fd, talloc_tos(), &inbuf, &err);
- if (len == -1) {
- errno = err;
- goto fail;
- }
-
- if (CVAL(inbuf,0) == 0x84) {
- /* C. Hoch 9/14/95 Start */
- /* For information, here is the response structure.
- * We do the byte-twiddling to for portability.
- struct RetargetResponse{
- unsigned char type;
- unsigned char flags;
- int16 length;
- int32 ip_addr;
- int16 port;
- };
- */
- uint16_t port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
- struct in_addr dest_ip;
- NTSTATUS status;
-
- /* SESSION RETARGET */
- putip((char *)&dest_ip,inbuf+4);
- in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
-
- status = open_socket_out(&cli->dest_ss, port,
- LONG_CONNECT_TIMEOUT, &cli->fd);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- DEBUG(3,("Retargeted\n"));
-
- set_socket_options(cli->fd, lp_socket_options());
-
- /* Try again */
- {
- static int depth;
- if (depth > 4) {
- DEBUG(0,("Retarget recursion - failing\n"));
- goto fail;
- }
- depth++;
- ret = cli_session_request(cli, calling, called);
- depth--;
- goto done;
- }
- } /* C. Hoch 9/14/95 End */
-
- if (CVAL(inbuf,0) != 0x82) {
- /* This is the wrong place to put the error... JRA. */
- cli->rap_error = CVAL(inbuf,4);
- goto fail;
- }
-done:
- ret = true;
-fail:
- err = errno;
- TALLOC_FREE(frame);
- errno = err;
- return ret;
-}
-
-struct fd_struct {
- int fd;
-};
-
-static void smb_sock_connected(struct tevent_req *req)
-{
- struct fd_struct *pfd = tevent_req_callback_data(
- req, struct fd_struct);
- int fd;
- NTSTATUS status;
-
- status = open_socket_out_defer_recv(req, &fd);
- if (NT_STATUS_IS_OK(status)) {
- pfd->fd = fd;
- }
-}
-
-static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
- uint16_t *port, int timeout, int *pfd)
-{
- struct event_context *ev;
- struct tevent_req *r139, *r445;
- struct fd_struct *fd139, *fd445;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
-
- if (*port != 0) {
- return open_socket_out(pss, *port, timeout, pfd);
- }
-
- ev = event_context_init(talloc_tos());
- if (ev == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- fd139 = talloc(ev, struct fd_struct);
- if (fd139 == NULL) {
- goto done;
- }
- fd139->fd = -1;
-
- fd445 = talloc(ev, struct fd_struct);
- if (fd445 == NULL) {
- goto done;
- }
- fd445->fd = -1;
-
- r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
- pss, 445, timeout);
- r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
- pss, 139, timeout);
- if ((r445 == NULL) || (r139 == NULL)) {
- goto done;
- }
- tevent_req_set_callback(r445, smb_sock_connected, fd445);
- tevent_req_set_callback(r139, smb_sock_connected, fd139);
-
- while ((fd445->fd == -1) && (fd139->fd == -1)
- && (tevent_req_is_in_progress(r139)
- || tevent_req_is_in_progress(r445))) {
- event_loop_once(ev);
- }
-
- if ((fd139->fd != -1) && (fd445->fd != -1)) {
- close(fd139->fd);
- fd139->fd = -1;
- }
-
- if (fd445->fd != -1) {
- *port = 445;
- *pfd = fd445->fd;
- status = NT_STATUS_OK;
- goto done;
- }
- if (fd139->fd != -1) {
- *port = 139;
- *pfd = fd139->fd;
- status = NT_STATUS_OK;
- goto done;
- }
-
- status = open_socket_out_defer_recv(r445, &fd445->fd);
- done:
- TALLOC_FREE(ev);
- return status;
-}
-
-/****************************************************************************
- Open the client sockets.
-****************************************************************************/
-
-NTSTATUS cli_connect(struct cli_state *cli,
- const char *host,
- struct sockaddr_storage *dest_ss)
-
-{
- int name_type = 0x20;
- TALLOC_CTX *frame = talloc_stackframe();
- unsigned int num_addrs = 0;
- unsigned int i = 0;
- struct sockaddr_storage *ss_arr = NULL;
- char *p = NULL;
-
- /* reasonable default hostname */
- if (!host) {
- host = STAR_SMBSERVER;
- }
-
- cli->desthost = talloc_strdup(cli, host);
- if (cli->desthost == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* allow hostnames of the form NAME#xx and do a netbios lookup */
- if ((p = strchr(cli->desthost, '#'))) {
- name_type = strtol(p+1, NULL, 16);
- *p = 0;
- }
-
- if (!dest_ss || is_zero_addr(dest_ss)) {
- NTSTATUS status =resolve_name_list(frame,
- cli->desthost,
- name_type,
- &ss_arr,
- &num_addrs);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(frame);
- return NT_STATUS_BAD_NETWORK_NAME;
- }
- } else {
- num_addrs = 1;
- ss_arr = TALLOC_P(frame, struct sockaddr_storage);
- if (!ss_arr) {
- TALLOC_FREE(frame);
- return NT_STATUS_NO_MEMORY;
- }
- *ss_arr = *dest_ss;
- }
-
- for (i = 0; i < num_addrs; i++) {
- cli->dest_ss = ss_arr[i];
- if (getenv("LIBSMB_PROG")) {
- cli->fd = sock_exec(getenv("LIBSMB_PROG"));
- } else {
- uint16_t port = cli->port;
- NTSTATUS status;
- status = open_smb_socket(&cli->dest_ss, &port,
- cli->timeout, &cli->fd);
- if (NT_STATUS_IS_OK(status)) {
- cli->port = port;
- }
- }
- if (cli->fd == -1) {
- char addr[INET6_ADDRSTRLEN];
- print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
- DEBUG(2,("Error connecting to %s (%s)\n",
- dest_ss?addr:host,strerror(errno)));
- } else {
- /* Exit from loop on first connection. */
- break;
- }
- }
-
- if (cli->fd == -1) {
- TALLOC_FREE(frame);
- return map_nt_error_from_unix(errno);
- }
-
- if (dest_ss) {
- *dest_ss = cli->dest_ss;
- }
-
- set_socket_options(cli->fd, lp_socket_options());
-
- TALLOC_FREE(frame);
- return NT_STATUS_OK;
-}
-
static NTSTATUS cli_connect_sock(const char *host, int name_type,
const struct sockaddr_storage *pss,
const char *myname, uint16_t port,
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+ set_socket_options(fd, lp_socket_options());
done:
*pfd = fd;
*pport = port;
return status;
}
-NTSTATUS cli_connect_nb(const char *host, struct sockaddr_storage *pss,
+NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss,
uint16_t port, int name_type, const char *myname,
- int signing_state, struct cli_state **pcli)
+ int signing_state, int flags, struct cli_state **pcli)
{
TALLOC_CTX *frame = talloc_stackframe();
struct cli_state *cli;
int fd = -1;
char *desthost;
char *p;
- socklen_t length;
- int ret;
desthost = talloc_strdup(talloc_tos(), host);
if (desthost == NULL) {
}
}
- cli = cli_initialise_ex(signing_state);
- if (cli == NULL) {
- goto fail;
- }
- cli->desthost = talloc_move(cli, &desthost);
-
- status = cli_connect_sock(host, name_type, pss, myname, port, 20, &fd,
- &port);
+ status = cli_connect_sock(host, name_type, dest_ss, myname, port,
+ 20, &fd, &port);
if (!NT_STATUS_IS_OK(status)) {
- cli_shutdown(cli);
goto fail;
}
- cli->fd = fd;
- cli->port = port;
- length = sizeof(cli->dest_ss);
- ret = getpeername(fd, (struct sockaddr *)(void *)&cli->dest_ss,
- &length);
- if (ret == -1) {
- status = map_nt_error_from_unix(errno);
- cli_shutdown(cli);
+ cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags);
+ if (cli == NULL) {
+ close(fd);
+ fd = -1;
goto fail;
}
- if (pss != NULL) {
- *pss = cli->dest_ss;
- }
-
*pcli = cli;
status = NT_STATUS_OK;
fail:
NTSTATUS cli_start_connection(struct cli_state **output_cli,
const char *my_name,
const char *dest_host,
- struct sockaddr_storage *dest_ss, int port,
+ const struct sockaddr_storage *dest_ss, int port,
int signing_state, int flags)
{
NTSTATUS nt_status;
struct cli_state *cli;
nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
- signing_state, &cli);
+ signing_state, flags, &cli);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(10, ("cli_connect_nb failed: %s\n",
nt_errstr(nt_status)));
return nt_status;
}
- if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
- cli->use_spnego = False;
- else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
- cli->use_kerberos = True;
-
- if ((flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) &&
- cli->use_kerberos) {
- cli->fallback_after_kerberos = true;
- }
- if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
- cli->use_ccache = true;
- }
-
- nt_status = cli_negprot(cli);
+ nt_status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
+ PROTOCOL_NT1);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
cli_shutdown(cli);
NTSTATUS cli_full_connection(struct cli_state **output_cli,
const char *my_name,
const char *dest_host,
- struct sockaddr_storage *dest_ss, int port,
+ const struct sockaddr_storage *dest_ss, int port,
const char *service, const char *service_type,
const char *user, const char *domain,
const char *password, int flags,
return nt_status;
}
- cli->use_oplocks = ((flags & CLI_FULL_CONNECTION_OPLOCKS) != 0);
- cli->use_level_II_oplocks =
- ((flags & CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS) != 0);
-
nt_status = cli_session_setup(cli, user, password, pw_len, password,
pw_len, domain);
if (!NT_STATUS_IS_OK(nt_status)) {
return NT_STATUS_OK;
}
-/****************************************************************************
- Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
-****************************************************************************/
-
-bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
- struct sockaddr_storage *pdest_ss)
-{
- struct nmb_name calling, called;
-
- make_nmb_name(&calling, srchost, 0x0);
-
- /*
- * If the called name is an IP address
- * then use *SMBSERVER immediately.
- */
-
- if(is_ipaddress(desthost)) {
- make_nmb_name(&called, STAR_SMBSERVER, 0x20);
- } else {
- make_nmb_name(&called, desthost, 0x20);
- }
-
- if (!cli_session_request(*ppcli, &calling, &called)) {
- NTSTATUS status;
- struct nmb_name smbservername;
-
- make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
-
- /*
- * If the name wasn't *SMBSERVER then
- * try with *SMBSERVER if the first name fails.
- */
-
- if (nmb_name_equal(&called, &smbservername)) {
-
- /*
- * The name used was *SMBSERVER, don't bother with another name.
- */
-
- DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
-with error %s.\n", desthost, cli_errstr(*ppcli) ));
- return False;
- }
-
- /* Try again... */
- cli_shutdown(*ppcli);
-
- *ppcli = cli_initialise();
- if (!*ppcli) {
- /* Out of memory... */
- return False;
- }
-
- status = cli_connect(*ppcli, desthost, pdest_ss);
- if (!NT_STATUS_IS_OK(status) ||
- !cli_session_request(*ppcli, &calling, &smbservername)) {
- DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
-name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
- return False;
- }
- }
-
- return True;
-}
-
/****************************************************************************
Send an old style tcon.
****************************************************************************/
lp_workgroup(),
user_info->password ? user_info->password : "",
flags,
- Undefined);
+ SMB_SIGNING_DEFAULT);
if (NT_STATUS_IS_OK(nt_status)) {
return cli;
if (!NT_STATUS_IS_OK(status)) {
DEBUG(99, ("No master browsers responded: %s\n",
nt_errstr(status)));
- return False;
+ return NULL;
}
for (i = 0; i < count; i++) {