summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/idl/netlogon.idl15
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c6
-rw-r--r--source4/torture/rpc/samlogon.c109
3 files changed, 99 insertions, 31 deletions
diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl
index 0f44c0616d..972f330cc1 100644
--- a/source4/librpc/idl/netlogon.idl
+++ b/source4/librpc/idl/netlogon.idl
@@ -223,7 +223,7 @@ interface netlogon
[in] [switch_is(logon_level)] netr_LogonLevel logon,
[in] uint16 validation_level,
[out] [switch_is(validation_level)] netr_Validation validation,
- [out] uint32 authoritative
+ [out] uint8 authoritative
);
@@ -1048,7 +1048,16 @@ interface netlogon
/****************/
/* Function 0x27 */
- WERROR netr_NETRLOGONSAMLOGONEX();
+ NTSTATUS netr_LogonSamLogonEx(
+ [in] unistr *server_name,
+ [in] unistr *workstation,
+ [in] uint16 logon_level,
+ [in] [switch_is(logon_level)] netr_LogonLevel logon,
+ [in] uint16 validation_level,
+ [out] [switch_is(validation_level)] netr_Validation validation,
+ [out] uint8 authoritative,
+ [in,out] uint32 flags
+ );
/****************/
/* Function 0x28 */
@@ -1108,7 +1117,7 @@ interface netlogon
[in] [switch_is(logon_level)] netr_LogonLevel logon,
[in] uint16 validation_level,
[out] [switch_is(validation_level)] netr_Validation validation,
- [out] uint32 authoritative,
+ [out] uint8 authoritative,
[in,out] uint32 flags
);
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 00e27c75a8..0720e317c5 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -1132,10 +1132,10 @@ static WERROR netr_DSRGETDCSITECOVERAGEW(struct dcesrv_call_state *dce_call, TAL
/*
- netr_NETRLOGONSAMLOGONEX
+ netr_LogonSamLogonEx
*/
-static WERROR netr_NETRLOGONSAMLOGONEX(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct netr_NETRLOGONSAMLOGONEX *r)
+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);
}
diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c
index 5204175559..c193ba5557 100644
--- a/source4/torture/rpc/samlogon.c
+++ b/source4/torture/rpc/samlogon.c
@@ -46,6 +46,7 @@ struct samlogon_state {
struct dcerpc_pipe *p;
int function_level;
struct netr_LogonSamLogon r;
+ struct netr_LogonSamLogonEx r_ex;
struct netr_LogonSamLogonWithFlags r_flags;
struct netr_Authenticator auth, auth2;
struct creds_CredentialState *creds;
@@ -68,6 +69,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
{
NTSTATUS status;
struct netr_LogonSamLogon *r = &samlogon_state->r;
+ struct netr_LogonSamLogonEx *r_ex = &samlogon_state->r_ex;
struct netr_LogonSamLogonWithFlags *r_flags = &samlogon_state->r_flags;
struct netr_NetworkInfo ninfo;
@@ -76,6 +78,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
uint16 validation_level;
samlogon_state->r.in.logon.network = &ninfo;
+ samlogon_state->r_ex.in.logon.network = &ninfo;
samlogon_state->r_flags.in.logon.network = &ninfo;
ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
@@ -132,11 +135,11 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
ninfo.lm.length = 0;
}
- ZERO_STRUCT(samlogon_state->auth2);
- creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
-
switch (samlogon_state->function_level) {
case DCERPC_NETR_LOGONSAMLOGON:
+ ZERO_STRUCT(samlogon_state->auth2);
+ creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
+
r->out.return_authenticator = NULL;
status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
if (!r->out.return_authenticator ||
@@ -162,7 +165,31 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
break;
}
break;
+ case DCERPC_NETR_LOGONSAMLOGONEX:
+ status = dcerpc_netr_LogonSamLogonEx(samlogon_state->p, samlogon_state->mem_ctx, r_ex);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (error_string) {
+ *error_string = strdup(nt_errstr(status));
+ }
+ }
+
+ validation_level = r_ex->in.validation_level;
+ switch (validation_level) {
+ case 2:
+ base = &r_ex->out.validation.sam2->base;
+ break;
+ case 3:
+ base = &r_ex->out.validation.sam3->base;
+ break;
+ case 6:
+ base = &r_ex->out.validation.sam6->base;
+ break;
+ }
+ break;
case DCERPC_NETR_LOGONSAMLOGONWITHFLAGS:
+ ZERO_STRUCT(samlogon_state->auth2);
+ creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
+
r_flags->out.return_authenticator = NULL;
status = dcerpc_netr_LogonSamLogonWithFlags(samlogon_state->p, samlogon_state->mem_ctx, r_flags);
if (!r_flags->out.return_authenticator ||
@@ -547,6 +574,10 @@ static BOOL test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, enum
return break_which == BREAK_BOTH;
}
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return False;
+ }
+
switch (break_which) {
case NO_NT:
if (memcmp(lmv2_session_key.data, user_session_key,
@@ -872,6 +903,7 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
int logon_levels[] = { 2, 6 };
int function_levels[] = {
DCERPC_NETR_LOGONSAMLOGON,
+ DCERPC_NETR_LOGONSAMLOGONEX,
DCERPC_NETR_LOGONSAMLOGONWITHFLAGS };
struct samlogon_state samlogon_state;
@@ -893,19 +925,25 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
samlogon_state.r_flags.in.flags = 0;
+ samlogon_state.r_ex.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+ samlogon_state.r_ex.in.workstation = TEST_MACHINE_NAME;
+ samlogon_state.r_ex.in.flags = 0;
+
samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
samlogon_state.r.in.credential = &samlogon_state.auth;
samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
- for (i=0; test_table[i].fn; i++) {
- for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
- for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
- for (f=0;f<ARRAY_SIZE(function_levels);f++) {
+ for (f=0;f<ARRAY_SIZE(function_levels);f++) {
+ for (i=0; test_table[i].fn; i++) {
+ for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
+ for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
char *error_string = NULL;
samlogon_state.function_level = function_levels[f];
samlogon_state.r.in.validation_level = validation_levels[v];
samlogon_state.r.in.logon_level = logon_levels[l];
+ samlogon_state.r_ex.in.validation_level = validation_levels[v];
+ samlogon_state.r_ex.in.logon_level = logon_levels[l];
samlogon_state.r_flags.in.validation_level = validation_levels[v];
samlogon_state.r_flags.in.logon_level = logon_levels[l];
if (!test_table[i].fn(&samlogon_state, &error_string)) {
@@ -998,10 +1036,12 @@ BOOL torture_rpc_samlogon(void)
{
NTSTATUS status;
struct dcerpc_pipe *p;
+ struct dcerpc_binding b;
TALLOC_CTX *mem_ctx;
BOOL ret = True;
void *join_ctx;
- const char *machine_pass;
+ const char *machine_password;
+ const char *binding = lp_parm_string(-1, "torture", "binding");
int i;
unsigned int credential_flags[] = {
@@ -1011,69 +1051,88 @@ BOOL torture_rpc_samlogon(void)
NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
NETLOGON_NEG_AUTH2_ADS_FLAGS};
- struct creds_CredentialState creds;
+ struct creds_CredentialState *creds;
mem_ctx = talloc_init("torture_rpc_netlogon");
join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST,
- &machine_pass);
+ &machine_password);
if (!join_ctx) {
printf("Failed to join as BDC\n");
return False;
}
- status = torture_rpc_connection(&p,
- DCERPC_NETLOGON_NAME,
- DCERPC_NETLOGON_UUID,
- DCERPC_NETLOGON_VERSION);
+ status = dcerpc_parse_binding(mem_ctx, binding, &b);
if (!NT_STATUS_IS_OK(status)) {
- return False;
+ printf("Bad binding string %s\n", binding);
+ ret = False;
+ goto failed;
}
- if (!test_SetupCredentials(p, mem_ctx,
- TEST_MACHINE_NAME, machine_pass, &creds)) {
+ /* We have to use schannel, otherwise the SamLogonEx fails
+ * with INTERNAL_ERROR */
+
+ b.flags &= ~DCERPC_AUTH_OPTIONS;
+ b.flags |= DCERPC_SCHANNEL_BDC | DCERPC_SIGN | DCERPC_SCHANNEL_128;
+
+ status = dcerpc_pipe_connect_b(&p, &b,
+ DCERPC_NETLOGON_UUID,
+ DCERPC_NETLOGON_VERSION,
+ lp_workgroup(),
+ TEST_MACHINE_NAME,
+ machine_password);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ ret = False;
+ goto failed;
+ }
+
+ status = dcerpc_schannel_creds(p->security_state.generic_state, mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(status)) {
ret = False;
+ goto failed;
}
- if (!test_InteractiveLogon(p, mem_ctx, &creds)) {
+ if (!test_InteractiveLogon(p, mem_ctx, creds)) {
ret = False;
}
- if (!test_SamLogon(p, mem_ctx, &creds)) {
+ if (!test_SamLogon(p, mem_ctx, creds)) {
ret = False;
}
for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
if (!test_SetupCredentials2(p, mem_ctx, credential_flags[i],
- TEST_MACHINE_NAME, machine_pass, &creds)) {
+ TEST_MACHINE_NAME, machine_password, creds)) {
return False;
}
- if (!test_InteractiveLogon(p, mem_ctx, &creds)) {
+ if (!test_InteractiveLogon(p, mem_ctx, creds)) {
ret = False;
}
- if (!test_SamLogon(p, mem_ctx, &creds)) {
+ if (!test_SamLogon(p, mem_ctx, creds)) {
ret = False;
}
}
for (i=0; i < 32; i++) {
if (!test_SetupCredentials2(p, mem_ctx, 1 << i,
- TEST_MACHINE_NAME, machine_pass, &creds)) {
+ TEST_MACHINE_NAME, machine_password, creds)) {
return False;
}
- if (!test_InteractiveLogon(p, mem_ctx, &creds)) {
+ if (!test_InteractiveLogon(p, mem_ctx, creds)) {
ret = False;
}
- if (!test_SamLogon(p, mem_ctx, &creds)) {
+ if (!test_SamLogon(p, mem_ctx, creds)) {
ret = False;
}
}
+failed:
talloc_destroy(mem_ctx);
torture_rpc_close(p);