]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2016-2118: s3:rpc_server: make use of "allow dcerpc auth level connect"
authorStefan Metzmacher <metze@samba.org>
Fri, 18 Mar 2016 03:40:30 +0000 (04:40 +0100)
committerStefan Metzmacher <metze@samba.org>
Wed, 30 Mar 2016 02:08:52 +0000 (04:08 +0200)
With this option turned off we only allow DCERPC_AUTH_LEVEL_{NONE,INTEGRITY,PRIVACY},
this means the reject any request with AUTH_LEVEL_CONNECT with ACCESS_DENIED.

We sadly need to keep this enabled by default for now.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11616

Pair-Programmed-With: Günther Deschner <gd@samba.org>

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Günther Deschner <gd@samba.org>
source3/rpc_server/rpc_ncacn_np.c
source3/rpc_server/rpc_pipes.h
source3/rpc_server/srv_pipe.c

index d504847b4345c1f66d35898dbc3552bc07575d24..5514956b9837795ae81f7fa6a401197a4692964d 100644 (file)
@@ -224,7 +224,7 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
-       context_fns = talloc(p, struct pipe_rpc_fns);
+       context_fns = talloc_zero(p, struct pipe_rpc_fns);
        if (context_fns == NULL) {
                DEBUG(0,("talloc() failed!\n"));
                TALLOC_FREE(p);
index e65209aefc030b6fc7e0ee6e74f40a1646e355eb..14b870532c828422f3fd64f3acc48b0947a5f20c 100644 (file)
@@ -94,6 +94,10 @@ struct pipe_rpc_fns {
        uint32_t context_id;
        struct ndr_syntax_id syntax;
 
+       /*
+        * shall we allow "connect" auth level for this interface ?
+        */
+       bool allow_connect;
 };
 
 /*
index 4ffaa0dbb036c3f5ad27f9aa52ff0f14395b3c17..49026765a1495682dd7aa2820a2c444d24387f86 100644 (file)
@@ -44,6 +44,7 @@
 #include "librpc/ndr/ndr_table.h"
 #include "auth/gensec/gensec.h"
 #include "librpc/ndr/ndr_dcerpc.h"
+#include "lib/tsocket/tsocket.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -338,6 +339,7 @@ static bool check_bind_req(struct pipes_struct *p,
 {
        struct pipe_rpc_fns *context_fns;
        bool ok;
+       const char *interface_name = NULL;
 
        DEBUG(3,("check_bind_req for %s\n",
                 ndr_interface_name(&abstract->uuid,
@@ -359,18 +361,34 @@ static bool check_bind_req(struct pipes_struct *p,
                return false;
        }
 
-       context_fns = talloc(p, struct pipe_rpc_fns);
+       context_fns = talloc_zero(p, struct pipe_rpc_fns);
        if (context_fns == NULL) {
                DEBUG(0,("check_bind_req: talloc() failed!\n"));
                return false;
        }
 
+       interface_name = ndr_interface_name(&abstract->uuid,
+                                           abstract->if_version);
+       SMB_ASSERT(interface_name != NULL);
+
        context_fns->next = context_fns->prev = NULL;
        context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(abstract);
        context_fns->cmds = rpc_srv_get_pipe_cmds(abstract);
        context_fns->context_id = context_id;
        context_fns->syntax = *abstract;
 
+       context_fns->allow_connect = lp_allow_dcerpc_auth_level_connect();
+       /*
+        * every interface can be modified to allow "connect" auth_level by
+        * using a parametric option like:
+        * allow dcerpc auth level connect:<interface>
+        * e.g.
+        * allow dcerpc auth level connect:samr = yes
+        */
+       context_fns->allow_connect = lp_parm_bool(-1,
+               "allow dcerpc auth level connect",
+               interface_name, context_fns->allow_connect);
+
        /* add to the list of open contexts */
 
        DLIST_ADD( p->contexts, context_fns );
@@ -1174,6 +1192,7 @@ static bool api_pipe_request(struct pipes_struct *p,
        TALLOC_CTX *frame = talloc_stackframe();
        bool ret = False;
        struct pipe_rpc_fns *pipe_fns;
+       const char *interface_name = NULL;
 
        if (!p->pipe_bound) {
                DEBUG(1, ("Pipe not bound!\n"));
@@ -1194,6 +1213,37 @@ static bool api_pipe_request(struct pipes_struct *p,
                return false;
        }
 
+       interface_name = ndr_interface_name(&pipe_fns->syntax.uuid,
+                                           pipe_fns->syntax.if_version);
+       SMB_ASSERT(interface_name != NULL);
+
+       switch (p->auth.auth_level) {
+       case DCERPC_AUTH_LEVEL_NONE:
+       case DCERPC_AUTH_LEVEL_INTEGRITY:
+       case DCERPC_AUTH_LEVEL_PRIVACY:
+               break;
+       default:
+               if (!pipe_fns->allow_connect) {
+                       char *addr;
+
+                       addr = tsocket_address_string(p->remote_address, frame);
+
+                       DEBUG(1, ("%s: restrict auth_level_connect access "
+                                 "to [%s] with auth[type=0x%x,level=0x%x] "
+                                 "on [%s] from [%s]\n",
+                                 __func__, interface_name,
+                                 p->auth.auth_type,
+                                 p->auth.auth_level,
+                                 derpc_transport_string_by_transport(p->transport),
+                                 addr));
+
+                       setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED));
+                       TALLOC_FREE(frame);
+                       return true;
+               }
+               break;
+       }
+
        if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) {
                DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n"));
                setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED));
@@ -1209,9 +1259,7 @@ static bool api_pipe_request(struct pipes_struct *p,
                return false;
        }
 
-       DEBUG(5, ("Requested %s rpc service\n",
-                 ndr_interface_name(&pipe_fns->syntax.uuid,
-                                    pipe_fns->syntax.if_version)));
+       DEBUG(5, ("Requested %s rpc service\n", interface_name));
 
        ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds,
                         &pipe_fns->syntax);