summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/ntlmssp.h8
-rw-r--r--source3/libsmb/ntlmssp.c59
-rw-r--r--source3/libsmb/ntlmssp_sign.c57
-rw-r--r--source3/libsmb/pwd_cache.c10
-rw-r--r--source3/rpc_client/cli_pipe.c17
5 files changed, 109 insertions, 42 deletions
diff --git a/source3/include/ntlmssp.h b/source3/include/ntlmssp.h
index 681d4071db..24ac796761 100644
--- a/source3/include/ntlmssp.h
+++ b/source3/include/ntlmssp.h
@@ -147,10 +147,10 @@ typedef struct ntlmssp_state
uint32 ntlmssp_seq_num;
/* ntlmv2 */
- char send_sign_const[16];
- char send_seal_const[16];
- char recv_sign_const[16];
- char recv_seal_const[16];
+ unsigned char send_sign_const[16];
+ unsigned char send_seal_const[16];
+ unsigned char recv_sign_const[16];
+ unsigned char recv_seal_const[16];
unsigned char send_sign_hash[258];
unsigned char send_seal_hash[258];
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
index 7b821da0fd..40d7f41109 100644
--- a/source3/libsmb/ntlmssp.c
+++ b/source3/libsmb/ntlmssp.c
@@ -338,6 +338,10 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
}
+ if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) {
+ ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+ }
+
if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) {
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
}
@@ -577,6 +581,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
}
}
+ if (auth_flags)
+ ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth());
+
if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
SAFE_FREE(domain);
SAFE_FREE(user);
@@ -654,7 +661,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
/* Finally, actually ask if the password is OK */
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, &nt_session_key, &lm_session_key))) {
+ if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state,
+ &nt_session_key, &lm_session_key))) {
data_blob_free(&encrypted_session_key);
return nt_status;
}
@@ -670,24 +678,28 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
sizeof(session_nonce), session_key.data);
DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
-
- }else {
- data_blob_free(&encrypted_session_key);
+
+ } else {
DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
- return NT_STATUS_INVALID_PARAMETER;
+ session_key = data_blob(NULL, 0);
}
} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
- if (lm_session_key.data && lm_session_key.length >= 8 &&
- ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
- session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
- SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data,
- session_key.data);
- DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
- dump_data_pw("LM session key:\n", session_key.data, session_key.length);
+ if (lm_session_key.data && lm_session_key.length >= 8) {
+ if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
+ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
+ SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data,
+ session_key.data);
+ DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
+ dump_data_pw("LM session key:\n", session_key.data, session_key.length);
+ } else {
+ /* use the key unmodified - it's
+ * probably a NULL key from the guest
+ * login */
+ session_key = lm_session_key;
+ }
} else {
- data_blob_free(&encrypted_session_key);
DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
- return NT_STATUS_INVALID_PARAMETER;
+ session_key = data_blob(NULL, 0);
}
} else if (nt_session_key.data) {
session_key = nt_session_key;
@@ -698,9 +710,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
} else {
- data_blob_free(&encrypted_session_key);
DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
- return NT_STATUS_INVALID_PARAMETER;
+ session_key = data_blob(NULL, 0);
}
/* With KEY_EXCH, the client supplies the proposed session key,
@@ -714,6 +725,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
} else if (!session_key.data || session_key.length != 16) {
DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",
session_key.length));
+ ntlmssp_state->session_key = session_key;
} else {
dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
SamOEMhash(encrypted_session_key.data,
@@ -723,12 +735,18 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
encrypted_session_key.data,
encrypted_session_key.length);
dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data,
- encrypted_session_key.length);
+ encrypted_session_key.length);
}
} else {
ntlmssp_state->session_key = session_key;
}
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ ntlmssp_state->session_key = data_blob(NULL, 0);
+ } else if (ntlmssp_state->session_key.length) {
+ nt_status = ntlmssp_sign_init(ntlmssp_state);
+ }
+
data_blob_free(&encrypted_session_key);
/* allow arbitarily many authentications */
@@ -906,7 +924,14 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
}
if (!ntlmssp_state->password) {
+ static const uchar zeros[16];
/* do nothing - blobs are zero length */
+
+ /* session key is all zeros */
+ session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16);
+
+ /* not doing NLTM2 without a password */
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
} else if (ntlmssp_state->use_ntlmv2) {
if (!struct_blob.length) {
diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c
index ea1a7037c9..6ce7a76743 100644
--- a/source3/libsmb/ntlmssp_sign.c
+++ b/source3/libsmb/ntlmssp_sign.c
@@ -53,7 +53,7 @@ static void NTLMSSPcalc_ap( unsigned char *hash, unsigned char *data, int len)
hash[257] = index_j;
}
-static void calc_hash(unsigned char *hash, const char *k2, int k2l)
+static void calc_hash(unsigned char hash[258], const char *k2, int k2l)
{
unsigned char j = 0;
int ind;
@@ -78,7 +78,7 @@ static void calc_hash(unsigned char *hash, const char *k2, int k2l)
hash[257] = 0;
}
-static void calc_ntlmv2_hash(unsigned char hash[16], char digest[16],
+static void calc_ntlmv2_hash(unsigned char hash[258], unsigned char digest[16],
DATA_BLOB session_key,
const char *constant)
{
@@ -91,8 +91,8 @@ static void calc_ntlmv2_hash(unsigned char hash[16], char digest[16],
MD5Init(&ctx3);
MD5Update(&ctx3, session_key.data, session_key.length);
- MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant));
- MD5Final((unsigned char *)digest, &ctx3);
+ MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant)+1);
+ MD5Final(digest, &ctx3);
calc_hash(hash, digest, 16);
}
@@ -109,12 +109,12 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
{
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
HMACMD5Context ctx;
- char seq_num[4];
+ uchar seq_num[4];
uchar digest[16];
SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
- hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
+ hmac_md5_update(seq_num, 4, &ctx);
hmac_md5_update(data, length, &ctx);
hmac_md5_final(digest, &ctx);
@@ -122,13 +122,16 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
, ntlmssp_state->ntlmssp_seq_num)) {
return NT_STATUS_NO_MEMORY;
}
- switch (direction) {
- case NTLMSSP_SEND:
- NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash, sig->data+4, sig->length-4);
- break;
- case NTLMSSP_RECEIVE:
- NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash, sig->data+4, sig->length-4);
- break;
+
+ if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+ switch (direction) {
+ case NTLMSSP_SEND:
+ NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash, sig->data+4, sig->length-4);
+ break;
+ case NTLMSSP_RECEIVE:
+ NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash, sig->data+4, sig->length-4);
+ break;
+ }
}
} else {
uint32 crc;
@@ -148,7 +151,13 @@ NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
const uchar *data, size_t length,
DATA_BLOB *sig)
{
- NTSTATUS nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig);
+ NTSTATUS nt_status;
+ if (!ntlmssp_state->session_key.length) {
+ DEBUG(3, ("NO session key, cannot check sign packet\n"));
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
+ nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig);
/* increment counter on send */
ntlmssp_state->ntlmssp_seq_num++;
@@ -168,6 +177,11 @@ NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
DATA_BLOB local_sig;
NTSTATUS nt_status;
+ if (!ntlmssp_state->session_key.length) {
+ DEBUG(3, ("NO session key, cannot check packet signature\n"));
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
if (sig->length < 8) {
DEBUG(0, ("NTLMSSP packet check failed due to short signature (%lu bytes)!\n",
(unsigned long)sig->length));
@@ -208,6 +222,11 @@ NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
uchar *data, size_t length,
DATA_BLOB *sig)
{
+ if (!ntlmssp_state->session_key.length) {
+ DEBUG(3, ("NO session key, cannot seal packet\n"));
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
DEBUG(10,("ntlmssp_seal_data: seal\n"));
dump_data_pw("ntlmssp clear data\n", data, length);
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
@@ -270,6 +289,11 @@ NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
uchar *data, size_t length,
DATA_BLOB *sig)
{
+ if (!ntlmssp_state->session_key.length) {
+ DEBUG(3, ("NO session key, cannot unseal packet\n"));
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
DEBUG(10,("ntlmssp__unseal_data: seal\n"));
dump_data_pw("ntlmssp sealed data\n", data, length);
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
@@ -295,6 +319,11 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n"));
debug_ntlmssp_flags(ntlmssp_state->neg_flags);
+ if (!ntlmssp_state->session_key.length) {
+ DEBUG(3, ("NO session key, cannot intialise signing\n"));
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
{
const char *send_sign_const;
diff --git a/source3/libsmb/pwd_cache.c b/source3/libsmb/pwd_cache.c
index f45832d7d7..7ba6cfc96f 100644
--- a/source3/libsmb/pwd_cache.c
+++ b/source3/libsmb/pwd_cache.c
@@ -45,8 +45,14 @@ static void pwd_make_lm_nt_16(struct pwd_info *pwd, const char *clr)
{
pwd_init(pwd);
- nt_lm_owf_gen(clr, pwd->smb_nt_pwd, pwd->smb_lm_pwd);
- pwd->null_pwd = False;
+ if (!clr) {
+ ZERO_STRUCT(pwd->smb_nt_pwd);
+ ZERO_STRUCT(pwd->smb_lm_pwd);
+ pwd->null_pwd = True;
+ } else {
+ nt_lm_owf_gen(clr, pwd->smb_nt_pwd, pwd->smb_lm_pwd);
+ pwd->null_pwd = False;
+ }
pwd->crypted = False;
}
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 49abf787ee..3213e955b6 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -1342,11 +1342,18 @@ static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_na
if (!NT_STATUS_IS_OK(nt_status))
return False;
- pwd_get_cleartext(&cli->pwd, password);
- nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state,
- password);
- if (!NT_STATUS_IS_OK(nt_status))
- return False;
+ if (cli->pwd.null_pwd) {
+ nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state,
+ NULL);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return False;
+ } else {
+ pwd_get_cleartext(&cli->pwd, password);
+ nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state,
+ password);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return False;
+ }
if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;