summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcli/auth/schannel_state_ldb.c10
-rw-r--r--libcli/auth/schannel_state_proto.h2
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c56
3 files changed, 44 insertions, 24 deletions
diff --git a/libcli/auth/schannel_state_ldb.c b/libcli/auth/schannel_state_ldb.c
index ba3d96fcf7..2919ed6369 100644
--- a/libcli/auth/schannel_state_ldb.c
+++ b/libcli/auth/schannel_state_ldb.c
@@ -264,8 +264,6 @@ NTSTATUS schannel_fetch_session_key_ldb(struct ldb_context *ldb,
NTSTATUS schannel_creds_server_step_check_ldb(struct ldb_context *ldb,
TALLOC_CTX *mem_ctx,
const char *computer_name,
- bool schannel_required_for_call,
- bool schannel_in_use,
struct netr_Authenticator *received_authenticator,
struct netr_Authenticator *return_authenticator,
struct netlogon_creds_CredentialState **creds_out)
@@ -277,14 +275,6 @@ NTSTATUS schannel_creds_server_step_check_ldb(struct ldb_context *ldb,
/* If we are flaged that schannel is required for a call, and
* it is not in use, then make this an error */
- /* It would be good to make this mandetory once schannel is
- * negoiated, but this is not what windows does */
- if (schannel_required_for_call && !schannel_in_use) {
- DEBUG(0,("schannel_creds_server_step_check: client %s not using schannel for netlogon, despite negotiating it\n",
- creds->computer_name ));
- return NT_STATUS_ACCESS_DENIED;
- }
-
ret = ldb_transaction_start(ldb);
if (ret != 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
diff --git a/libcli/auth/schannel_state_proto.h b/libcli/auth/schannel_state_proto.h
index d0a071c876..da5ebb3b7b 100644
--- a/libcli/auth/schannel_state_proto.h
+++ b/libcli/auth/schannel_state_proto.h
@@ -21,8 +21,6 @@ NTSTATUS schannel_fetch_session_key_ldb(struct ldb_context *ldb,
NTSTATUS schannel_creds_server_step_check_ldb(struct ldb_context *ldb,
TALLOC_CTX *mem_ctx,
const char *computer_name,
- bool schannel_required_for_call,
- bool schannel_in_use,
struct netr_Authenticator *received_authenticator,
struct netr_Authenticator *return_authenticator,
struct netlogon_creds_CredentialState **creds_out);
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 65d8c7b8df..27186d8f0f 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -307,15 +307,43 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca
}
/*
- Validate an incoming authenticator against the credentials for the remote machine.
+ * NOTE: The following functions are nearly identical to the ones available in
+ * source3/rpc_server/srv_nelog_nt.c
+ * The reason we keep 2 copies is that they use different structures to
+ * represent the auth_info and the decrpc pipes.
+ */
- The credentials are (re)read and from the schannel database, and
- written back after the caclulations are performed.
+/*
+ * If schannel is required for this call test that it actually is available.
+ */
+static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
+ const char *computer_name,
+ bool integrity, bool privacy)
+{
- The creds_out parameter (if not NULL) returns the credentials, if
- the caller needs some of that information.
+ if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+ if (!privacy && !integrity) {
+ return NT_STATUS_OK;
+ }
+
+ if ((!privacy && integrity) &&
+ auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
+ return NT_STATUS_OK;
+ }
+
+ if ((privacy || integrity) &&
+ auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+ return NT_STATUS_OK;
+ }
+ }
+
+ /* test didn't pass */
+ DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
+ computer_name));
+
+ return NT_STATUS_ACCESS_DENIED;
+}
-*/
static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
const char *computer_name,
@@ -325,11 +353,17 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
{
NTSTATUS nt_status;
struct ldb_context *ldb;
+ struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
- bool schannel_in_use = dce_call->conn->auth_state.auth_info
- && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL
- && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY
- || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY);
+
+ if (schannel_global_required) {
+ nt_status = schannel_check_required(auth_info,
+ computer_name,
+ true, false);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+ }
ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
if (!ldb) {
@@ -337,8 +371,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
}
nt_status = schannel_creds_server_step_check_ldb(ldb, mem_ctx,
computer_name,
- schannel_global_required,
- schannel_in_use,
received_authenticator,
return_authenticator, creds_out);
talloc_unlink(mem_ctx, ldb);