s4:schannel more readable check logic
authorSimo Sorce <idra@samba.org>
Thu, 18 Feb 2010 15:26:24 +0000 (10:26 -0500)
committerSimo Sorce <idra@samba.org>
Tue, 23 Feb 2010 17:46:50 +0000 (12:46 -0500)
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
libcli/auth/schannel_state_proto.h
source4/rpc_server/netlogon/dcerpc_netlogon.c

index ba3d96fcf7eab6e32a35bfa13d1e0402ad8d8974..2919ed63692571fff78c79466d175231154972ba 100644 (file)
@@ -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;
index d0a071c876d59225902066e9757d6bae2233a4f4..da5ebb3b7b2b139c9f03715ecdddfeccc1a27523 100644 (file)
@@ -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);
index 65d8c7b8df3c9b011e113c7485ab5732ff985ef2..27186d8f0f0d14bd058809e7492a2ab5e758daf7 100644 (file)
@@ -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);