-/*
+/*
Unix SMB/CIFS implementation.
client connect/disconnect routines
Copyright (C) Andrew Tridgell 1994-1998
#include "includes.h"
#include "libsmb/libsmb.h"
-#include "auth_info.h"
+#include "libsmb/namequery.h"
#include "../libcli/auth/libcli_auth.h"
-#include "../libcli/auth/spnego.h"
#include "smb_krb5.h"
#include "auth/credentials/credentials.h"
#include "auth/gensec/gensec.h"
#include "../libcli/smb/smbXcli_base.h"
#include "../libcli/smb/smb_seal.h"
#include "lib/param/param.h"
+#include "../libcli/smb/smb2_negotiate_context.h"
#define STAR_SMBSERVER "*SMBSERVER"
if (lp_ctx == NULL) {
goto fail;
}
- cli_credentials_set_conf(creds, lp_ctx);
+ ok = cli_credentials_set_conf(creds, lp_ctx);
+ if (!ok) {
+ goto fail;
+ }
if (username == NULL) {
username = "";
if (use_kerberos && fallback_after_kerberos) {
cli_credentials_set_kerberos_state(creds,
- CRED_AUTO_USE_KERBEROS);
+ CRED_USE_KERBEROS_DESIRED,
+ CRED_SPECIFIED);
} else if (use_kerberos) {
cli_credentials_set_kerberos_state(creds,
- CRED_MUST_USE_KERBEROS);
+ CRED_USE_KERBEROS_REQUIRED,
+ CRED_SPECIFIED);
} else {
cli_credentials_set_kerberos_state(creds,
- CRED_DONT_USE_KERBEROS);
+ CRED_USE_KERBEROS_DISABLED,
+ CRED_SPECIFIED);
}
if (use_ccache) {
features = cli_credentials_get_gensec_features(creds);
features |= GENSEC_FEATURE_NTLM_CCACHE;
- cli_credentials_set_gensec_features(creds, features);
+ cli_credentials_set_gensec_features(creds,
+ features,
+ CRED_SPECIFIED);
if (password != NULL && strlen(password) == 0) {
/*
const char *user_account = NULL;
const char *user_domain = NULL;
const char *pass = NULL;
+ char *canon_principal = NULL;
+ char *canon_realm = NULL;
const char *target_hostname = NULL;
- const DATA_BLOB *server_blob = NULL;
enum credentials_use_kerberos krb5_state;
bool try_kerberos = false;
bool need_kinit = false;
bool auth_requested = true;
int ret;
+ bool ok;
target_hostname = smbXcli_conn_remote_name(cli->conn);
- if (!cli->got_kerberos_mechanism) {
- server_blob = smbXcli_conn_server_gss_blob(cli->conn);
- }
-
- /* the server might not even do spnego */
- if (server_blob != NULL && server_blob->length != 0) {
- char *OIDs[ASN1_MAX_OIDS] = { NULL, };
- size_t i;
- bool ok;
-
- /*
- * 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,
- * we try to best guess, then fall back to NTLM.
- */
- ok = spnego_parse_negTokenInit(frame,
- *server_blob,
- OIDs,
- NULL,
- NULL);
- if (!ok) {
- TALLOC_FREE(frame);
- return NT_STATUS_INVALID_PARAMETER;
- }
- if (OIDs[0] == NULL) {
- TALLOC_FREE(frame);
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* make sure the server understands kerberos */
- for (i = 0; OIDs[i] != NULL; i++) {
- if (i == 0) {
- DEBUG(3,("got OID=%s\n", OIDs[i]));
- } else {
- DEBUGADD(3,("got OID=%s\n", OIDs[i]));
- }
-
- if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
- strcmp(OIDs[i], OID_KERBEROS5) == 0) {
- cli->got_kerberos_mechanism = true;
- break;
- }
- }
- }
auth_requested = cli_credentials_authentication_requested(creds);
if (auth_requested) {
+ errno = 0;
user_principal = cli_credentials_get_principal(creds, frame);
- if (user_principal == NULL) {
+ if (errno != 0) {
TALLOC_FREE(frame);
return NT_STATUS_NO_MEMORY;
}
krb5_state = cli_credentials_get_kerberos_state(creds);
- if (krb5_state != CRED_DONT_USE_KERBEROS) {
+ if (krb5_state != CRED_USE_KERBEROS_DISABLED) {
try_kerberos = true;
}
+ if (user_principal == NULL) {
+ try_kerberos = false;
+ }
+
if (target_hostname == NULL) {
try_kerberos = false;
} else if (is_ipaddress(target_hostname)) {
try_kerberos = false;
}
- if (krb5_state == CRED_MUST_USE_KERBEROS && !try_kerberos) {
+ if (krb5_state == CRED_USE_KERBEROS_REQUIRED && !try_kerberos) {
DEBUG(0, ("Kerberos auth with '%s' (%s\\%s) to access "
"'%s' not possible\n",
user_principal, user_domain, user_account,
if (pass == NULL || strlen(pass) == 0) {
need_kinit = false;
- } else if (krb5_state == CRED_MUST_USE_KERBEROS) {
+ } else if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
need_kinit = try_kerberos;
- } else if (!cli->got_kerberos_mechanism) {
- /*
- * Most likely the server doesn't support
- * Kerberos, don't waste time doing a kinit
- */
- need_kinit = false;
} else {
need_kinit = try_kerberos;
}
return NT_STATUS_OK;
}
+ DBG_INFO("Doing kinit for %s to access %s\n",
+ user_principal, target_hostname);
/*
* TODO: This should be done within the gensec layer
* only if required!
*/
setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
- ret = kerberos_kinit_password(user_principal, pass,
- 0 /* no time correction for now */,
- NULL);
+ ret = kerberos_kinit_password_ext(user_principal,
+ pass,
+ 0,
+ 0,
+ 0,
+ NULL,
+ false,
+ false,
+ 0,
+ frame,
+ &canon_principal,
+ &canon_realm,
+ NULL);
if (ret != 0) {
- DEBUG(0, ("Kinit for %s to access %s failed: %s\n",
- user_principal, target_hostname,
- error_message(ret)));
- if (krb5_state == CRED_MUST_USE_KERBEROS) {
+ int dbglvl = DBGLVL_NOTICE;
+
+ if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
+ dbglvl = DBGLVL_ERR;
+ }
+
+ DEBUG(dbglvl, ("Kinit for %s to access %s failed: %s\n",
+ user_principal, target_hostname,
+ error_message(ret)));
+ if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
TALLOC_FREE(frame);
return krb5_to_nt_status(ret);
}
/*
* Ignore the error and hope that NTLM will work
*/
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
}
+ ok = cli_credentials_set_principal(creds,
+ canon_principal,
+ CRED_SPECIFIED);
+ if (!ok) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ok = cli_credentials_set_realm(creds,
+ canon_realm,
+ CRED_SPECIFIED);
+ if (!ok) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ DBG_DEBUG("Successfully authenticated as %s (%s) to access %s using "
+ "Kerberos\n",
+ user_principal,
+ canon_principal,
+ target_hostname);
+
TALLOC_FREE(frame);
return NT_STATUS_OK;
}
+static NTSTATUS cli_state_update_after_sesssetup(struct cli_state *cli,
+ const char *native_os,
+ const char *native_lm,
+ const char *primary_domain)
+{
+#define _VALID_STR(p) ((p) != NULL && (p)[0] != '\0')
+
+ if (!_VALID_STR(cli->server_os) && _VALID_STR(native_os)) {
+ cli->server_os = talloc_strdup(cli, native_os);
+ if (cli->server_os == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ if (!_VALID_STR(cli->server_type) && _VALID_STR(native_lm)) {
+ cli->server_type = talloc_strdup(cli, native_lm);
+ if (cli->server_type == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ if (!_VALID_STR(cli->server_domain) && _VALID_STR(primary_domain)) {
+ cli->server_domain = talloc_strdup(cli, primary_domain);
+ if (cli->server_domain == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+#undef _VALID_STRING
+ return NT_STATUS_OK;
+}
+
/********************************************************
Utility function to ensure we always return at least
a valid char * pointer to an empty string for the
size_t srclen,
ssize_t *destlen)
{
- *destlen = clistr_pull_talloc(mem_ctx,
- (const char *)hdr,
- SVAL(hdr, HDR_FLG2),
- dest,
- (char *)src,
- srclen,
- STR_TERMINATE);
+ *destlen = pull_string_talloc(mem_ctx,
+ (const char *)hdr,
+ SVAL(hdr, HDR_FLG2),
+ dest,
+ (char *)src,
+ srclen,
+ STR_TERMINATE);
if (*destlen == -1) {
return NT_STATUS_NO_MEMORY;
}
tevent_req_nterror(req, status);
return;
}
- p += ret;
tevent_req_done(req);
}
subreq, struct tevent_req);
struct cli_sesssetup_blob_state *state = tevent_req_data(
req, struct cli_sesssetup_blob_state);
- struct cli_state *cli = state->cli;
NTSTATUS status;
if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
return;
}
- if (cli->server_os == NULL) {
- cli->server_os = talloc_move(cli, &state->out_native_os);
- }
- if (cli->server_type == NULL) {
- cli->server_type = talloc_move(cli, &state->out_native_lm);
- }
-
state->status = status;
+ status = cli_state_update_after_sesssetup(state->cli,
+ state->out_native_os,
+ state->out_native_lm,
+ NULL);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
if (state->blob.length != 0) {
/*
* More to send
* We can't finish the gensec handshake, we don't
* have a negotiated session key.
*
- * So just pretend we are completely done.
+ * So just pretend we are completely done,
+ * we need to continue as anonymous from this point,
+ * as we can't get a session key.
*
* Note that smbXcli_session_is_guest()
* always returns false if we require signing.
*/
state->blob_in = data_blob_null;
state->local_ready = true;
+ state->is_anonymous = true;
}
state->remote_ready = true;
cli_session_setup_gensec_local_next(req);
}
+static void cli_session_dump_keys(TALLOC_CTX *mem_ctx,
+ struct smbXcli_session *session,
+ DATA_BLOB session_key)
+{
+ NTSTATUS status;
+ DATA_BLOB sig = data_blob_null;
+ DATA_BLOB app = data_blob_null;
+ DATA_BLOB enc = data_blob_null;
+ DATA_BLOB dec = data_blob_null;
+ uint64_t sid = smb2cli_session_current_id(session);
+
+ status = smb2cli_session_signing_key(session, mem_ctx, &sig);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+ status = smbXcli_session_application_key(session, mem_ctx, &app);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+ status = smb2cli_session_encryption_key(session, mem_ctx, &enc);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+ status = smb2cli_session_decryption_key(session, mem_ctx, &dec);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto out;
+ }
+
+ DEBUG(0, ("debug encryption: dumping generated session keys\n"));
+ DEBUGADD(0, ("Session Id "));
+ dump_data(0, (uint8_t*)&sid, sizeof(sid));
+ DEBUGADD(0, ("Session Key "));
+ dump_data(0, session_key.data, session_key.length);
+ DEBUGADD(0, ("Signing Key "));
+ dump_data(0, sig.data, sig.length);
+ DEBUGADD(0, ("App Key "));
+ dump_data(0, app.data, app.length);
+
+ /* In client code, ServerIn is the encryption key */
+
+ DEBUGADD(0, ("ServerIn Key "));
+ dump_data(0, enc.data, enc.length);
+ DEBUGADD(0, ("ServerOut Key "));
+ dump_data(0, dec.data, dec.length);
+
+out:
+ data_blob_clear_free(&sig);
+ data_blob_clear_free(&app);
+ data_blob_clear_free(&enc);
+ data_blob_clear_free(&dec);
+}
+
static void cli_session_setup_gensec_ready(struct tevent_req *req)
{
struct cli_session_setup_gensec_state *state =
if (tevent_req_nterror(req, status)) {
return;
}
+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB3_00
+ && lp_debug_encryption())
+ {
+ cli_session_dump_keys(state, session, state->session_key);
+ }
} else {
struct smbXcli_session *session = state->cli->smb1.session;
bool active;
status = cli_session_creds_prepare_krb5(cli, creds);
if (tevent_req_nterror(req, status)) {
- return tevent_req_post(req, ev);;
+ return tevent_req_post(req, ev);
}
+ DBG_INFO("Connect to %s as %s using SPNEGO\n",
+ target_hostname,
+ cli_credentials_get_principal(creds, talloc_tos()));
+
subreq = cli_session_setup_gensec_send(state, ev, cli, creds,
target_service, target_hostname);
if (tevent_req_nomem(subreq, req)) {
* We only call data_blob_clear() as
* some of the blobs point to the same memory.
*
- * We let the talloc hierachy free the memory.
+ * We let the talloc hierarchy free the memory.
*/
data_blob_clear(&state->apassword_blob);
data_blob_clear(&state->upassword_blob);
uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
bool use_spnego = false;
int flags = 0;
- enum credentials_use_kerberos krb5_state;
- uint32_t gensec_features;
const char *username = "";
const char *domain = "";
DATA_BLOB target_info = data_blob_null;
uint32_t in_sess_key = 0;
const char *in_native_os = NULL;
const char *in_native_lm = NULL;
+ enum credentials_use_kerberos krb5_state =
+ cli_credentials_get_kerberos_state(creds);
NTSTATUS status;
req = tevent_req_create(mem_ctx, &state,
tevent_req_set_cleanup_fn(req, cli_session_setup_creds_cleanup);
- krb5_state = cli_credentials_get_kerberos_state(creds);
- gensec_features = cli_credentials_get_gensec_features(creds);
-
- switch (krb5_state) {
- case CRED_MUST_USE_KERBEROS:
- cli->use_kerberos = true;
- cli->fallback_after_kerberos = false;
- break;
- case CRED_AUTO_USE_KERBEROS:
- cli->use_kerberos = true;
- cli->fallback_after_kerberos = true;
- break;
- case CRED_DONT_USE_KERBEROS:
- cli->use_kerberos = false;
- cli->fallback_after_kerberos = false;
- break;
- }
-
- if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
- cli->use_ccache = true;
- } else {
- cli->use_ccache = false;
- }
-
/*
* Now work out what sort of session setup we are going to
* do. I have split this into separate functions to make the flow a bit
return req;
}
+ if (krb5_state == CRED_USE_KERBEROS_REQUIRED) {
+ DBG_WARNING("Kerberos authentication requested, but "
+ "the server does not support SPNEGO authentication\n");
+ tevent_req_nterror(req, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT);
+ return tevent_req_post(req, ev);
+ }
+
if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_LANMAN1) {
/*
* SessionSetupAndX was introduced by LANMAN 1.0. So we skip
return tevent_req_post(req, ev);
}
+ DBG_INFO("Connect to %s as %s using NTLM\n", domain, username);
+
if ((sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
bool use_unicode = smbXcli_conn_use_unicode(cli->conn);
uint8_t *bytes = NULL;
&state->out_native_lm,
&state->out_primary_domain);
TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
+ if (tevent_req_nterror(req, status)) {
DEBUG(3, ("NT1 login failed: %s\n", nt_errstr(status)));
- tevent_req_nterror(req, status);
return;
}
- if (cli->server_os == NULL) {
- cli->server_os = talloc_move(cli, &state->out_native_os);
- }
- if (cli->server_type == NULL) {
- cli->server_type = talloc_move(cli, &state->out_native_lm);
- }
- if (cli->server_domain == NULL) {
- cli->server_domain = talloc_move(cli, &state->out_primary_domain);
+ status = cli_state_update_after_sesssetup(state->cli,
+ state->out_native_os,
+ state->out_native_lm,
+ state->out_primary_domain);
+ if (tevent_req_nterror(req, status)) {
+ return;
}
ok = smb1cli_conn_activate_signing(cli->conn,
subreq, struct tevent_req);
struct cli_session_setup_creds_state *state = tevent_req_data(
req, struct cli_session_setup_creds_state);
- struct cli_state *cli = state->cli;
NTSTATUS status;
status = smb1cli_session_setup_lm21_recv(subreq, state,
&state->out_native_os,
&state->out_native_lm);
TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
+ if (tevent_req_nterror(req, status)) {
DEBUG(3, ("LM21 login failed: %s\n", nt_errstr(status)));
- tevent_req_nterror(req, status);
return;
}
- if (cli->server_os == NULL) {
- cli->server_os = talloc_move(cli, &state->out_native_os);
- }
- if (cli->server_type == NULL) {
- cli->server_type = talloc_move(cli, &state->out_native_lm);
+ status = cli_state_update_after_sesssetup(state->cli,
+ state->out_native_os,
+ state->out_native_lm,
+ NULL);
+ if (tevent_req_nterror(req, status)) {
+ return;
}
tevent_req_done(req);
NTSTATUS cli_session_setup_anon(struct cli_state *cli)
{
- NTSTATUS status = NT_STATUS_NO_MEMORY;
+ NTSTATUS status;
struct cli_credentials *creds = NULL;
creds = cli_credentials_init_anon(cli);
NTSTATUS status;
status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
+ if (tevent_req_nterror(req, status)) {
return;
}
cli_state_set_uid(state->cli, UID_FIELD_INVALID);
state->cli = cli;
vwv = state->vwv;
+ TALLOC_FREE(cli->smb1.tcon);
+ cli->smb1.tcon = smbXcli_tcon_create(cli);
+ if (tevent_req_nomem(cli->smb1.tcon, req)) {
+ return tevent_req_post(req, ev);
+ }
+ smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
+
cli->share = talloc_strdup(cli, share);
if (!cli->share) {
return NULL;
return req;
}
status = smb1cli_req_chain_submit(&subreq, 1);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
+ if (tevent_req_nterror(req, status)) {
return tevent_req_post(req, ev);
}
return req;
status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
&num_bytes, &bytes);
TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
+ if (tevent_req_nterror(req, status)) {
return;
}
inhdr = in + NBT_HDR_SIZE;
if (num_bytes) {
- if (clistr_pull_talloc(cli,
- (const char *)inhdr,
- SVAL(inhdr, HDR_FLG2),
- &cli->dev,
- bytes,
- num_bytes,
- STR_TERMINATE|STR_ASCII) == -1) {
+ if (pull_string_talloc(cli,
+ (const char *)inhdr,
+ SVAL(inhdr, HDR_FLG2),
+ &cli->dev,
+ bytes,
+ num_bytes,
+ STR_TERMINATE|STR_ASCII) == -1) {
tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
char *unc;
+ TALLOC_FREE(cli->smb2.tcon);
cli->smb2.tcon = smbXcli_tcon_create(cli);
if (tevent_req_nomem(cli->smb2.tcon, req)) {
return tevent_req_post(req, ev);
static void cli_tree_connect_smb2_done(struct tevent_req *subreq)
{
- tevent_req_simple_finish_ntstatus(
- subreq, smb2cli_tcon_recv(subreq));
+ NTSTATUS status = smb2cli_tcon_recv(subreq);
+ tevent_req_simple_finish_ntstatus(subreq, status);
}
static void cli_tree_connect_andx_done(struct tevent_req *subreq)
{
- tevent_req_simple_finish_ntstatus(
- subreq, cli_tcon_andx_recv(subreq));
+ NTSTATUS status = cli_tcon_andx_recv(subreq);
+ tevent_req_simple_finish_ntstatus(subreq, status);
}
static void cli_tree_connect_raw_done(struct tevent_req *subreq)
const char *share, const char *dev,
struct cli_credentials *creds)
{
+ bool need_pass = false;
const char *pw = NULL;
- if (creds != NULL) {
+ /*
+ * We should work out if the protocol
+ * will make use of a password for share level
+ * authentication before we may cause
+ * the password prompt to be called.
+ */
+ if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
+ uint16_t sec_mode = smb1cli_conn_server_security_mode(cli->conn);
+
+ /* in user level security don't send a password now */
+ if (!(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
+ need_pass = true;
+ }
+ }
+
+ if (need_pass && creds != NULL) {
pw = cli_credentials_get_password(creds);
}
status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
+ if (tevent_req_nterror(req, status)) {
return;
}
- cli_state_set_tid(state->cli, UINT16_MAX);
+ TALLOC_FREE(state->cli->smb1.tcon);
tevent_req_done(req);
}
NTSTATUS status = NT_STATUS_NO_MEMORY;
if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
- return smb2cli_tdis(cli->conn,
+ status = smb2cli_tdis(cli->conn,
cli->timeout,
cli->smb2.session,
cli->smb2.tcon);
+ if (NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(cli->smb2.tcon);
+ }
+ return status;
}
if (smbXcli_conn_has_async_calls(cli->conn)) {
{
struct tevent_req *req, *subreq;
struct cli_connect_sock_state *state;
- const char *prog;
- struct sockaddr_storage *addrs;
- unsigned i, num_addrs;
+ struct sockaddr_storage *addrs = NULL;
+ unsigned i;
+ unsigned num_addrs = 0;
NTSTATUS status;
req = tevent_req_create(mem_ctx, &state,
return NULL;
}
- prog = getenv("LIBSMB_PROG");
- if (prog != NULL) {
- state->fd = sock_exec(prog);
- if (state->fd == -1) {
- status = map_nt_error_from_unix(errno);
- tevent_req_nterror(req, status);
- } else {
- state->port = 0;
- tevent_req_done(req);
- }
- return tevent_req_post(req, ev);
- }
-
if ((pss == NULL) || is_zero_addr(pss)) {
/*
status = resolve_name_list(state, host, name_type,
&addrs, &num_addrs);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
+ if (tevent_req_nterror(req, status)) {
return tevent_req_post(req, ev);
}
} else {
struct cli_connect_nb_state {
const char *desthost;
- int signing_state;
+ enum smb_signing_setting signing_state;
int flags;
struct cli_state *cli;
};
TALLOC_CTX *mem_ctx, struct tevent_context *ev,
const char *host, const struct sockaddr_storage *dest_ss,
uint16_t port, int name_type, const char *myname,
- int signing_state, int flags)
+ enum smb_signing_setting signing_state, int flags)
{
struct tevent_req *req, *subreq;
struct cli_connect_nb_state *state;
}
} else {
/* No host or dest_ss given. Error out. */
- tevent_req_error(req, EINVAL);
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
return tevent_req_post(req, ev);
}
return;
}
- state->cli = cli_state_create(state, fd, state->desthost, NULL,
+ state->cli = cli_state_create(state, fd, state->desthost,
state->signing_state, state->flags);
if (tevent_req_nomem(state->cli, req)) {
close(fd);
}
static NTSTATUS cli_connect_nb_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
struct cli_state **pcli)
{
struct cli_connect_nb_state *state = tevent_req_data(
if (tevent_req_is_nterror(req, &status)) {
return status;
}
- *pcli = talloc_move(NULL, &state->cli);
+ *pcli = talloc_move(mem_ctx, &state->cli);
return NT_STATUS_OK;
}
-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, int flags, struct cli_state **pcli)
+NTSTATUS cli_connect_nb(TALLOC_CTX *mem_ctx,
+ const char *host,
+ const struct sockaddr_storage *dest_ss,
+ uint16_t port,
+ int name_type,
+ const char *myname,
+ enum smb_signing_setting signing_state,
+ int flags,
+ struct cli_state **pcli)
{
struct tevent_context *ev;
struct tevent_req *req;
NTSTATUS status = NT_STATUS_NO_MEMORY;
- ev = samba_tevent_context_init(talloc_tos());
+ ev = samba_tevent_context_init(mem_ctx);
if (ev == NULL) {
goto fail;
}
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
goto fail;
}
- status = cli_connect_nb_recv(req, pcli);
+ status = cli_connect_nb_recv(req, mem_ctx, pcli);
fail:
TALLOC_FREE(ev);
return status;
struct cli_state *cli;
int min_protocol;
int max_protocol;
+ struct smb2_negotiate_contexts *negotiate_contexts;
};
static void cli_start_connection_connected(struct tevent_req *subreq);
static void cli_start_connection_done(struct tevent_req *subreq);
/**
- establishes a connection to after the negprot.
+ 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_ss (optional) The the destination IP, NULL for name based lookup
+ @param dest_ss (optional) The destination IP, NULL for name based lookup
@param port (optional) The destination port (0 for default)
*/
TALLOC_CTX *mem_ctx, struct tevent_context *ev,
const char *my_name, const char *dest_host,
const struct sockaddr_storage *dest_ss, int port,
- int signing_state, int flags)
+ enum smb_signing_setting signing_state, int flags,
+ struct smb2_negotiate_contexts *negotiate_contexts)
{
struct tevent_req *req, *subreq;
struct cli_start_connection_state *state;
}
state->ev = ev;
- if (signing_state == SMB_SIGNING_IPC_DEFAULT) {
+ if (flags & CLI_FULL_CONNECTION_IPC) {
state->min_protocol = lp_client_ipc_min_protocol();
state->max_protocol = lp_client_ipc_max_protocol();
} else {
state->max_protocol = lp_client_max_protocol();
}
+ if (flags & CLI_FULL_CONNECTION_FORCE_SMB1) {
+ state->max_protocol = MIN(state->max_protocol,
+ PROTOCOL_NT1);
+ state->min_protocol = MIN(state->min_protocol,
+ state->max_protocol);
+ }
+
+ if (flags & CLI_FULL_CONNECTION_DISABLE_SMB1) {
+ state->min_protocol = MAX(state->min_protocol,
+ PROTOCOL_SMB2_02);
+ state->max_protocol = MAX(state->max_protocol,
+ state->min_protocol);
+ }
+
+ state->negotiate_contexts = talloc_zero(
+ state, struct smb2_negotiate_contexts);
+ if (tevent_req_nomem(state->negotiate_contexts, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ if (flags & CLI_FULL_CONNECTION_REQUEST_POSIX) {
+ NTSTATUS status;
+
+ status = smb2_negotiate_context_add(
+ state->negotiate_contexts,
+ state->negotiate_contexts,
+ SMB2_POSIX_EXTENSIONS_AVAILABLE,
+ (const uint8_t *)SMB2_CREATE_TAG_POSIX,
+ strlen(SMB2_CREATE_TAG_POSIX));
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
+ }
+
+ if (negotiate_contexts != NULL) {
+ uint16_t i;
+
+ for (i=0; i<negotiate_contexts->num_contexts; i++) {
+ struct smb2_negotiate_context *ctx =
+ &negotiate_contexts->contexts[i];
+ NTSTATUS status;
+
+ status = smb2_negotiate_context_add(
+ state->negotiate_contexts,
+ state->negotiate_contexts,
+ ctx->type,
+ ctx->data.data,
+ ctx->data.length);
+ if (tevent_req_nterror(req, status)) {
+ return tevent_req_post(req, ev);
+ }
+ }
+ }
+
subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
0x20, my_name, signing_state, flags);
if (tevent_req_nomem(subreq, req)) {
req, struct cli_start_connection_state);
NTSTATUS status;
- status = cli_connect_nb_recv(subreq, &state->cli);
+ status = cli_connect_nb_recv(subreq, state, &state->cli);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
}
- subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
- state->cli->timeout,
- state->min_protocol,
- state->max_protocol);
+ subreq = smbXcli_negprot_send(
+ state,
+ state->ev,
+ state->cli->conn,
+ state->cli->timeout,
+ state->min_protocol,
+ state->max_protocol,
+ WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
+ state->negotiate_contexts);
if (tevent_req_nomem(subreq, req)) {
return;
}
req, struct cli_start_connection_state);
NTSTATUS status;
- status = smbXcli_negprot_recv(subreq);
+ status = smbXcli_negprot_recv(subreq, NULL, NULL);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
}
static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
struct cli_state **output_cli)
{
struct cli_start_connection_state *state = tevent_req_data(
if (tevent_req_is_nterror(req, &status)) {
return status;
}
- *output_cli = state->cli;
+ *output_cli = talloc_move(mem_ctx, &state->cli);
return NT_STATUS_OK;
}
-NTSTATUS cli_start_connection(struct cli_state **output_cli,
- const char *my_name,
- const char *dest_host,
+NTSTATUS cli_start_connection(TALLOC_CTX *mem_ctx,
+ struct cli_state **output_cli,
+ const char *my_name,
+ const char *dest_host,
const struct sockaddr_storage *dest_ss, int port,
- int signing_state, int flags)
+ enum smb_signing_setting signing_state, int flags)
{
struct tevent_context *ev;
struct tevent_req *req;
NTSTATUS status = NT_STATUS_NO_MEMORY;
- ev = samba_tevent_context_init(talloc_tos());
+ ev = samba_tevent_context_init(mem_ctx);
if (ev == NULL) {
goto fail;
}
req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
- port, signing_state, flags);
+ port, signing_state, flags, NULL);
if (req == NULL) {
goto fail;
}
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
goto fail;
}
- status = cli_start_connection_recv(req, output_cli);
+ status = cli_start_connection_recv(req, mem_ctx, output_cli);
fail:
TALLOC_FREE(ev);
return status;
@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 service_type The 'type' of service.
@param creds The used user credentials
*/
}
static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
-static void cli_full_connection_creds_sess_start(struct tevent_req *req);
static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
+static void cli_full_connection_creds_enc_start(struct tevent_req *req);
+static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
+static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
+static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
+static void cli_full_connection_creds_enc_tdis(struct tevent_req *req);
+static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq);
static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
const struct sockaddr_storage *dest_ss, int port,
const char *service, const char *service_type,
struct cli_credentials *creds,
- int flags, int signing_state)
+ int flags,
+ struct smb2_negotiate_contexts *negotiate_contexts)
{
struct tevent_req *req, *subreq;
struct cli_full_connection_creds_state *state;
- enum credentials_use_kerberos krb5_state;
- uint32_t gensec_features = 0;
+ enum smb_signing_setting signing_state;
+ enum smb_encryption_setting encryption_state =
+ cli_credentials_get_smb_encryption(creds);
req = tevent_req_create(mem_ctx, &state,
struct cli_full_connection_creds_state);
}
talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
- flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
- flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
- flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
- flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
-
- krb5_state = cli_credentials_get_kerberos_state(creds);
- switch (krb5_state) {
- case CRED_MUST_USE_KERBEROS:
- flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
- flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
- break;
- case CRED_AUTO_USE_KERBEROS:
- flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
- flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
- break;
- case CRED_DONT_USE_KERBEROS:
- break;
- }
-
- gensec_features = cli_credentials_get_gensec_features(creds);
- if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
- flags |= CLI_FULL_CONNECTION_USE_CCACHE;
- }
-
state->ev = ev;
state->service = service;
state->service_type = service_type;
state->creds = creds;
state->flags = flags;
+ if (flags & CLI_FULL_CONNECTION_IPC) {
+ signing_state = cli_credentials_get_smb_ipc_signing(creds);
+ } else {
+ signing_state = cli_credentials_get_smb_signing(creds);
+ }
+
+ if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
+ if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
+ encryption_state = SMB_ENCRYPTION_DESIRED;
+ }
+ }
+
+ if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
+ signing_state = SMB_SIGNING_REQUIRED;
+ }
+
subreq = cli_start_connection_send(
state, ev, my_name, dest_host, dest_ss, port,
- signing_state, flags);
+ signing_state, flags,
+ negotiate_contexts);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
req, struct cli_full_connection_creds_state);
NTSTATUS status;
- status = cli_start_connection_recv(subreq, &state->cli);
+ status = cli_start_connection_recv(subreq, state, &state->cli);
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
}
- cli_full_connection_creds_sess_start(req);
-}
-
-static void cli_full_connection_creds_sess_start(struct tevent_req *req)
-{
- struct cli_full_connection_creds_state *state = tevent_req_data(
- req, struct cli_full_connection_creds_state);
- struct tevent_req *subreq = NULL;
-
subreq = cli_session_setup_creds_send(
state, state->ev, state->cli, state->creds);
if (tevent_req_nomem(subreq, req)) {
return;
}
- cli_full_connection_creds_sess_start(req);
+ subreq = cli_session_setup_creds_send(
+ state, state->ev, state->cli, state->creds);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq,
+ cli_full_connection_creds_sess_done,
+ req);
+ return;
+ }
+
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ cli_full_connection_creds_enc_start(req);
+}
+
+static void cli_full_connection_creds_enc_start(struct tevent_req *req)
+{
+ struct cli_full_connection_creds_state *state = tevent_req_data(
+ req, struct cli_full_connection_creds_state);
+ enum smb_encryption_setting encryption_state =
+ cli_credentials_get_smb_encryption(state->creds);
+ struct tevent_req *subreq = NULL;
+ NTSTATUS status;
+
+ if (encryption_state < SMB_ENCRYPTION_DESIRED) {
+ cli_full_connection_creds_tcon_start(req);
+ return;
+ }
+
+ if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
+ status = smb2cli_session_encryption_on(state->cli->smb2.session);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
+ if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
+ cli_full_connection_creds_tcon_start(req);
+ return;
+ }
+ d_printf("Encryption required and "
+ "server doesn't support "
+ "SMB3 encryption - failing connect\n");
+ tevent_req_nterror(req, status);
+ return;
+ } else if (!NT_STATUS_IS_OK(status)) {
+ d_printf("Encryption required and "
+ "setup failed with error %s.\n",
+ nt_errstr(status));
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ cli_full_connection_creds_tcon_start(req);
+ return;
+ }
+
+ if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
+ if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
+ cli_full_connection_creds_tcon_start(req);
+ return;
+ }
+
+ status = NT_STATUS_NOT_SUPPORTED;
+ d_printf("Encryption required and "
+ "server doesn't support "
+ "SMB1 Unix Extensions - failing connect\n");
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ /*
+ * We do a tcon on IPC$ just to setup the encryption,
+ * the real tcon will be encrypted then.
+ */
+ subreq = cli_tree_connect_send(state, state->ev, state->cli,
+ "IPC$", "IPC", NULL);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
+}
+
+static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_full_connection_creds_state *state = tevent_req_data(
+ req, struct cli_full_connection_creds_state);
+ NTSTATUS status;
+
+ status = cli_tree_connect_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
+}
+
+static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_full_connection_creds_state *state = tevent_req_data(
+ req, struct cli_full_connection_creds_state);
+ enum smb_encryption_setting encryption_state =
+ cli_credentials_get_smb_encryption(state->creds);
+ uint16_t major, minor;
+ uint32_t caplow, caphigh;
+ NTSTATUS status;
+
+ status = cli_unix_extensions_version_recv(subreq,
+ &major, &minor,
+ &caplow,
+ &caphigh);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
+ /* disconnect ipc$ followed by the real tree connect */
+ cli_full_connection_creds_enc_tdis(req);
+ return;
+ }
+ DEBUG(10, ("%s: cli_unix_extensions_version "
+ "returned %s\n", __func__, nt_errstr(status)));
+ tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
+ return;
+ }
+
+ if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
+ if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
+ /* disconnect ipc$ followed by the real tree connect */
+ cli_full_connection_creds_enc_tdis(req);
+ return;
+ }
+ DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
+ "not supported\n", __func__));
+ tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
+ return;
+ }
+
+ subreq = cli_smb1_setup_encryption_send(state, state->ev,
+ state->cli,
+ state->creds);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq,
+ cli_full_connection_creds_enc_done,
+ req);
+}
+
+static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
+
+ status = cli_smb1_setup_encryption_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ /* disconnect ipc$ followed by the real tree connect */
+ cli_full_connection_creds_enc_tdis(req);
+}
+
+static void cli_full_connection_creds_enc_tdis(struct tevent_req *req)
+{
+ struct cli_full_connection_creds_state *state = tevent_req_data(
+ req, struct cli_full_connection_creds_state);
+ struct tevent_req *subreq = NULL;
+
+ subreq = cli_tdis_send(state, state->ev, state->cli);
+ if (tevent_req_nomem(subreq, req)) {
return;
}
+ tevent_req_set_callback(subreq,
+ cli_full_connection_creds_enc_finished,
+ req);
+}
+static void cli_full_connection_creds_enc_finished(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
+
+ status = cli_tdis_recv(subreq);
+ TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
}
}
NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
- struct cli_state **output_cli)
+ TALLOC_CTX *mem_ctx,
+ struct cli_state **output_cli)
{
struct cli_full_connection_creds_state *state = tevent_req_data(
req, struct cli_full_connection_creds_state);
if (tevent_req_is_nterror(req, &status)) {
return status;
}
- *output_cli = state->cli;
+ *output_cli = talloc_move(mem_ctx, &state->cli);
talloc_set_destructor(state, NULL);
return NT_STATUS_OK;
}
-NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
+NTSTATUS cli_full_connection_creds(TALLOC_CTX *mem_ctx,
+ struct cli_state **output_cli,
const char *my_name,
const char *dest_host,
const struct sockaddr_storage *dest_ss, int port,
const char *service, const char *service_type,
struct cli_credentials *creds,
- int flags,
- int signing_state)
+ int flags)
{
struct tevent_context *ev;
struct tevent_req *req;
NTSTATUS status = NT_STATUS_NO_MEMORY;
- ev = samba_tevent_context_init(talloc_tos());
+ ev = samba_tevent_context_init(mem_ctx);
if (ev == NULL) {
goto fail;
}
req = cli_full_connection_creds_send(
ev, ev, my_name, dest_host, dest_ss, port, service,
- service_type, creds, flags, signing_state);
+ service_type, creds, flags,
+ NULL);
if (req == NULL) {
goto fail;
}
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
goto fail;
}
- status = cli_full_connection_creds_recv(req, output_cli);
+ status = cli_full_connection_creds_recv(req, mem_ctx, output_cli);
fail:
TALLOC_FREE(ev);
return status;
}
-NTSTATUS cli_full_connection(struct cli_state **output_cli,
- const char *my_name,
- const char *dest_host,
- 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,
- int signing_state)
-{
- TALLOC_CTX *frame = talloc_stackframe();
- NTSTATUS status;
- bool use_kerberos = false;
- bool fallback_after_kerberos = false;
- bool use_ccache = false;
- bool pw_nt_hash = false;
- struct cli_credentials *creds = NULL;
-
- if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
- use_kerberos = true;
- }
-
- if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
- fallback_after_kerberos = true;
- }
-
- if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
- use_ccache = true;
- }
-
- if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
- pw_nt_hash = true;
- }
-
- creds = cli_session_creds_init(frame,
- user,
- domain,
- NULL, /* realm (use default) */
- password,
- use_kerberos,
- fallback_after_kerberos,
- use_ccache,
- pw_nt_hash);
- if (creds == NULL) {
- TALLOC_FREE(frame);
- return NT_STATUS_NO_MEMORY;
- }
-
- status = cli_full_connection_creds(output_cli, my_name,
- dest_host, dest_ss, port,
- service, service_type,
- creds, flags, signing_state);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(frame);
- return status;
- }
-
- TALLOC_FREE(frame);
- return NT_STATUS_OK;
-}
-
/****************************************************************************
Send an old style tcon.
****************************************************************************/
return tevent_req_post(req, ev);
}
+ TALLOC_FREE(cli->smb1.tcon);
+ cli->smb1.tcon = smbXcli_tcon_create(cli);
+ if (tevent_req_nomem(cli->smb1.tcon, req)) {
+ return tevent_req_post(req, ev);
+ }
+ smb1cli_tcon_set_id(cli->smb1.tcon, UINT16_MAX);
+
bytes = talloc_array(state, uint8_t, 0);
bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
/* Return a cli_state pointing at the IPC$ share for the given server */
-struct cli_state *get_ipc_connect(char *server,
- struct sockaddr_storage *server_ss,
- const struct user_auth_info *user_info)
+static struct cli_state *get_ipc_connect(TALLOC_CTX *mem_ctx,
+ char *server,
+ struct sockaddr_storage *server_ss,
+ struct cli_credentials *creds)
{
struct cli_state *cli;
NTSTATUS nt_status;
uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
- if (get_cmdline_auth_info_use_kerberos(user_info)) {
- flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
- }
+ flags |= CLI_FULL_CONNECTION_FORCE_SMB1;
+ flags |= CLI_FULL_CONNECTION_IPC;
- nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
- get_cmdline_auth_info_username(user_info),
- lp_workgroup(),
- get_cmdline_auth_info_password(user_info),
- flags,
- SMB_SIGNING_DEFAULT);
+ nt_status = cli_full_connection_creds(mem_ctx,
+ &cli,
+ NULL,
+ server,
+ server_ss,
+ 0,
+ "IPC$",
+ "IPC",
+ creds,
+ flags);
if (NT_STATUS_IS_OK(nt_status)) {
return cli;
- } else if (is_ipaddress(server)) {
+ }
+ if (is_ipaddress(server)) {
/* windows 9* needs a correct NMB name for connections */
fstring remote_name;
if (name_status_find("*", 0, 0, server_ss, remote_name)) {
- cli = get_ipc_connect(remote_name, server_ss, user_info);
+ cli = get_ipc_connect(mem_ctx, remote_name, server_ss, creds);
if (cli)
return cli;
}
struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
struct sockaddr_storage *mb_ip,
- const struct user_auth_info *user_info,
+ struct cli_credentials *creds,
char **pp_workgroup_out)
{
char addr[INET6_ADDRSTRLEN];
DEBUG(4, ("found master browser %s, %s\n", name, addr));
print_sockaddr(addr, sizeof(addr), &server_ss);
- cli = get_ipc_connect(addr, &server_ss, user_info);
+ cli = get_ipc_connect(ctx, addr, &server_ss, creds);
return cli;
}
-
-/*
- * Return the IP address and workgroup of a master browser on the network, and
- * connect to it.
- */
-
-struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
- const struct user_auth_info *user_info,
- char **pp_workgroup_out)
-{
- struct sockaddr_storage *ip_list;
- struct cli_state *cli;
- int i, count;
- NTSTATUS status;
-
- *pp_workgroup_out = NULL;
-
- DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
-
- /* Go looking for workgroups by broadcasting on the local network */
-
- status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
- &ip_list, &count);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(99, ("No master browsers responded: %s\n",
- nt_errstr(status)));
- return NULL;
- }
-
- for (i = 0; i < count; i++) {
- char addr[INET6_ADDRSTRLEN];
- print_sockaddr(addr, sizeof(addr), &ip_list[i]);
- DEBUG(99, ("Found master browser %s\n", addr));
-
- cli = get_ipc_connect_master_ip(ctx, &ip_list[i],
- user_info, pp_workgroup_out);
- if (cli)
- return(cli);
- }
-
- return NULL;
-}