]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2016-2111: s4:rpc_server: implement 'server schannel = yes' restriction
authorStefan Metzmacher <metze@samba.org>
Wed, 9 Mar 2016 14:31:23 +0000 (15:31 +0100)
committerStefan Metzmacher <metze@samba.org>
Mon, 28 Mar 2016 22:42:17 +0000 (00:42 +0200)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11749

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Günther Deschner <gd@samba.org>
source4/rpc_server/netlogon/dcerpc_netlogon.c

index b2f0073d0912e0a3cee58ba673192428ec02fccc..045908882d3f0920230766cd5febcbf3c2c73253 100644 (file)
@@ -126,6 +126,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
        bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx);
        bool reject_des_client = !allow_nt4_crypto;
        bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx);
+       int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
+       bool reject_none_rpc = (schannel == true);
 
        ZERO_STRUCTP(r->out.return_credentials);
        *r->out.rid = 0;
@@ -198,6 +200,10 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
 
        negotiate_flags = *r->in.negotiate_flags & server_flags;
 
+       if (negotiate_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
+               reject_none_rpc = false;
+       }
+
        if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
                reject_des_client = false;
        }
@@ -234,6 +240,14 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca
         */
        *r->out.negotiate_flags = negotiate_flags;
 
+       if (reject_none_rpc) {
+               /* schannel must be used, but client did not offer it. */
+               DEBUG(0,("%s: schannel required but client failed "
+                       "to offer it. Client was %s\n",
+                       __func__, r->in.account_name));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        switch (r->in.secure_channel_type) {
        case SEC_CHAN_WKSTA:
        case SEC_CHAN_DNS_DOMAIN:
@@ -488,7 +502,8 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc
 {
        NTSTATUS nt_status;
        struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
-       bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
+       int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx);
+       bool schannel_global_required = (schannel == true);
 
        if (schannel_global_required) {
                nt_status = schannel_check_required(auth_info,