summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2006-02-21 00:07:59 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:51:58 -0500
commit9d1954c25d646c46daa38c3f96f4c4029b9bb417 (patch)
treecf7c42a24e88ba091d9a1f5bf2d460cf45f62790
parenteefb44079160b66dc69f63a0d9bae955bcb6acc9 (diff)
downloadsamba-9d1954c25d646c46daa38c3f96f4c4029b9bb417.tar.gz
samba-9d1954c25d646c46daa38c3f96f4c4029b9bb417.tar.bz2
samba-9d1954c25d646c46daa38c3f96f4c4029b9bb417.zip
r13583: Realise that the member server name appears in all calls that use the
credentials. Consistantly rename these elements in the IDL to computer_name. Fix the server-side code to always lookup by this name. Add new, even nastier tests to RPC-SCHANNEL to prove this. Andrew Bartlett (This used to be commit 341a0abeb4a9f88d64ffd4681249cb1f643a7a5a)
-rw-r--r--source4/auth/gensec/schannel_state.c2
-rw-r--r--source4/librpc/idl/netlogon.idl6
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c132
-rw-r--r--source4/torture/rpc/netlogon.c5
-rw-r--r--source4/torture/rpc/samlogon.c8
-rw-r--r--source4/torture/rpc/samsync.c2
-rw-r--r--source4/torture/rpc/schannel.c30
-rw-r--r--source4/winbind/wb_pam_auth.c2
8 files changed, 74 insertions, 113 deletions
diff --git a/source4/auth/gensec/schannel_state.c b/source4/auth/gensec/schannel_state.c
index a73e450ec8..beaa8cfb08 100644
--- a/source4/auth/gensec/schannel_state.c
+++ b/source4/auth/gensec/schannel_state.c
@@ -175,7 +175,7 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
NTSTATUS schannel_fetch_session_key_ldb(TALLOC_CTX *mem_ctx,
struct ldb_context *ldb,
const char *computer_name,
- const char *domain,
+ const char *domain,
struct creds_CredentialState **creds)
{
struct ldb_result *res;
diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl
index fe0a1adbe4..75d1b3316b 100644
--- a/source4/librpc/idl/netlogon.idl
+++ b/source4/librpc/idl/netlogon.idl
@@ -229,7 +229,7 @@ interface netlogon
NTSTATUS netr_LogonSamLogon(
[in] [string,charset(UTF16)] uint16 *server_name,
- [in] [string,charset(UTF16)] uint16 *workstation,
+ [in] [string,charset(UTF16)] uint16 *computer_name,
[in] netr_Authenticator *credential,
[in][out] netr_Authenticator *return_authenticator,
[in] uint16 logon_level,
@@ -1096,7 +1096,7 @@ interface netlogon
/* Function 0x27 */
NTSTATUS netr_LogonSamLogonEx(
[in] [string,charset(UTF16)] uint16 *server_name,
- [in] [string,charset(UTF16)] uint16 *workstation,
+ [in] [string,charset(UTF16)] uint16 *computer_name,
[in] uint16 logon_level,
[in] [switch_is(logon_level)] netr_LogonLevel logon,
[in] uint16 validation_level,
@@ -1175,7 +1175,7 @@ interface netlogon
/* this is the ADS varient. I don't yet know what the "flags" are for */
NTSTATUS netr_LogonSamLogonWithFlags(
[in] [string,charset(UTF16)] uint16 *server_name,
- [in] [string,charset(UTF16)] uint16 *workstation,
+ [in] [string,charset(UTF16)] uint16 *computer_name,
[in] netr_Authenticator *credential,
[in][out] netr_Authenticator *return_authenticator,
[in] uint16 logon_level,
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 176246901b..d506d9192d 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -31,72 +31,9 @@
struct server_pipe_state {
struct netr_Credential client_challenge;
struct netr_Credential server_challenge;
-
- /* This is a bit (dangeroursly?) tricky:
- - The session key, computer name and domain elements are
- valid.
- - However the credentials chaining (seed, client, server etc)
- should be obtained from the database at runtime */
- struct creds_CredentialState *creds;
};
-/*
- a client has connected to the netlogon server using schannel, so we need
- to re-establish the credentials state
-*/
-static NTSTATUS netlogon_schannel_setup(struct dcesrv_call_state *dce_call)
-{
- struct server_pipe_state *state;
- NTSTATUS status;
-
- /* We want the client and server challenge zero */
- state = talloc_zero(dce_call->conn, struct server_pipe_state);
- if (state == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = dcerpc_schannel_creds(dce_call->conn->auth_state.gensec_security,
- state,
- &state->creds);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("getting schannel credentials failed with %s\n", nt_errstr(status)));
- talloc_free(state);
- return status;
- }
-
- dce_call->context->private = state;
-
- return NT_STATUS_OK;
-}
-
-/*
- a hook for bind on the netlogon pipe
-*/
-static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *di)
-{
- dce_call->context->private = NULL;
-
- /* if this is a schannel bind then we need to reconstruct the pipe state */
- if (dce_call->conn->auth_state.auth_info &&
- dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
- NTSTATUS status;
-
- DEBUG(5, ("schannel bind on netlogon\n"));
-
- status = netlogon_schannel_setup(dce_call);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("schannel bind on netlogon failed with %s\n", nt_errstr(status)));
- return status;
- }
- }
-
- return NT_STATUS_OK;
-}
-
-#define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
-
static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerReqChallenge *r)
{
@@ -116,8 +53,6 @@ static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALL
return NT_STATUS_NO_MEMORY;
}
- pipe_state->creds = NULL;
-
pipe_state->client_challenge = *r->in.credentials;
generate_random_buffer(pipe_state->server_challenge.data,
@@ -238,12 +173,6 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL
/* remember this session key state */
nt_status = schannel_store_session_key(mem_ctx, creds);
- if (pipe_state->creds) {
- talloc_free(pipe_state->creds);
- }
- talloc_steal(pipe_state, creds);
- pipe_state->creds = creds;
-
return nt_status;
}
@@ -302,7 +231,7 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL
the caller needs some of that information.
*/
-static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_state,
+static NTSTATUS netr_creds_server_step_check(const char *computer_name,
TALLOC_CTX *mem_ctx,
struct netr_Authenticator *received_authenticator,
struct netr_Authenticator *return_authenticator,
@@ -313,11 +242,6 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
struct ldb_context *ldb;
int ret;
- if (!pipe_state) {
- DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
ldb = schannel_db_connect(mem_ctx);
if (!ldb) {
return NT_STATUS_ACCESS_DENIED;
@@ -333,8 +257,8 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
* disconnects) we must update the database every time we
* update the structure */
- nt_status = schannel_fetch_session_key_ldb(ldb, ldb, pipe_state->creds->computer_name,
- pipe_state->creds->domain, &creds);
+ nt_status = schannel_fetch_session_key_ldb(ldb, ldb, computer_name, lp_workgroup(),
+ &creds);
if (NT_STATUS_IS_OK(nt_status)) {
nt_status = creds_server_step_check(creds,
received_authenticator,
@@ -365,12 +289,11 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerPasswordSet *r)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
struct creds_CredentialState *creds;
struct ldb_context *sam_ctx;
NTSTATUS nt_status;
- nt_status = netr_creds_server_step_check(pipe_state, mem_ctx,
+ nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx,
&r->in.credential, &r->out.return_authenticator,
&creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -400,7 +323,6 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerPasswordSet2 *r)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
struct creds_CredentialState *creds;
struct ldb_context *sam_ctx;
NTSTATUS nt_status;
@@ -410,7 +332,7 @@ static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALL
struct samr_CryptPassword password_buf;
- nt_status = netr_creds_server_step_check(pipe_state, mem_ctx,
+ nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx,
&r->in.credential, &r->out.return_authenticator,
&creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -464,15 +386,15 @@ static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX
/*
- netr_LogonSamLogonEx
+ netr_LogonSamLogon_base
This version of the function allows other wrappers to say 'do not check the credentials'
+
+ We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
*/
-static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct netr_LogonSamLogonEx *r)
+static NTSTATUS netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct netr_LogonSamLogonEx *r, struct creds_CredentialState *creds)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
- struct creds_CredentialState *creds = pipe_state->creds;
struct auth_context *auth_context;
struct auth_usersupplied_info *user_info;
struct auth_serversupplied_info *server_info;
@@ -496,7 +418,7 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
case 1:
case 3:
case 5:
- if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+ if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
creds_arcfour_crypt(creds,
r->in.logon.password->lmpassword.hash,
sizeof(r->in.logon.password->lmpassword.hash));
@@ -633,6 +555,23 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
return NT_STATUS_OK;
}
+static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct netr_LogonSamLogonEx *r)
+{
+ NTSTATUS nt_status;
+ struct creds_CredentialState *creds;
+ nt_status = schannel_fetch_session_key(mem_ctx, r->in.computer_name, lp_workgroup(), &creds);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ if (!dce_call->conn->auth_state.auth_info
+ || dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
+}
+
/*
netr_LogonSamLogonWithFlags
@@ -640,8 +579,8 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonSamLogonWithFlags *r)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
NTSTATUS nt_status;
+ struct creds_CredentialState *creds;
struct netr_LogonSamLogonEx r2;
struct netr_Authenticator *return_authenticator;
@@ -649,21 +588,21 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
- nt_status = netr_creds_server_step_check(pipe_state, mem_ctx,
+ nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx,
r->in.credential, return_authenticator,
- NULL);
+ &creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
ZERO_STRUCT(r2);
r2.in.server_name = r->in.server_name;
- r2.in.workstation = r->in.workstation;
+ r2.in.computer_name = r->in.computer_name;
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);
+ nt_status = netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
r->out.return_authenticator = return_authenticator;
r->out.validation = r2.out.validation;
@@ -685,7 +624,7 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
ZERO_STRUCT(r2);
r2.in.server_name = r->in.server_name;
- r2.in.workstation = r->in.workstation;
+ r2.in.computer_name = r->in.computer_name;
r2.in.credential = r->in.credential;
r2.in.return_authenticator = r->in.return_authenticator;
r2.in.logon_level = r->in.logon_level;
@@ -947,7 +886,6 @@ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx, struct ldb_message *
static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonGetDomainInfo *r)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
const char * const attrs[] = { "dnsDomain", "objectSid",
"objectGUID", "flatName", "securityIdentifier",
NULL };
@@ -960,7 +898,7 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
const char *local_domain;
- status = netr_creds_server_step_check(pipe_state, mem_ctx,
+ status = netr_creds_server_step_check(r->in.computer_name, mem_ctx,
r->in.credential,
r->out.return_authenticator,
NULL);
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 7919e7c441..79e85cce57 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -539,7 +539,7 @@ BOOL test_netlogon_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
- r.in.workstation = cli_credentials_get_workstation(credentials);
+ r.in.computer_name = cli_credentials_get_workstation(credentials);
r.in.credential = &auth;
r.in.return_authenticator = &auth2;
r.in.logon_level = 2;
@@ -564,7 +564,6 @@ BOOL test_netlogon_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
printf("Credential chaining failed\n");
ret = False;
}
-
}
r.in.credential = NULL;
@@ -573,7 +572,7 @@ BOOL test_netlogon_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.validation_level = i;
- printf("Testing SamLogon with validation level %d\n", i);
+ printf("Testing SamLogon with validation level %d and a NULL credential\n", i);
status = dcerpc_netr_LogonSamLogon(p, mem_ctx, &r);
if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
diff --git a/source4/torture/rpc/samlogon.c b/source4/torture/rpc/samlogon.c
index 69c9ff6ea9..03bec56ab6 100644
--- a/source4/torture/rpc/samlogon.c
+++ b/source4/torture/rpc/samlogon.c
@@ -1335,17 +1335,17 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
generate_random_buffer(samlogon_state.chall.data, 8);
samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
- samlogon_state.r_flags.in.workstation = TEST_MACHINE_NAME;
+ samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
samlogon_state.r_flags.in.credential = &samlogon_state.auth;
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(fn_ctx, "\\\\%s", dcerpc_server_name(p));
- samlogon_state.r_ex.in.workstation = TEST_MACHINE_NAME;
+ samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
samlogon_state.r_ex.in.flags = 0;
samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
- samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
+ samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
samlogon_state.r.in.credential = &samlogon_state.auth;
samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
@@ -1415,7 +1415,7 @@ BOOL test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
creds_client_authenticator(creds, &a);
r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
- r.in.workstation = TEST_MACHINE_NAME;
+ r.in.computer_name = TEST_MACHINE_NAME;
r.in.credential = &a;
r.in.return_authenticator = &ra;
r.in.logon_level = 5;
diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c
index afa47e5932..f0f19f0818 100644
--- a/source4/torture/rpc/samsync.c
+++ b/source4/torture/rpc/samsync.c
@@ -77,7 +77,7 @@ static NTSTATUS test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
}
r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
- r.in.workstation = workstation;
+ r.in.computer_name = workstation;
r.in.credential = &auth;
r.in.return_authenticator = &auth2;
r.in.logon_level = 2;
diff --git a/source4/torture/rpc/schannel.c b/source4/torture/rpc/schannel.c
index 80b223656d..3ad781c145 100644
--- a/source4/torture/rpc/schannel.c
+++ b/source4/torture/rpc/schannel.c
@@ -85,7 +85,7 @@ BOOL test_netlogon_ex_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
- r.in.workstation = cli_credentials_get_workstation(credentials);
+ r.in.computer_name = cli_credentials_get_workstation(credentials);
r.in.logon_level = 2;
r.in.logon.network = &ninfo;
r.in.flags = 0;
@@ -238,6 +238,7 @@ static BOOL test_schannel(TALLOC_CTX *mem_ctx,
struct dcerpc_pipe *p = NULL;
struct dcerpc_pipe *p_netlogon = NULL;
struct dcerpc_pipe *p_netlogon2 = NULL;
+ struct dcerpc_pipe *p_netlogon3 = NULL;
struct dcerpc_pipe *p_samr2 = NULL;
struct dcerpc_pipe *p_lsa = NULL;
struct creds_CredentialState *creds;
@@ -395,14 +396,37 @@ static BOOL test_schannel(TALLOC_CTX *mem_ctx,
/* Try the schannel-only SamLogonEx operation */
if (!test_netlogon_ex_ops(p_netlogon2, test_ctx, credentials, creds)) {
- printf("Failed to process schannel secured NETLOGON EX ops\n");
+ printf("Failed to process schannel secured NETLOGON EX ops (on fresh connection)\n");
ret = False;
}
/* And the more traditional style, proving that the
* credentials chaining state is fully present */
if (!test_netlogon_ops(p_netlogon2, test_ctx, credentials, creds)) {
- printf("Failed to process schannel secured NETLOGON EX ops\n");
+ printf("Failed to process schannel secured NETLOGON ops (on fresh connection)\n");
+ ret = False;
+ }
+
+ /* Drop the socket, we want to start from scratch (again) */
+ talloc_free(p_samr2);
+
+ /* We don't want schannel for this test */
+ b->flags &= ~DCERPC_AUTH_OPTIONS;
+
+ status = dcerpc_pipe_connect_b(test_ctx, &p_netlogon3, b, &dcerpc_table_netlogon,
+ credentials, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to connect without schannel: %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+ if (test_netlogon_ex_ops(p_netlogon3, test_ctx, credentials, creds)) {
+ printf("Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)\n");
+ ret = False;
+ }
+
+ if (!test_netlogon_ops(p_netlogon3, test_ctx, credentials, creds)) {
+ printf("Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth\n");
ret = False;
}
diff --git a/source4/winbind/wb_pam_auth.c b/source4/winbind/wb_pam_auth.c
index 593cd22291..f85cfd1f1a 100644
--- a/source4/winbind/wb_pam_auth.c
+++ b/source4/winbind/wb_pam_auth.c
@@ -153,7 +153,7 @@ static void pam_auth_crap_recv_domain(struct composite_context *ctx)
ZERO_STRUCT(state->auth2);
- state->r.in.workstation =
+ state->r.in.computer_name =
cli_credentials_get_workstation(domain->schannel_creds);
state->r.in.credential = &state->auth;
state->r.in.return_authenticator = &state->auth2;