*/
#include "includes.h"
+#include "popt_common.h"
#include "../libcli/auth/libcli_auth.h"
#include "../libcli/auth/spnego.h"
#include "smb_krb5.h"
-#include "ntlmssp.h"
+#include "../libcli/auth/ntlmssp.h"
+#include "libads/kerberos_proto.h"
+#include "krb5_env.h"
+#include "async_smb.h"
static const struct {
int prot;
cli_temp_set_signing(cli);
/*
- * Ok, this is cheated: spnego_gen_negTokenTarg can block if
+ * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
* we have to acquire a ticket. To be fixed later :-)
*/
- rc = spnego_gen_negTokenTarg(principal, 0, &state->negTokenTarg,
+ rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
&state->session_key_krb5, 0, NULL);
if (rc) {
DEBUG(1, ("cli_session_setup_kerberos: "
- "spnego_gen_negTokenTarg failed: %s\n",
+ "spnego_gen_krb5_negTokenInit failed: %s\n",
error_message(rc)));
state->ads_status = ADS_ERROR_KRB5(rc);
tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
struct cli_session_setup_ntlmssp_state *state)
{
if (state->ntlmssp_state != NULL) {
- ntlmssp_end(&state->ntlmssp_state);
+ TALLOC_FREE(state->ntlmssp_state);
}
return 0;
}
struct cli_session_setup_ntlmssp_state *state;
NTSTATUS status;
DATA_BLOB blob_out;
+ const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
req = tevent_req_create(mem_ctx, &state,
struct cli_session_setup_ntlmssp_state);
cli_temp_set_signing(cli);
- status = ntlmssp_client_start(&state->ntlmssp_state);
+ status = ntlmssp_client_start(state,
+ global_myname(),
+ lp_workgroup(),
+ lp_client_ntlmv2_auth(),
+ &state->ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
goto fail;
}
- state->blob_out = gen_negTokenInit(OID_NTLMSSP, blob_out);
+ state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
data_blob_free(&blob_out);
subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
if (NT_STATUS_IS_OK(status)) {
if (state->cli->server_domain[0] == '\0') {
fstrcpy(state->cli->server_domain,
- state->ntlmssp_state->server_domain);
+ state->ntlmssp_state->server.netbios_domain);
}
cli_set_session_key(
state->cli, state->ntlmssp_state->session_key);
return;
}
TALLOC_FREE(subreq);
- ntlmssp_end(&state->ntlmssp_state);
+ TALLOC_FREE(state->ntlmssp_state);
tevent_req_done(req);
return;
}
&& NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
DATA_BLOB tmp_blob = data_blob_null;
/* the server might give us back two challenges */
- parse_ret = spnego_parse_challenge(blob_in, &msg_in,
+ parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
&tmp_blob);
data_blob_free(&tmp_blob);
} else {
- parse_ret = spnego_parse_auth_response(blob_in, status,
+ parse_ret = spnego_parse_auth_response(state, blob_in, status,
OID_NTLMSSP, &msg_in);
}
state->turn += 1;
if (!NT_STATUS_IS_OK(status)
&& !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
TALLOC_FREE(subreq);
- ntlmssp_end(&state->ntlmssp_state);
+ TALLOC_FREE(state->ntlmssp_state);
tevent_req_nterror(req, status);
return;
}
- state->blob_out = spnego_gen_auth(blob_out);
+ state->blob_out = spnego_gen_auth(state, blob_out);
TALLOC_FREE(subreq);
if (tevent_req_nomem(state->blob_out.data, req)) {
return;
* 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. */
- if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
+ if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
+ OIDs[0] == NULL) {
data_blob_free(&blob);
return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
status = cli_set_username(cli, user);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(principal);
return ADS_ERROR_NT(status);
}
}
}
- /* If we get a bad principal, try to guess it if
- we have a valid host NetBIOS name.
+ /* We may not be allowed to use the server-supplied SPNEGO principal, or it may not have been supplied to us
*/
- if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
+ if (!lp_client_use_spnego_principal() || strequal(principal, ADS_IGNORE_PRINCIPAL)) {
TALLOC_FREE(principal);
}
!strequal(STAR_SMBSERVER,
cli->desthost)) {
char *realm = NULL;
- char *machine = NULL;
char *host = NULL;
- DEBUG(3,("cli_session_setup_spnego: got a "
- "bad server principal, trying to guess ...\n"));
+ DEBUG(3,("cli_session_setup_spnego: using target "
+ "hostname not SPNEGO principal\n"));
host = strchr_m(cli->desthost, '.');
- if (host) {
- /* We had a '.' in the name. */
- machine = SMB_STRNDUP(cli->desthost,
- host - cli->desthost);
- } else {
- machine = SMB_STRDUP(cli->desthost);
- }
- if (machine == NULL) {
- return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- }
-
if (dest_realm) {
realm = SMB_STRDUP(dest_realm);
strupper_m(realm);
}
if (realm && *realm) {
- if (host) {
- /* DNS name. */
- principal = talloc_asprintf(talloc_tos(),
- "cifs/%s@%s",
- cli->desthost,
- realm);
- } else {
- /* NetBIOS name, use machine account. */
- principal = talloc_asprintf(talloc_tos(),
- "%s$@%s",
- machine,
- realm);
- }
+ principal = talloc_asprintf(talloc_tos(),
+ "cifs/%s@%s",
+ cli->desthost,
+ realm);
if (!principal) {
- SAFE_FREE(machine);
SAFE_FREE(realm);
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
"server principal=%s\n",
principal ? principal : "<null>"));
}
- SAFE_FREE(machine);
SAFE_FREE(realm);
}
if (cli->protocol < PROTOCOL_NT1) {
if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
- DEBUG(1, ("Server requested LM password but 'client lanman auth'"
- " is disabled\n"));
+ 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 &&
!lp_client_plaintext_auth() && (*pass)) {
- DEBUG(1, ("Server requested plaintext password but "
- "'client plaintext auth' is disabled\n"));
+ DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
+ " or 'client ntlmv2 auth = yes'\n"));
return NT_STATUS_ACCESS_DENIED;
}
if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
if (!lp_client_plaintext_auth() && (*pass)) {
- DEBUG(1, ("Server requested plaintext password but "
- "'client plaintext auth' is disabled\n"));
+ DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
+ " or 'client ntlmv2 auth = yes'\n"));
return NT_STATUS_ACCESS_DENIED;
}
return cli_session_setup_plaintext(cli, user, pass, workgroup);
struct cli_ulogoff_state {
struct cli_state *cli;
- uint16_t vwv[2];
+ uint16_t vwv[3];
};
static void cli_ulogoff_done(struct tevent_req *subreq);
if (!lp_client_lanman_auth()) {
DEBUG(1, ("Server requested LANMAN password "
"(share-level security) but "
- "'client lanman auth' is disabled\n"));
+ "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
goto access_denied;
}
== 0) {
if (!lp_client_plaintext_auth() && (*pass)) {
DEBUG(1, ("Server requested plaintext "
- "password but 'client plaintext "
- "auth' is disabled\n"));
+ "password but "
+ "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
goto access_denied;
}
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;
}
cli->serverzone = SVALS(vwv + 10, 0);
cli->serverzone *= 60;
/* this time is converted to GMT by make_unix_date */
- cli->servertime = cli_make_unix_date(
- cli, (char *)(vwv + 8));
+ 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);
{
char *p;
int len = 4;
+ int namelen = 0;
char *tmp;
/* 445 doesn't have session request */
}
p = cli->outbuf+len;
- memcpy(p, tmp, name_len(tmp));
- len += name_len(tmp);
+ namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
+ if (namelen > 0) {
+ memcpy(p, tmp, namelen);
+ len += namelen;
+ }
TALLOC_FREE(tmp);
/* and my name */
}
p = cli->outbuf+len;
- memcpy(p, tmp, name_len(tmp));
- len += name_len(tmp);
+ namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
+ if (namelen > 0) {
+ memcpy(p, tmp, namelen);
+ len += namelen;
+ }
TALLOC_FREE(tmp);
/* send a session request (RFC 1002) */
@param user Username, unix string
@param domain User's domain
@param password User's password, unencrypted unix string.
- @param retry bool. Did this connection fail with a retryable error ?
*/
NTSTATUS cli_full_connection(struct cli_state **output_cli,
const char *service, const char *service_type,
const char *user, const char *domain,
const char *password, int flags,
- int signing_state,
- bool *retry)
+ int signing_state)
{
NTSTATUS nt_status;
struct cli_state *cli = NULL;
nt_status = cli_start_connection(&cli, my_name, dest_host,
dest_ss, port, signing_state,
- flags, retry);
+ flags, NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
lp_workgroup(),
user_info->password ? user_info->password : "",
flags,
- Undefined, NULL);
+ Undefined);
if (NT_STATUS_IS_OK(nt_status)) {
return cli;