p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
}
- else {
+ else {
+ /* For ucs2 passwords clistr_push calls ucs2_align, which causes
+ * the space taken by the unicode password to be one byte too
+ * long (as we're on an odd byte boundary here). Reduce the
+ * count by 1 to cope with this. Fixes smbclient against NetApp
+ * servers which can't cope. Fix from
+ * bryan.kolodziej@allenlund.com in bug #3840.
+ */
p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
- SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf)));
+ SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
}
p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
if (cli_is_error(cli) &&
!NT_STATUS_EQUAL( cli_get_nt_error(cli),
NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(0, ("cli_session_setup_blob: recieve failed (%s)\n",
- nt_errstr(cli_get_nt_error(cli)) ));
+ DEBUG(0, ("cli_session_setup_blob: receive failed "
+ "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
cli->vuid = 0;
return False;
}
if (!cli_session_setup_blob(cli, negTokenTarg, session_key_krb5)) {
data_blob_free(&negTokenTarg);
data_blob_free(&session_key_krb5);
- ADS_ERROR_NT(cli_nt_error(cli));
+ return ADS_ERROR_NT(cli_nt_error(cli));
}
cli_set_session_key(cli, session_key_krb5);
/* 'resign' the last message, so we get the right sequence numbers
for checking the first reply from the server */
- cli_calculate_sign_mac(cli);
+ cli_calculate_sign_mac(cli, cli->outbuf);
- if (!cli_check_sign_mac(cli)) {
+ if (!cli_check_sign_mac(cli, cli->inbuf)) {
nt_status = NT_STATUS_ACCESS_DENIED;
}
}
/****************************************************************************
Do a spnego encrypted session setup.
+
+ user_domain: The shortname of the domain the user/machine is a member of.
+ 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 *domain)
+ const char *pass, const char *user_domain,
+ const char * dest_realm)
{
- char *principal;
+ char *principal = NULL;
char *OIDs[ASN1_MAX_OIDS];
int i;
- bool got_kerberos_mechanism = False;
DATA_BLOB blob;
+ const char *p = NULL;
+ char *account = NULL;
DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
/* 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 */
+ /* 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. */
if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
data_blob_free(&blob);
return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
DEBUG(3,("got OID=%s\n", OIDs[i]));
if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
strcmp(OIDs[i], OID_KERBEROS5) == 0) {
- got_kerberos_mechanism = True;
+ cli->got_kerberos_mechanism = True;
}
- free(OIDs[i]);
+ talloc_free(OIDs[i]);
}
DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
- if (got_kerberos_mechanism && (principal == NULL)) {
- /*
- * It is WRONG to depend on the principal sent in the negprot
- * reply, but right now we do it. So for safety (don't
- * segfault later) disable Kerberos when no principal was
- * sent. -- VL
- */
- DEBUG(1, ("Kerberos mech was offered, but no principal was "
- "sent, disabling Kerberos\n"));
- cli->use_kerberos = False;
- }
-
fstrcpy(cli->user_name, user);
#ifdef HAVE_KRB5
/* If password is set we reauthenticate to kerberos server
* and do not store results */
- if (got_kerberos_mechanism && cli->use_kerberos) {
+ if (cli->got_kerberos_mechanism && cli->use_kerberos) {
ADS_STATUS rc;
if (pass && *pass) {
ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
if (ret){
- SAFE_FREE(principal);
+ TALLOC_FREE(principal);
DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
if (cli->fallback_after_kerberos)
goto ntlmssp;
we have a valid host NetBIOS name.
*/
if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
- SAFE_FREE(principal);
+ TALLOC_FREE(principal);
}
if (principal == NULL &&
DEBUG(3,("cli_session_setup_spnego: got a "
"bad server principal, trying to guess ...\n"));
- host = strchr(cli->desthost, '.');
+ host = strchr_m(cli->desthost, '.');
if (host) {
machine = SMB_STRNDUP(cli->desthost,
host - cli->desthost);
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
- realm = kerberos_get_default_realm_from_ccache();
+ if (dest_realm) {
+ realm = SMB_STRDUP(dest_realm);
+ strupper_m(realm);
+ } else {
+ realm = kerberos_get_default_realm_from_ccache();
+ }
if (realm && *realm) {
- if (asprintf(&principal, "%s$@%s",
- machine, realm) < 0) {
+ principal = talloc_asprintf(NULL, "%s$@%s",
+ machine, realm);
+ if (!principal) {
+ SAFE_FREE(machine);
SAFE_FREE(realm);
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
}
if (principal) {
- rc = cli_session_setup_kerberos(cli, principal, domain);
+ rc = cli_session_setup_kerberos(cli, principal,
+ dest_realm);
if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
- SAFE_FREE(principal);
+ TALLOC_FREE(principal);
return rc;
}
}
}
#endif
- SAFE_FREE(principal);
+ TALLOC_FREE(principal);
ntlmssp:
- return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain));
+ account = talloc_strdup(talloc_tos(), user);
+ if (!account) {
+ return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ /* when falling back to ntlmssp while authenticating with a machine
+ * account strip off the realm - gd */
+
+ if ((p = strchr_m(user, '@')) != NULL) {
+ account[PTR_DIFF(p,user)] = '\0';
+ }
+
+ return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, account, pass, user_domain));
}
/****************************************************************************
/* if the server supports extended security then use SPNEGO */
if (cli->capabilities & CAP_EXTENDED_SECURITY) {
- ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
+ ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
+ workgroup, NULL);
if (!ADS_ERR_OK(status)) {
DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
return ads_ntstatus(status);
}
return NT_STATUS_OK;
-
}
/****************************************************************************
if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
*pass && passlen != 24) {
if (!lp_client_lanman_auth()) {
- DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
- " is disabled\n"));
+ DEBUG(1, ("Server requested LANMAN password "
+ "(share-level security) but "
+ "'client lanman auth' is disabled\n"));
return False;
}
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+SAFETY_MARGIN);
- cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+SAFETY_MARGIN);
- cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE;
+ 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);
+ cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
}
} else if (cli->protocol >= PROTOCOL_LANMAN1) {
*p = 0;
}
- if (!dest_ss || is_zero_addr(dest_ss)) {
+ if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
NTSTATUS status =resolve_name_list(frame,
cli->desthost,
name_type,
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 (!cli_negprot(cli)) {
DEBUG(1,("failed negprot\n"));
nt_status = cli_nt_error(cli);
{
struct cli_state *cli;
NTSTATUS nt_status;
+ uint32_t flags = CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
+
+ if (user_info->use_kerberos) {
+ flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
+ }
nt_status = cli_full_connection(&cli, NULL, server, server_ss, 0, "IPC$", "IPC",
user_info->username ? user_info->username : "",
lp_workgroup(),
user_info->password ? user_info->password : "",
- CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK, Undefined, NULL);
+ flags,
+ Undefined, NULL);
if (NT_STATUS_IS_OK(nt_status)) {
return cli;