s4:rpc_server: set the full DCERPC_BIND_NAK_REASON_* in dcesrv_bind()
authorStefan Metzmacher <metze@samba.org>
Wed, 31 Aug 2016 19:39:25 +0000 (21:39 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Wed, 26 Oct 2016 09:20:14 +0000 (11:20 +0200)
This is required in order to support DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE
vs. DCERPC_BIND_NAK_REASON_INVALID_CHECKSUM.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source4/rpc_server/dcerpc_server.c
source4/rpc_server/dcesrv_auth.c

index 2528a84ee884db14dfca588427fa3e1b8dca3485..0ddd3b0a7b8932c1a7ea5723a56d4a6f8b5e6c19 100644 (file)
@@ -802,21 +802,20 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
 
                TALLOC_FREE(call->context);
 
-               if (call->fault_code == DCERPC_NCA_S_PROTO_ERROR) {
-                       return dcesrv_bind_nak(call,
-                       DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
-               }
-
-               if (auth->auth_level != DCERPC_AUTH_LEVEL_NONE) {
+               if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
                        /*
-                        * We only give INVALID_AUTH_TYPE if the auth_level was
-                        * valid.
+                        * With DCERPC_AUTH_LEVEL_NONE, we get the
+                        * reject_reason in auth->auth_context_id.
                         */
-                       return dcesrv_bind_nak(call,
-                                       DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE);
+                       return dcesrv_bind_nak(call, auth->auth_context_id);
                }
+
+               /*
+                * This must a be a temporary failure e.g. talloc or invalid
+                * configuration, e.g. no machine account.
+                */
                return dcesrv_bind_nak(call,
-                                       DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
+                               DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
        }
 
        /* setup a bind_ack */
index 74a62dfa9b756ee9aed7d08d734ff0847a0657f7..cc244430d9922436f88816abcff8a71fa8928f8c 100644 (file)
@@ -57,11 +57,16 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
                                          NULL, true);
        if (!NT_STATUS_IS_OK(status)) {
                /*
-                * This will cause a
-                * DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED
-                * in the caller
+                * Setting DCERPC_AUTH_LEVEL_NONE,
+                * gives the caller the reject_reason
+                * as auth_context_id.
+                *
+                * Note: DCERPC_AUTH_LEVEL_NONE == 1
                 */
-               call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
+               auth->auth_type = DCERPC_AUTH_TYPE_NONE;
+               auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+               auth->auth_context_id =
+                       DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED;
                return false;
        }
 
@@ -78,14 +83,14 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
        default:
                /*
                 * Setting DCERPC_AUTH_LEVEL_NONE,
-                * gives the caller a chance to decide what
-                * reject_reason to use
+                * gives the caller the reject_reason
+                * as auth_context_id.
                 *
                 * Note: DCERPC_AUTH_LEVEL_NONE == 1
                 */
                auth->auth_type = DCERPC_AUTH_TYPE_NONE;
                auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
-               auth->auth_context_id = 0;
+               auth->auth_context_id = DCERPC_BIND_NAK_REASON_NOT_SPECIFIED;
                return false;
        }
 
@@ -133,10 +138,32 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call)
        status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_type,
                                               auth->auth_level);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: auth_type=%d, auth_level=%d: %s\n",
-                         (int)auth->auth_type,
+               const char *backend_name =
+                       gensec_get_name_by_authtype(auth->gensec_security,
+                                                   auth->auth_type);
+
+               DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: "
+                         "auth_type=%d (%s), auth_level=%d: %s\n",
+                         (int)auth->auth_type, backend_name,
                          (int)auth->auth_level,
                          nt_errstr(status)));
+
+               /*
+                * Setting DCERPC_AUTH_LEVEL_NONE,
+                * gives the caller the reject_reason
+                * as auth_context_id.
+                *
+                * Note: DCERPC_AUTH_LEVEL_NONE == 1
+                */
+               auth->auth_type = DCERPC_AUTH_TYPE_NONE;
+               auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+               if (backend_name != NULL) {
+                       auth->auth_context_id =
+                               DCERPC_BIND_NAK_REASON_INVALID_CHECKSUM;
+               } else {
+                       auth->auth_context_id =
+                               DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE;
+               }
                return false;
        }