summaryrefslogtreecommitdiff
path: root/source3/libsmb/cliconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb/cliconnect.c')
-rw-r--r--source3/libsmb/cliconnect.c313
1 files changed, 148 insertions, 165 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 487b184dd6..389b7a1733 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
client connect/disconnect routines
Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Andrew Barteltt 2001-2003
+ Copyright (C) Andrew Barteltt 2001-2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -45,7 +45,7 @@ static const struct {
****************************************************************************/
static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
- const char *pass, size_t passlen, const char *workgroup)
+ const char *pass, int passlen, const char *workgroup)
{
fstring pword;
char *p;
@@ -228,7 +228,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
return True;
}
-static void set_signing_on_cli (struct cli_state *cli, uint8 user_session_key[16], DATA_BLOB response)
+static void set_signing_on_cli (struct cli_state *cli, const char* pass, uint8 response[24])
{
uint8 zero_sig[8];
ZERO_STRUCT(zero_sig);
@@ -242,18 +242,12 @@ static void set_signing_on_cli (struct cli_state *cli, uint8 user_session_key[16
DEBUG(3, ("smb signing enabled!\n"));
cli->sign_info.use_smb_signing = True;
- cli_calculate_mac_key(cli, user_session_key, response);
+ cli_calculate_mac_key(cli, pass, response);
} else {
DEBUG(5, ("smb signing NOT enabled!\n"));
}
}
-static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key)
-{
- memcpy(cli->user_session_key, session_key.data, MIN(session_key.length, sizeof(cli->user_session_key)));
-}
-
-
static void set_temp_signing_on_cli(struct cli_state *cli)
{
if (cli->sign_info.negotiated_smb_signing)
@@ -271,54 +265,37 @@ static void set_temp_signing_on_cli(struct cli_state *cli)
****************************************************************************/
static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
- const char *pass, size_t passlen,
- const char *ntpass, size_t ntpasslen,
+ const char *pass, int passlen,
+ const char *ntpass, int ntpasslen,
const char *workgroup)
{
uint32 capabilities = cli_session_setup_capabilities(cli);
- DATA_BLOB lm_response = data_blob(NULL, 0);
- DATA_BLOB nt_response = data_blob(NULL, 0);
- DATA_BLOB session_key = data_blob(NULL, 0);
- BOOL ret = False;
+ uchar pword[24];
+ uchar ntpword[24];
char *p;
+ BOOL have_plaintext = False;
- if (passlen != 24) {
- if (lp_client_ntlmv2_auth()) {
- DATA_BLOB server_chal;
-
- server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
-
- if (!SMBNTLMv2encrypt(user, workgroup, pass, server_chal,
- &lm_response, &nt_response, &session_key)) {
- data_blob_free(&server_chal);
- return False;
- }
- data_blob_free(&server_chal);
-
- } else {
- uchar nt_hash[16];
- E_md4hash(pass, nt_hash);
-
- /* non encrypted password supplied. Ignore ntpass. */
- if (lp_client_lanman_auth()) {
- lm_response = data_blob(NULL, 24);
- SMBencrypt(pass,cli->secblob.data,lm_response.data);
- }
+ if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword))
+ return False;
- nt_response = data_blob(NULL, 24);
- SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
- session_key = data_blob(NULL, 16);
- SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
- }
+ if (passlen != 24) {
+ /* non encrypted password supplied. Ignore ntpass. */
+ passlen = 24;
+ ntpasslen = 24;
+ SMBencrypt(pass,cli->secblob.data,pword);
+ SMBNTencrypt(pass,cli->secblob.data,ntpword);
+ have_plaintext = True;
set_temp_signing_on_cli(cli);
} else {
/* pre-encrypted password supplied. Only used for
security=server, can't do
signing becouse we don't have oringial key */
-
- lm_response = data_blob(pass, passlen);
- nt_response = data_blob(ntpass, ntpasslen);
+ memcpy(pword, pass, 24);
+ if (ntpasslen == 24)
+ memcpy(ntpword, ntpass, 24);
+ else
+ ZERO_STRUCT(ntpword);
}
/* send a session setup command */
@@ -333,33 +310,28 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
SSVAL(cli->outbuf,smb_vwv3,2);
SSVAL(cli->outbuf,smb_vwv4,cli->pid);
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
- SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
- SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
+ SSVAL(cli->outbuf,smb_vwv7,passlen);
+ SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
SIVAL(cli->outbuf,smb_vwv11,capabilities);
p = smb_buf(cli->outbuf);
- if (lm_response.length) {
- memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
- }
- if (nt_response.length) {
- memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
- }
+ memcpy(p,pword,passlen); p += passlen;
+ memcpy(p,ntpword,ntpasslen); p += ntpasslen;
p += clistr_push(cli, p, user, -1, STR_TERMINATE);
p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
- if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
- ret = False;
- goto end;
- }
+ if (!cli_send_smb(cli))
+ return False;
+
+ if (!cli_receive_smb(cli))
+ return False;
show_msg(cli->inbuf);
- if (cli_is_error(cli)) {
- ret = False;
- goto end;
- }
+ if (cli_is_error(cli))
+ return False;
/* use the returned vuid from now on */
cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -371,16 +343,11 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
fstrcpy(cli->user_name, user);
- if (session_key.data) {
+ if (have_plaintext) {
/* Have plaintext orginal */
- set_cli_session_key(cli, session_key);
- set_signing_on_cli(cli, session_key.data, nt_response);
+ set_signing_on_cli(cli, pass, ntpword);
}
-
-end:
- data_blob_free(&lm_response);
- data_blob_free(&nt_response);
- data_blob_free(&session_key);
+
return True;
}
@@ -392,9 +359,11 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
{
uint32 capabilities = cli_session_setup_capabilities(cli);
char *p;
- DATA_BLOB blob2 = data_blob(NULL, 0);
+ DATA_BLOB blob2;
uint32 len;
+ blob2 = data_blob(NULL, 0);
+
capabilities |= CAP_EXTENDED_SECURITY;
/* send a session setup command */
@@ -451,13 +420,6 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
#ifdef HAVE_KRB5
/****************************************************************************
- Use in-memory credentials cache
-****************************************************************************/
-static void use_in_memory_ccache() {
- setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
-}
-
-/****************************************************************************
Do a spnego/kerberos encrypted session setup.
****************************************************************************/
@@ -494,87 +456,126 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *princi
static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
const char *pass, const char *workgroup)
{
- struct ntlmssp_client_state *ntlmssp_state;
- NTSTATUS nt_status;
- int turn = 1;
- DATA_BLOB msg1;
- DATA_BLOB blob;
- DATA_BLOB blob_in = data_blob(NULL, 0);
- DATA_BLOB blob_out;
+ DATA_BLOB msg1, struct_blob;
+ DATA_BLOB blob, chal1, chal2, auth, challenge_blob;
+ uint8 challenge[8];
+ uint8 nthash[24], lmhash[24], sess_key[16];
+ uint32 neg_flags, chal_flags, ntlmssp_command, unkn1, unkn2;
+ pstring server_domain; /* FIX THIS, SHOULD be UCS2-LE */
+
+ neg_flags = NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_128 |
+ NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_REQUEST_TARGET;
+
+ memset(sess_key, 0, 16);
+
+ DEBUG(10, ("sending NTLMSSP_NEGOTIATE\n"));
+
+ /* generate the ntlmssp negotiate packet */
+ msrpc_gen(&blob, "CddAA",
+ "NTLMSSP",
+ NTLMSSP_NEGOTIATE,
+ neg_flags,
+ workgroup,
+ cli->calling.name);
+ DEBUG(10, ("neg_flags: %0X, workgroup: %s, calling name %s\n",
+ neg_flags, workgroup, cli->calling.name));
+ /* and wrap it in a SPNEGO wrapper */
+ msg1 = gen_negTokenInit(OID_NTLMSSP, blob);
+ data_blob_free(&blob);
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
+ /* now send that blob on its way */
+ blob = cli_session_setup_blob(cli, msg1);
+
+ data_blob_free(&msg1);
+
+ if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED))
return False;
- }
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
+#if 0
+ file_save("chal.dat", blob.data, blob.length);
+#endif
+
+ /* the server gives us back two challenges */
+ if (!spnego_parse_challenge(blob, &chal1, &chal2)) {
+ DEBUG(3,("Failed to parse challenges\n"));
return False;
}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, workgroup))) {
- return False;
+
+ data_blob_free(&blob);
+
+ /*
+ * Ok, chal1 and chal2 are actually two identical copies of
+ * the NTLMSSP Challenge BLOB, and they contain, encoded in them
+ * the challenge to use.
+ */
+
+ if (!msrpc_parse(&chal1, "CdUdbddB",
+ "NTLMSSP",
+ &ntlmssp_command,
+ &server_domain,
+ &chal_flags,
+ &challenge_blob, 8,
+ &unkn1, &unkn2,
+ &struct_blob)) {
+ DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n"));
+ return False;
}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
+
+ if (ntlmssp_command != NTLMSSP_CHALLENGE) {
+ DEBUG(0, ("NTLMSSP Response != NTLMSSP_CHALLENGE. Got %0X\n",
+ ntlmssp_command));
return False;
}
+
+ DEBUG(10, ("Challenge:\n"));
+ dump_data(10, challenge_blob.data, 8);
- ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth();
-
- do {
- nt_status = ntlmssp_client_update(ntlmssp_state,
- blob_in, &blob_out);
- data_blob_free(&blob_in);
- if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- if (turn == 1) {
- /* and wrap it in a SPNEGO wrapper */
- msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
- } else {
- /* wrap it in SPNEGO */
- msg1 = spnego_gen_auth(blob_out);
- }
-
- /* now send that blob on its way */
- blob = cli_session_setup_blob(cli, msg1);
- data_blob_free(&msg1);
- nt_status = cli_nt_error(cli);
- }
-
- if (!blob.length) {
- if (NT_STATUS_IS_OK(nt_status)) {
- nt_status = NT_STATUS_UNSUCCESSFUL;
- }
- } else if ((turn == 1) &&
- NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DATA_BLOB tmp_blob = data_blob(NULL, 0);
- /* the server might give us back two challenges */
- if (!spnego_parse_challenge(blob, &blob_in,
- &tmp_blob)) {
- DEBUG(3,("Failed to parse challenges\n"));
- nt_status = NT_STATUS_INVALID_PARAMETER;
- }
- data_blob_free(&tmp_blob);
- } else {
- /* the server might give us back two challenges */
- if (!spnego_parse_auth_response(blob, nt_status,
- &blob_in)) {
- DEBUG(3,("Failed to parse auth response\n"));
- if (NT_STATUS_IS_OK(nt_status)
- || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
- nt_status = NT_STATUS_INVALID_PARAMETER;
- }
- }
- data_blob_free(&blob);
- data_blob_free(&blob_out);
- turn++;
- } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
+ /* encrypt the password with the challenge which is in the blob */
+ memcpy(challenge, challenge_blob.data, 8);
+ SMBencrypt(pass, challenge,lmhash);
+ SMBNTencrypt(pass, challenge,nthash);
+ data_blob_free(&challenge_blob);
- if (NT_STATUS_IS_OK(nt_status)) {
- set_cli_session_key(cli, ntlmssp_state->session_key);
- }
+#if 0
+ file_save("nthash.dat", nthash, 24);
+ file_save("lmhash.dat", lmhash, 24);
+ file_save("chal1.dat", chal1.data, chal1.length);
+#endif
+
+ data_blob_free(&chal1);
+ data_blob_free(&chal2);
+
+ /* this generates the actual auth packet */
+ msrpc_gen(&blob, "CdBBUUUBd",
+ "NTLMSSP",
+ NTLMSSP_AUTH,
+ lmhash, 24,
+ nthash, 24,
+ workgroup,
+ user,
+ cli->calling.name,
+ sess_key, 0,
+ neg_flags);
+
+ /* wrap it in SPNEGO */
+ auth = spnego_gen_auth(blob);
+
+ data_blob_free(&blob);
- if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) {
+ /* now send the auth packet and we should be done */
+ blob = cli_session_setup_blob(cli, auth);
+
+ data_blob_free(&auth);
+ data_blob_free(&blob);
+
+ if (cli_is_error(cli))
return False;
- }
- return (NT_STATUS_IS_OK(nt_status));
+ set_signing_on_cli(cli, pass, nthash);
+
+ return True;
}
/****************************************************************************
@@ -627,21 +628,6 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user,
fstrcpy(cli->user_name, user);
#ifdef HAVE_KRB5
- /* If password is set we reauthenticate to kerberos server
- * and do not store results */
-
- if (*pass) {
- int ret;
-
- use_in_memory_ccache();
- ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */);
-
- if (ret){
- DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
- return False;
- }
- }
-
if (got_kerberos_mechanism && cli->use_kerberos) {
return cli_session_setup_kerberos(cli, principal, workgroup);
}
@@ -956,10 +942,7 @@ BOOL cli_negprot(struct cli_state *cli)
smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
}
- if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED))
- cli->sign_info.negotiated_smb_signing = True;
-
- if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing)
+ if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
cli->sign_info.negotiated_smb_signing = True;
} else if (cli->protocol >= PROTOCOL_LANMAN1) {