summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cliconnect.c16
-rw-r--r--source3/libsmb/nterr.c1
-rw-r--r--source3/libsmb/ntlmssp.c8
-rw-r--r--source3/libsmb/smb_signing.c28
-rw-r--r--source3/libsmb/smbencrypt.c126
-rw-r--r--source3/libsmb/trusts_util.c2
6 files changed, 138 insertions, 43 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 4340503148..154a7cae58 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -257,14 +257,23 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
if (passlen != 24) {
if (lp_client_ntlmv2_auth()) {
DATA_BLOB server_chal;
-
+ DATA_BLOB names_blob;
server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
- if (!SMBNTLMv2encrypt(user, workgroup, pass, server_chal,
+ /* 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...
+ */
+ names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
+
+ if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
+ &names_blob,
&lm_response, &nt_response, &session_key)) {
+ data_blob_free(&names_blob);
data_blob_free(&server_chal);
return False;
}
+ data_blob_free(&names_blob);
data_blob_free(&server_chal);
} else {
@@ -810,9 +819,6 @@ BOOL cli_send_tconX(struct cli_state *cli,
clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
- if (strcasecmp(share,"IPC$")==0)
- fstrcpy(cli->dev, "IPC");
-
if (cli->protocol >= PROTOCOL_NT1 &&
smb_buflen(cli->inbuf) == 3) {
/* almost certainly win95 - enable bug fixes */
diff --git a/source3/libsmb/nterr.c b/source3/libsmb/nterr.c
index e6047847ae..166229ec6c 100644
--- a/source3/libsmb/nterr.c
+++ b/source3/libsmb/nterr.c
@@ -533,6 +533,7 @@ static nt_err_code_struct nt_errs[] =
{ "NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS },
{ "NT_STATUS_QUOTA_LIST_INCONSISTENT", NT_STATUS_QUOTA_LIST_INCONSISTENT },
{ "NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE },
+ { "NT_STATUS_NOT_A_REPARSE_POINT", NT_STATUS_NOT_A_REPARSE_POINT },
{ "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES },
{ "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES },
{ "STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED },
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
index d54655d17f..636e384e65 100644
--- a/source3/libsmb/ntlmssp.c
+++ b/source3/libsmb/ntlmssp.c
@@ -487,9 +487,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
}
SAFE_FREE(server_domain);
- data_blob_free(&struct_blob);
-
if (challenge_blob.length != 8) {
+ data_blob_free(&struct_blob);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -500,9 +499,11 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
if (!SMBNTLMv2encrypt(ntlmssp_state->user,
ntlmssp_state->domain,
- ntlmssp_state->password, challenge_blob,
+ ntlmssp_state->password, &challenge_blob,
+ &struct_blob,
&lm_response, &nt_response, &session_key)) {
data_blob_free(&challenge_blob);
+ data_blob_free(&struct_blob);
return NT_STATUS_NO_MEMORY;
}
} else {
@@ -522,6 +523,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st
session_key = data_blob(NULL, 16);
SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
}
+ data_blob_free(&struct_blob);
/* this generates the actual auth packet */
if (!msrpc_gen(next_request, auth_gen_string,
diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c
index 4e9b895a1b..eedf7f401f 100644
--- a/source3/libsmb/smb_signing.c
+++ b/source3/libsmb/smb_signing.c
@@ -111,6 +111,9 @@ static void cli_simple_sign_outgoing_message(struct cli_state *cli)
/*
* Firstly put the sequence number into the first 4 bytes.
* and zero out the next 4 bytes.
+ *
+ * We put the sequence into the packet, because we are going
+ * to copy over it anyway.
*/
SIVAL(cli->outbuf, smb_ss_field,
data->send_seq_num);
@@ -132,7 +135,7 @@ static void cli_simple_sign_outgoing_message(struct cli_state *cli)
memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
/* cli->outbuf[smb_ss_field+2]=0;
- Uncomment this to test if the remote server actually verifies signitures...*/
+ Uncomment this to test if the remote server actually verifies signatures...*/
data->send_seq_num++;
data->reply_seq_num = data->send_seq_num;
data->send_seq_num++;
@@ -155,6 +158,8 @@ static BOOL cli_simple_check_incoming_message(struct cli_state *cli)
/*
* Firstly put the sequence number into the first 4 bytes.
* and zero out the next 4 bytes.
+ *
+ * We do this here, to avoid modifying the packet.
*/
SIVAL(sequence_buf, 0, data->reply_seq_num);
@@ -163,15 +168,28 @@ static BOOL cli_simple_check_incoming_message(struct cli_state *cli)
/* get a copy of the server-sent mac */
memcpy(server_sent_mac, &cli->inbuf[smb_ss_field], sizeof(server_sent_mac));
- /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
+ /* Calculate the 16 byte MAC - but don't alter the data in the
+ incoming packet.
+
+ This makes for a bit for fussing about, but it's not too bad.
+ */
MD5Init(&md5_ctx);
+
+ /* intialise with the key */
MD5Update(&md5_ctx, data->mac_key.data,
data->mac_key.length);
+
+ /* copy in the first bit of the SMB header */
MD5Update(&md5_ctx, cli->inbuf + 4, smb_ss_field - 4);
+
+ /* copy in the sequence number, instead of the signature */
MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
-
+
+ /* copy in the rest of the packet in, skipping the signature */
MD5Update(&md5_ctx, cli->inbuf + offset_end_of_sig,
smb_len(cli->inbuf) - (offset_end_of_sig - 4));
+
+ /* caclulate the MD5 sig */
MD5Final(calc_md5_mac, &md5_ctx);
good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
@@ -219,10 +237,10 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
data = smb_xmalloc(sizeof(*data));
cli->sign_info.signing_context = data;
- data->mac_key = data_blob(NULL, MIN(response.length + 16, 40));
+ data->mac_key = data_blob(NULL, response.length + 16);
memcpy(&data->mac_key.data[0], user_session_key, 16);
- memcpy(&data->mac_key.data[16],response.data, MIN(response.length, 40 - 16));
+ memcpy(&data->mac_key.data[16],response.data, response.length);
/* Initialise the sequence number */
data->send_seq_num = 0;
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index 28160d9609..c1b3880299 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/libsmb/smbencrypt.c
@@ -76,10 +76,9 @@ void E_deshash(const char *passwd, uchar p16[16])
{
fstring dospwd;
ZERO_STRUCT(dospwd);
- ZERO_STRUCTP(p16);
/* Password must be converted to DOS charset - null terminated, uppercase. */
- push_ascii(dospwd, (const char *)passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE);
+ push_ascii(dospwd, passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE);
/* Only the fisrt 14 chars are considered, password need not be null terminated. */
E_P16(dospwd, p16);
@@ -250,21 +249,21 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[
/* Does the md5 encryption from the NT hash for NTLMv2. */
void SMBOWFencrypt_ntv2(const uchar kr[16],
- const DATA_BLOB srv_chal,
- const DATA_BLOB cli_chal,
+ const DATA_BLOB *srv_chal,
+ const DATA_BLOB *cli_chal,
uchar resp_buf[16])
{
HMACMD5Context ctx;
hmac_md5_init_limK_to_64(kr, 16, &ctx);
- hmac_md5_update(srv_chal.data, srv_chal.length, &ctx);
- hmac_md5_update(cli_chal.data, cli_chal.length, &ctx);
+ hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
+ hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
hmac_md5_final(resp_buf, &ctx);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
- dump_data(100, srv_chal.data, srv_chal.length);
- dump_data(100, cli_chal.data, cli_chal.length);
+ dump_data(100, srv_chal->data, srv_chal->length);
+ dump_data(100, cli_chal->data, cli_chal->length);
dump_data(100, resp_buf, 16);
#endif
}
@@ -295,36 +294,99 @@ void SMBsesskeygen_ntv1(const uchar kr[16],
#endif
}
-static DATA_BLOB NTLMv2_generate_response(uchar ntlm_v2_hash[16],
- DATA_BLOB server_chal, size_t client_chal_length)
+DATA_BLOB NTLMv2_generate_names_blob(const char *hostname,
+ const char *domain)
+{
+ DATA_BLOB names_blob = data_blob(NULL, 0);
+
+ msrpc_gen(&names_blob, "aaa",
+ True, NTLMSSP_NAME_TYPE_DOMAIN, domain,
+ True, NTLMSSP_NAME_TYPE_SERVER, hostname,
+ True, 0, "");
+ return names_blob;
+}
+
+static DATA_BLOB NTLMv2_generate_client_data(const DATA_BLOB *names_blob)
+{
+ uchar client_chal[8];
+ DATA_BLOB response = data_blob(NULL, 0);
+ char long_date[8];
+
+ generate_random_buffer(client_chal, sizeof(client_chal), False);
+
+ put_long_date(long_date, time(NULL));
+
+ /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */
+
+ msrpc_gen(&response, "ddbbdb",
+ 0x00000101, /* Header */
+ 0, /* 'Reserved' */
+ long_date, 8, /* Timestamp */
+ client_chal, 8, /* client challenge */
+ 0, /* Unknown */
+ names_blob->data, names_blob->length); /* End of name list */
+
+ return response;
+}
+
+static DATA_BLOB NTLMv2_generate_response(const uchar ntlm_v2_hash[16],
+ const DATA_BLOB *server_chal,
+ const DATA_BLOB *names_blob)
{
uchar ntlmv2_response[16];
DATA_BLOB ntlmv2_client_data;
DATA_BLOB final_response;
/* NTLMv2 */
+ /* generate some data to pass into the response function - including
+ the hostname and domain name of the server */
+ ntlmv2_client_data = NTLMv2_generate_client_data(names_blob);
- /* We also get to specify some random data */
- ntlmv2_client_data = data_blob(NULL, client_chal_length);
- generate_random_buffer(ntlmv2_client_data.data, ntlmv2_client_data.length, False);
-
/* Given that data, and the challenge from the server, generate a response */
- SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, ntlmv2_client_data, ntlmv2_response);
+ SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response);
- /* put it into nt_response, for the code below to put into the packet */
- final_response = data_blob(NULL, ntlmv2_client_data.length + sizeof(ntlmv2_response));
+ final_response = data_blob(NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length);
+
memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response));
- /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */
- memcpy(final_response.data + sizeof(ntlmv2_response), ntlmv2_client_data.data, ntlmv2_client_data.length);
+
+ memcpy(final_response.data+sizeof(ntlmv2_response),
+ ntlmv2_client_data.data, ntlmv2_client_data.length);
+
data_blob_free(&ntlmv2_client_data);
return final_response;
}
+static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16],
+ const DATA_BLOB *server_chal)
+{
+ uchar lmv2_response[16];
+ DATA_BLOB lmv2_client_data = data_blob(NULL, 8);
+ DATA_BLOB final_response = data_blob(NULL, 24);
+
+ /* LMv2 */
+ /* client-supplied random data */
+ generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length, False);
+
+ /* Given that data, and the challenge from the server, generate a response */
+ SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response);
+ memcpy(final_response.data, lmv2_response, sizeof(lmv2_response));
+
+ /* after the first 16 bytes is the random data we generated above,
+ so the server can verify us with it */
+ memcpy(final_response.data+sizeof(lmv2_response),
+ lmv2_client_data.data, lmv2_client_data.length);
+
+ data_blob_free(&lmv2_client_data);
+
+ return final_response;
+}
+
BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password,
- const DATA_BLOB server_chal,
+ const DATA_BLOB *server_chal,
+ const DATA_BLOB *names_blob,
DATA_BLOB *lm_response, DATA_BLOB *nt_response,
- DATA_BLOB *session_key)
+ DATA_BLOB *nt_session_key)
{
uchar nt_hash[16];
uchar ntlm_v2_hash[16];
@@ -338,18 +400,24 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
return False;
}
- *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, 64 /* pick a number, > 8 */);
+ if (nt_response) {
+ *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal,
+ names_blob);
+ if (nt_session_key) {
+ *nt_session_key = data_blob(NULL, 16);
+
+ /* The NTLMv2 calculations also provide a session key, for signing etc later */
+ /* use only the first 16 bytes of nt_response for session key */
+ SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, nt_session_key->data);
+ }
+ }
/* LMv2 */
- *lm_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, 8);
-
- *session_key = data_blob(NULL, 16);
+ if (lm_response) {
+ *lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal);
+ }
- /* The NTLMv2 calculations also provide a session key, for signing etc later */
- /* use only the first 16 bytes of nt_response for session key */
- SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, session_key->data);
-
return True;
}
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index d5a02bb625..6244c844f2 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -40,7 +40,7 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
result = cli_nt_setup_creds(cli, sec_channel_type, orig_trust_passwd_hash, &neg_flags, 2);
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(1,("just_change_the_password: unable to setup creds (%s)!\n",
+ DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
nt_errstr(result)));
return result;
}