summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/auth/ntlm_check.c105
-rw-r--r--source4/libcli/auth/credentials.c11
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c140
-rw-r--r--source4/rpc_server/netlogon/schannel_state.c13
-rw-r--r--source4/torture/rpc/netlogon.c16
-rw-r--r--source4/torture/rpc/samlogon.c11
6 files changed, 191 insertions, 105 deletions
diff --git a/source4/auth/ntlm_check.c b/source4/auth/ntlm_check.c
index e6a8ce681f..474742bee0 100644
--- a/source4/auth/ntlm_check.c
+++ b/source4/auth/ntlm_check.c
@@ -285,48 +285,57 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
(unsigned long)nt_response->length, username));
}
- if (nt_response->length >= 24 && nt_pw) {
- if (nt_response->length > 24) {
- /* We have the NT MD4 hash challenge available - see if we can
- use it
- */
- DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain));
- if (smb_pwd_check_ntlmv2(mem_ctx,
- nt_response,
- nt_pw, challenge,
- client_username,
- client_domain,
- False,
- user_sess_key)) {
- return NT_STATUS_OK;
+ if (nt_response->length > 24 && nt_pw) {
+ /* We have the NT MD4 hash challenge available - see if we can
+ use it
+ */
+ DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain));
+ if (smb_pwd_check_ntlmv2(mem_ctx,
+ nt_response,
+ nt_pw, challenge,
+ client_username,
+ client_domain,
+ False,
+ user_sess_key)) {
+ if (lm_sess_key) {
+ *lm_sess_key = *user_sess_key;
+ lm_sess_key->length = 8;
}
-
- DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain));
- if (smb_pwd_check_ntlmv2(mem_ctx,
- nt_response,
- nt_pw, challenge,
- client_username,
- client_domain,
- True,
- user_sess_key)) {
- return NT_STATUS_OK;
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain));
+ if (smb_pwd_check_ntlmv2(mem_ctx,
+ nt_response,
+ nt_pw, challenge,
+ client_username,
+ client_domain,
+ True,
+ user_sess_key)) {
+ if (lm_sess_key) {
+ *lm_sess_key = *user_sess_key;
+ lm_sess_key->length = 8;
}
-
- DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n"));
- if (smb_pwd_check_ntlmv2(mem_ctx,
- nt_response,
- nt_pw, challenge,
- client_username,
- "",
- False,
- user_sess_key)) {
- return NT_STATUS_OK;
- } else {
- DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n"));
- return NT_STATUS_WRONG_PASSWORD;
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n"));
+ if (smb_pwd_check_ntlmv2(mem_ctx,
+ nt_response,
+ nt_pw, challenge,
+ client_username,
+ "",
+ False,
+ user_sess_key)) {
+ if (lm_sess_key) {
+ *lm_sess_key = *user_sess_key;
+ lm_sess_key->length = 8;
}
+ return NT_STATUS_OK;
+ } else {
+ DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n"));
}
-
+ } else if (nt_response->length == 24 && nt_pw) {
if (lp_ntlm_auth()) {
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
@@ -338,7 +347,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
user_sess_key)) {
/* The LM session key for this response is not very secure,
so use it only if we otherwise allow LM authentication */
-
+
if (lp_lanman_auth() && lm_pw) {
*lm_sess_key = data_blob_talloc(mem_ctx, lm_pw, 8);
}
@@ -409,7 +418,11 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
client_username,
client_domain,
False,
- NULL)) {
+ user_sess_key)) {
+ if (lm_sess_key) {
+ *lm_sess_key = *user_sess_key;
+ lm_sess_key->length = 8;
+ }
return NT_STATUS_OK;
}
@@ -420,7 +433,11 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
client_username,
client_domain,
True,
- NULL)) {
+ user_sess_key)) {
+ if (lm_sess_key) {
+ *lm_sess_key = *user_sess_key;
+ lm_sess_key->length = 8;
+ }
return NT_STATUS_OK;
}
@@ -431,7 +448,11 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
client_username,
"",
False,
- NULL)) {
+ user_sess_key)) {
+ if (lm_sess_key) {
+ *lm_sess_key = *user_sess_key;
+ lm_sess_key->length = 8;
+ }
return NT_STATUS_OK;
}
diff --git a/source4/libcli/auth/credentials.c b/source4/libcli/auth/credentials.c
index a61660d776..8cae71180c 100644
--- a/source4/libcli/auth/credentials.c
+++ b/source4/libcli/auth/credentials.c
@@ -273,6 +273,7 @@ void creds_server_init(struct creds_CredentialState *creds,
}
*initial_credential = creds->server;
+ creds->negotiate_flags = negotiate_flags;
}
/*
@@ -290,10 +291,14 @@ BOOL creds_server_check(const struct creds_CredentialState *creds,
return True;
}
-BOOL creds_server_step_check(struct creds_CredentialState *creds,
+NTSTATUS creds_server_step_check(struct creds_CredentialState *creds,
struct netr_Authenticator *received_authenticator,
struct netr_Authenticator *return_authenticator)
{
+ if (!received_authenticator || !return_authenticator) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
/* TODO: this may allow the a replay attack on a non-signed
connection. Should we check that this is increasing? */
creds->sequence = received_authenticator->timestamp;
@@ -301,9 +306,9 @@ BOOL creds_server_step_check(struct creds_CredentialState *creds,
if (creds_server_check(creds, &received_authenticator->cred)) {
return_authenticator->cred = creds->server;
return_authenticator->timestamp = creds->sequence;
- return True;
+ return NT_STATUS_OK;
} else {
ZERO_STRUCTP(return_authenticator);
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
}
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 422aa626ed..167c4e8ceb 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -317,12 +317,17 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL
}
-static BOOL netr_creds_server_step_check(struct server_pipe_state *pipe_state,
- struct netr_Authenticator *received_authenticator,
- struct netr_Authenticator *return_authenticator)
+static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_state,
+ struct netr_Authenticator *received_authenticator,
+ struct netr_Authenticator *return_authenticator)
{
+ if (!pipe_state) {
+ DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (!pipe_state->authenticated) {
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
return creds_server_step_check(pipe_state->creds,
received_authenticator,
@@ -351,13 +356,9 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
const char **domain_attrs = attrs;
ZERO_STRUCT(mod);
- if (!pipe_state) {
- DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) {
- return NT_STATUS_ACCESS_DENIED;
+ nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
}
sam_ctx = samdb_connect(mem_ctx);
@@ -461,9 +462,10 @@ static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX
/*
netr_LogonSamLogonWithFlags
+ This version of the function allows other wrappers to say 'do not check the credentials'
*/
-static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct netr_LogonSamLogonWithFlags *r)
+static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct netr_LogonSamLogonEx *r)
{
struct server_pipe_state *pipe_state = dce_call->conn->private;
@@ -478,30 +480,21 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
struct netr_SamInfo3 *sam3;
struct netr_SamInfo6 *sam6;
- if (!pipe_state) {
- DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- r->out.return_authenticator = talloc_p(mem_ctx, struct netr_Authenticator);
- if (!r->out.return_authenticator) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (!netr_creds_server_step_check(pipe_state, r->in.credential, r->out.return_authenticator)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
switch (r->in.logon_level) {
case 1:
case 3:
case 5:
- creds_arcfour_crypt(pipe_state->creds,
- r->in.logon.password->lmpassword.hash,
- sizeof(r->in.logon.password->lmpassword.hash));
- creds_arcfour_crypt(pipe_state->creds,
- r->in.logon.password->ntpassword.hash,
- sizeof(r->in.logon.password->ntpassword.hash));
+ if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+ creds_arcfour_crypt(pipe_state->creds,
+ r->in.logon.password->lmpassword.hash,
+ sizeof(r->in.logon.password->lmpassword.hash));
+ creds_arcfour_crypt(pipe_state->creds,
+ r->in.logon.password->ntpassword.hash,
+ sizeof(r->in.logon.password->ntpassword.hash));
+ } else {
+ creds_des_decrypt(pipe_state->creds, &r->in.logon.password->lmpassword);
+ creds_des_decrypt(pipe_state->creds, &r->in.logon.password->ntpassword);
+ }
nt_status = make_auth_context_subsystem(pipe_state, &auth_context);
if (!NT_STATUS_IS_OK(nt_status)) {
@@ -600,9 +593,13 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
if ((r->in.validation_level != 6)
&& memcmp(sam->key.key, zeros,
sizeof(sam->key.key)) != 0) {
- creds_arcfour_crypt(pipe_state->creds,
- sam->key.key,
- sizeof(sam->key.key));
+
+ /* This key is sent unencrypted without the ARCFOUR flag set */
+ if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+ creds_arcfour_crypt(pipe_state->creds,
+ sam->key.key,
+ sizeof(sam->key.key));
+ }
}
if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
@@ -617,9 +614,14 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
if ((r->in.validation_level != 6)
&& memcmp(sam->LMSessKey.key, zeros,
sizeof(sam->LMSessKey.key)) != 0) {
- creds_arcfour_crypt(pipe_state->creds,
- sam->LMSessKey.key,
- sizeof(sam->LMSessKey.key));
+ if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+ creds_arcfour_crypt(pipe_state->creds,
+ sam->LMSessKey.key,
+ sizeof(sam->LMSessKey.key));
+ } else {
+ creds_des_encrypt_LMKey(pipe_state->creds,
+ &sam->LMSessKey);
+ }
}
switch (r->in.validation_level) {
@@ -657,6 +659,45 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
}
/*
+ netr_LogonSamLogonWithFlags
+
+*/
+static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct netr_LogonSamLogonWithFlags *r)
+{
+ NTSTATUS nt_status;
+ struct netr_LogonSamLogonEx r2;
+
+ struct server_pipe_state *pipe_state = dce_call->conn->private;
+
+ r->out.return_authenticator = talloc_p(mem_ctx, struct netr_Authenticator);
+ if (!r->out.return_authenticator) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ nt_status = netr_creds_server_step_check(pipe_state, r->in.credential, r->out.return_authenticator);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ ZERO_STRUCT(r2);
+
+ r2.in.server_name = r->in.server_name;
+ r2.in.workstation = r->in.workstation;
+ r2.in.logon_level = r->in.logon_level;
+ r2.in.logon = r->in.logon;
+ r2.in.validation_level = r->in.validation_level;
+ r2.in.flags = r->in.flags;
+
+ nt_status = netr_LogonSamLogonEx(dce_call, mem_ctx, &r2);
+
+ r->out.validation = r2.out.validation;
+ r->out.authoritative = r2.out.authoritative;
+
+ return nt_status;
+}
+
+/*
netr_LogonSamLogon
*/
static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
@@ -940,13 +981,10 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
int ret1, ret2, i;
NTSTATUS status;
- if (!pipe_state) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (!netr_creds_server_step_check(pipe_state,
- r->in.credential, r->out.credential)) {
- return NT_STATUS_ACCESS_DENIED;
+ status = netr_creds_server_step_check(pipe_state,
+ r->in.credential, r->out.credential);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
sam_ctx = samdb_connect(mem_ctx);
@@ -1134,16 +1172,6 @@ static WERROR netr_DSRGETDCSITECOVERAGEW(struct dcesrv_call_state *dce_call, TAL
/*
- netr_LogonSamLogonEx
-*/
-static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct netr_LogonSamLogonEx *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
-
-/*
netr_DsrEnumerateDomainTrusts
*/
static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
diff --git a/source4/rpc_server/netlogon/schannel_state.c b/source4/rpc_server/netlogon/schannel_state.c
index 564564e8c2..7dc60a1617 100644
--- a/source4/rpc_server/netlogon/schannel_state.c
+++ b/source4/rpc_server/netlogon/schannel_state.c
@@ -61,7 +61,8 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
struct ldb_wrap *ldb;
struct ldb_message *msg;
struct ldb_val val, seed;
- char *s = NULL;
+ char *s;
+ char *f;
time_t expiry = time(NULL) + SCHANNEL_CREDENTIALS_EXPIRY;
int ret;
@@ -77,6 +78,13 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
return NT_STATUS_NO_MEMORY;
}
+ f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags);
+
+ if (f == NULL) {
+ talloc_free(ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+
msg = ldb_msg_new(mem_ctx);
if (msg == NULL) {
talloc_free(ldb);
@@ -99,6 +107,7 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
ldb_msg_add_value(ldb->ldb, msg, "sessionKey", &val);
ldb_msg_add_value(ldb->ldb, msg, "seed", &seed);
ldb_msg_add_string(ldb->ldb, msg, "expiry", s);
+ ldb_msg_add_string(ldb->ldb, msg, "negotiateFlags", f);
ldb_delete(ldb->ldb, msg->dn);
@@ -180,6 +189,8 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx,
memcpy((*creds)->seed.data, val->data, 8);
+ (*creds)->negotiate_flags = ldb_msg_find_int(res[0], "negotiateFlags", 0);
+
talloc_free(ldb);
return NT_STATUS_OK;
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index a23cdb8b0c..35f64933a9 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -378,6 +378,22 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
}
}
+ r.in.credential = NULL;
+
+ for (i=2;i<=3;i++) {
+
+ r.in.validation_level = i;
+
+ printf("Testing SamLogon with validation level %d\n", i);
+
+ status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+ printf("LogonSamLogon expected INVALID_PARAMETER, got: %s\n", nt_errstr(status));
+ ret = False;
+ }
+
+ }
+
return ret;
}
diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c
index 821a823595..29a87f9804 100644
--- a/source4/torture/rpc/samlogon.c
+++ b/source4/torture/rpc/samlogon.c
@@ -220,7 +220,11 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
/* we cannot check the session key, if the logon failed... */
return status;
}
-
+
+ if (!base) {
+ printf("No user info returned from 'successful' SamLogon*() call!\n");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
/* find and decyrpt the session keys, return in parameters above */
if (validation_level == 6) {
@@ -1043,11 +1047,12 @@ BOOL torture_rpc_samlogon(void)
int i;
unsigned int credential_flags[] = {
- 0,
NETLOGON_NEG_AUTH2_FLAGS,
NETLOGON_NEG_ARCFOUR,
NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
- NETLOGON_NEG_AUTH2_ADS_FLAGS};
+ NETLOGON_NEG_AUTH2_ADS_FLAGS,
+ 0 /* yes, this is a valid flag, causes the use of DES */
+ };
struct creds_CredentialState *creds;