From 8e2f5fe7c5bc0fce0564c751a68e0feb370e0857 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 18 Feb 2010 10:26:24 -0500 Subject: [PATCH] s4:schannel more readable check logic Make the initial schannel check logic more understandable. Make it easy to define different policies depending on the caller's security requirements (Integrity/Privacy/Both/None) This is the same change applied to s3 --- libcli/auth/schannel_state_ldb.c | 10 ---- libcli/auth/schannel_state_proto.h | 2 - source4/rpc_server/netlogon/dcerpc_netlogon.c | 56 +++++++++++++++---- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/libcli/auth/schannel_state_ldb.c b/libcli/auth/schannel_state_ldb.c index ba3d96fcf7e..2919ed63692 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 d0a071c876d..da5ebb3b7b2 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 65d8c7b8df3..27186d8f0f0 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); -- 2.34.1