123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- From d68424b5ef92f5810760f90e9eeb664572a61e4e Mon Sep 17 00:00:00 2001
- From: Stefan Metzmacher <metze@samba.org>
- Date: Tue, 15 Dec 2015 14:49:36 +0100
- Subject: [PATCH 01/10] CVE-2016-2118: s3: rpcclient: change the default auth
- level from DCERPC_AUTH_LEVEL_CONNECT to DCERPC_AUTH_LEVEL_INTEGRITY
- ncacn_ip_tcp:server should get the same protection as ncacn_np:server
- if authentication and smb signing is used.
- BUG: https://bugzilla.samba.org/show_bug.cgi?id=11616
- Signed-off-by: Stefan Metzmacher <metze@samba.org>
- (cherry picked from commit dab41dee8a4fb27dbf3913b0e44a4cc726e3ac98)
- ---
- source3/rpcclient/rpcclient.c | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
- --- a/source3/rpcclient/rpcclient.c
- +++ b/source3/rpcclient/rpcclient.c
- @@ -1062,10 +1062,9 @@ out_free:
- }
- }
- if (pipe_default_auth_type != DCERPC_AUTH_TYPE_NONE) {
- - /* If neither Integrity or Privacy are requested then
- - * Use just Connect level */
- + /* If nothing is requested then default to integrity */
- if (pipe_default_auth_level == DCERPC_AUTH_LEVEL_NONE) {
- - pipe_default_auth_level = DCERPC_AUTH_LEVEL_CONNECT;
- + pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
- }
- }
-
- --- a/source4/librpc/rpc/dcerpc_util.c
- +++ b/source4/librpc/rpc/dcerpc_util.c
- @@ -593,15 +593,15 @@ struct composite_context *dcerpc_pipe_au
-
- /* Perform an authenticated DCE-RPC bind
- */
- - if (!(conn->flags & (DCERPC_SIGN|DCERPC_SEAL))) {
- + if (!(conn->flags & (DCERPC_CONNECT|DCERPC_SEAL))) {
- /*
- we are doing an authenticated connection,
- - but not using sign or seal. We must force
- - the CONNECT dcerpc auth type as a NONE auth
- - type doesn't allow authentication
- - information to be passed.
- + which needs to use [connect], [sign] or [seal].
- + If nothing is specified, we default to [sign] now.
- + This give roughly the same protection as
- + ncacn_np with smb signing.
- */
- - conn->flags |= DCERPC_CONNECT;
- + conn->flags |= DCERPC_SIGN;
- }
-
- if (s->binding->flags & DCERPC_AUTH_SPNEGO) {
- --- /dev/null
- +++ b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml
- @@ -0,0 +1,22 @@
- +<samba:parameter name="allow dcerpc auth level connect"
- + context="G"
- + type="boolean"
- + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
- +<description>
- + <para>This option controls whether DCERPC services are allowed to
- + be used with DCERPC_AUTH_LEVEL_CONNECT, which provides authentication,
- + but no per message integrity nor privacy protection.</para>
- +
- + <para>The behavior can be controlled per interface name (e.g. lsarpc, netlogon, samr, srvsvc,
- + winreg, wkssvc ...) by using 'allow dcerpc auth level connect:interface = no' as option.</para>
- +
- + <para>This option yields precedence to the implentation specific restrictions.
- + E.g. the drsuapi and backupkey protocols require DCERPC_AUTH_LEVEL_PRIVACY.
- + While others like samr and lsarpc have a hardcoded default of <constant>no</constant>.
- + </para>
- +</description>
- +
- +<value type="default">no</value>
- +<value type="example">yes</value>
- +
- +</samba:parameter>
- --- a/source3/include/proto.h
- +++ b/source3/include/proto.h
- @@ -1821,6 +1821,7 @@ char* lp_perfcount_module(void);
- void lp_set_passdb_backend(const char *backend);
- void widelinks_warning(int snum);
- char *lp_ncalrpc_dir(void);
- +bool lp_allow_dcerpc_auth_level_connect(void);
-
- /* The following definitions come from param/loadparm_server_role.c */
-
- --- a/source3/param/loadparm.c
- +++ b/source3/param/loadparm.c
- @@ -355,6 +355,7 @@ struct global {
- bool bUseMmap;
- bool bHostnameLookups;
- bool bUnixExtensions;
- + bool bAllowDcerpcAuthLevelConnect;
- bool bDisableNetbios;
- char * szDedicatedKeytabFile;
- int iKerberosMethod;
- @@ -2303,6 +2304,15 @@ static struct parm_struct parm_table[] =
- .flags = FLAG_ADVANCED,
- },
- {
- + .label = "allow dcerpc auth level connect",
- + .type = P_BOOL,
- + .p_class = P_GLOBAL,
- + .ptr = &Globals.bAllowDcerpcAuthLevelConnect,
- + .special = NULL,
- + .enum_list = NULL,
- + .flags = FLAG_ADVANCED,
- + },
- + {
- .label = "use spnego",
- .type = P_BOOL,
- .p_class = P_GLOBAL,
- @@ -5371,6 +5381,8 @@ static void init_globals(bool reinit_glo
- Globals.bClientNTLMv2Auth = True; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
- /* Note, that we will also use NTLM2 session security (which is different), if it is available */
-
- + Globals.bAllowDcerpcAuthLevelConnect = false; /* we don't allow this by default */
- +
- Globals.map_to_guest = 0; /* By Default, "Never" */
- Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
- Globals.enhanced_browsing = true;
- @@ -5745,6 +5757,7 @@ FN_GLOBAL_INTEGER(lp_username_map_cache_
-
- FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
-
- +FN_GLOBAL_BOOL(lp_allow_dcerpc_auth_level_connect, &Globals.bAllowDcerpcAuthLevelConnect)
- FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
- FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
- FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
- --- a/source3/include/ntdomain.h
- +++ b/source3/include/ntdomain.h
- @@ -89,6 +89,10 @@ typedef struct pipe_rpc_fns {
- uint32 context_id;
- struct ndr_syntax_id syntax;
-
- + /*
- + * shall we allow "connect" auth level for this interface ?
- + */
- + bool allow_connect;
- } PIPE_RPC_FNS;
-
- /*
- --- a/source3/rpc_server/srv_pipe.c
- +++ b/source3/rpc_server/srv_pipe.c
- @@ -44,6 +44,11 @@
- #include "rpc_server/srv_pipe.h"
- #include "../librpc/gen_ndr/ndr_dcerpc.h"
- #include "../librpc/ndr/ndr_dcerpc.h"
- +#include "../librpc/gen_ndr/ndr_samr.h"
- +#include "../librpc/gen_ndr/ndr_lsa.h"
- +#include "../librpc/gen_ndr/ndr_netlogon.h"
- +#include "../librpc/gen_ndr/ndr_epmapper.h"
- +#include "../librpc/gen_ndr/ndr_echo.h"
-
- #undef DBGC_CLASS
- #define DBGC_CLASS DBGC_RPC_SRV
- @@ -340,6 +345,8 @@ static bool check_bind_req(struct pipes_
- uint32 context_id)
- {
- struct pipe_rpc_fns *context_fns;
- + const char *interface_name = NULL;
- + bool ok;
-
- DEBUG(3,("check_bind_req for %s\n",
- get_pipe_name_from_syntax(talloc_tos(), abstract)));
- @@ -390,12 +397,57 @@ static bool check_bind_req(struct pipes_
- return False;
- }
-
- + interface_name = get_pipe_name_from_syntax(talloc_tos(),
- + abstract);
- +
- + 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();
- + /*
- + * for the samr and the lsarpc interfaces we don't allow "connect"
- + * auth_level by default.
- + */
- + ok = ndr_syntax_id_equal(abstract, &ndr_table_samr.syntax_id);
- + if (ok) {
- + context_fns->allow_connect = false;
- + }
- + ok = ndr_syntax_id_equal(abstract, &ndr_table_lsarpc.syntax_id);
- + if (ok) {
- + context_fns->allow_connect = false;
- + }
- + ok = ndr_syntax_id_equal(abstract, &ndr_table_netlogon.syntax_id);
- + if (ok) {
- + context_fns->allow_connect = false;
- + }
- + /*
- + * for the epmapper and echo interfaces we allow "connect"
- + * auth_level by default.
- + */
- + ok = ndr_syntax_id_equal(abstract, &ndr_table_epmapper.syntax_id);
- + if (ok) {
- + context_fns->allow_connect = true;
- + }
- + ok = ndr_syntax_id_equal(abstract, &ndr_table_rpcecho.syntax_id);
- + if (ok) {
- + context_fns->allow_connect = true;
- + }
- + /*
- + * 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 );
- @@ -1736,6 +1788,7 @@ static bool api_pipe_request(struct pipe
- TALLOC_CTX *frame = talloc_stackframe();
- bool ret = False;
- PIPE_RPC_FNS *pipe_fns;
- + const char *interface_name = NULL;
-
- if (!p->pipe_bound) {
- DEBUG(1, ("Pipe not bound!\n"));
- @@ -1757,8 +1810,36 @@ static bool api_pipe_request(struct pipe
- return false;
- }
-
- + interface_name = get_pipe_name_from_syntax(talloc_tos(),
- + &pipe_fns->syntax);
- +
- + SMB_ASSERT(interface_name != NULL);
- +
- DEBUG(5, ("Requested \\PIPE\\%s\n",
- - get_pipe_name_from_syntax(talloc_tos(), &pipe_fns->syntax)));
- + interface_name));
- +
- + 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) {
- + 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),
- + p->client_id->name));
- +
- + 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"));
- --- a/source3/selftest/knownfail
- +++ b/source3/selftest/knownfail
- @@ -18,3 +18,5 @@ samba3.posix_s3.nbt.dgram.*netlogon2
- samba3.*rap.sam.*.useradd # Not provided by Samba 3
- samba3.*rap.sam.*.userdelete # Not provided by Samba 3
- samba3.*rap.basic.*.netsessiongetinfo # Not provided by Samba 3
- +samba3.blackbox.rpcclient.over.ncacn_np.with.*connect.* # we don't allow auth_level_connect anymore
- +samba3.posix_s3.rpc.lsa.lookupsids.*ncacn_ip_tcp.*connect.* # we don't allow auth_level_connect anymore
- --- a/source3/selftest/tests.py
- +++ b/source3/selftest/tests.py
- @@ -201,6 +201,8 @@ if sub.returncode == 0:
- plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmpguest -U$USERNAME%$PASSWORD')
- elif t == "raw.samba3posixtimedlock":
- plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmpguest -U$USERNAME%$PASSWORD --option=torture:localdir=$SELFTEST_PREFIX/dc/share')
- + elif t == "rpc.samr.passwords.validate":
- + plansmbtorturetestsuite(t, "s3dc", 'ncacn_np:$SERVER_IP[seal] -U$USERNAME%$PASSWORD', 'over ncacn_np ')
- else:
- plansmbtorturetestsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
-
- --- a/source3/rpc_server/samr/srv_samr_nt.c
- +++ b/source3/rpc_server/samr/srv_samr_nt.c
- @@ -6628,6 +6628,11 @@ NTSTATUS _samr_ValidatePassword(struct p
- struct samr_GetDomPwInfo pw;
- struct samr_PwInfo dom_pw_info;
-
- + if (p->auth.auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
- + p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
- + return NT_STATUS_ACCESS_DENIED;
- + }
- +
- if (r->in.level < 1 || r->in.level > 3) {
- return NT_STATUS_INVALID_INFO_CLASS;
- }
|