From 5ac052f085c74f058703c5da29d59849c11e571f Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Thu, 3 Dec 2015 14:26:19 +0100 Subject: [PATCH 26/26] Workarounds for SELinux execmem violations in cryptography ipaserver.dcerpc uses M2Crypto again on Python 2.7 and Dogtag's pki.client no longer tries to use PyOpenSSL instead of Python's ssl module. Some dependencies like Dogtag's pki.client library and custodia use python-requsts to make HTTPS connection. python-requests prefers PyOpenSSL over Python's stdlib ssl module. PyOpenSSL is build on top of python-cryptography which trigger a execmem SELinux violation in the context of Apache HTTPD (httpd_execmem). When requests is imported, it always tries to import pyopenssl glue code from urllib3's contrib directory. The import of PyOpenSSL is enough to trigger the SELinux denial. A hack in wsgi.py prevents the import by raising an ImportError. --- freeipa.spec.in | 2 ++ install/share/wsgi.py | 14 ++++++++++++++ ipaserver/dcerpc.py | 32 +++++++++++++++++++++++--------- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/freeipa.spec.in b/freeipa.spec.in index a60d9b63f363773b6ca1b0969fa56b369a94092f..4fe8a911f0ae08882287bfea262064f5a2386ec1 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -66,6 +66,7 @@ BuildRequires: python-ldap BuildRequires: python-setuptools BuildRequires: python-nss BuildRequires: python-cryptography +BuildRequires: m2crypto BuildRequires: python-netaddr BuildRequires: python-gssapi >= 1.1.2 BuildRequires: python-rhsm @@ -322,6 +323,7 @@ Requires: keyutils Requires: pyOpenSSL Requires: python-nss >= 0.16 Requires: python-cryptography +Requires: m2crypto Requires: python-lxml Requires: python-netaddr Requires: python-libipa_hbac diff --git a/install/share/wsgi.py b/install/share/wsgi.py index ee9311e4eab8b95b5143170469cac7dc0b8b8e5e..ba42c343228da21f8e2ae9ea717450bada93359d 100644 --- a/install/share/wsgi.py +++ b/install/share/wsgi.py @@ -23,6 +23,20 @@ """ WSGI appliction for IPA server. """ +import sys + +# Some dependencies like Dogtag's pki.client library and custodia use +# python-requsts to make HTTPS connection. python-requests prefers +# PyOpenSSL over Python's stdlib ssl module. PyOpenSSL is build on top +# of python-cryptography which trigger a execmem SELinux violation +# in the context of Apache HTTPD (httpd_execmem). +# When requests is imported, it always tries to import pyopenssl glue +# code from urllib3's contrib directory. The import of PyOpenSSL is +# enough to trigger the SELinux denial. +# This hack prevents the import by raising an ImportError. + +sys.modules['request.packages.urllib3.contrib.pyopenssl'] = None + from ipalib import api from ipalib.config import Env from ipalib.constants import DEFAULT_CONFIG diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py index 2e412861ebc265a9b07c8634068151181a3e9b9e..15d8e192e397868a0bf623d8a23c4a2489126bcb 100644 --- a/ipaserver/dcerpc.py +++ b/ipaserver/dcerpc.py @@ -42,8 +42,6 @@ from samba.ndr import ndr_pack, ndr_print from samba import net import samba import random -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms -from cryptography.hazmat.backends import default_backend try: from ldap.controls import RequestControl as LDAPControl #pylint: disable=F0401 except ImportError: @@ -65,6 +63,29 @@ if six.PY3: unicode = str long = int +# Some versions of python-cryptography depend on python-cffi callbacks which +# are built on top of libffi's closure API. The closures require writeable +# and executable anonymous memory mappings, which violate SELinux execmem +# rules such as 'httpd_execmem'. Prefer M2Crypto on Python 2. +try: + from M2Crypto import RC4 +except ImportError: + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms + from cryptography.hazmat.backends import default_backend + + def arcfour_encrypt(key, data): + """RC4 with python-cryptography""" + algorithm = algorithms.ARC4(key) + cipher = Cipher(algorithm, mode=None, backend=default_backend()) + encryptor = cipher.encryptor() + return encryptor.update(data) +else: + def arcfour_encrypt(key, data): + """RC4 with M2Crypto""" + c = RC4.RC4(key) + return c.update(data) + + __doc__ = _(""" Classes to manage trust joins using DCE-RPC calls @@ -135,13 +156,6 @@ def assess_dcerpc_exception(num=None,message=None): return errors.RemoteRetrieveError(reason=reason) -def arcfour_encrypt(key, data): - algorithm = algorithms.ARC4(key) - cipher = Cipher(algorithm, mode=None, backend=default_backend()) - encryptor = cipher.encryptor() - return encryptor.update(data) - - class ExtendedDNControl(LDAPControl): # This class attempts to implement LDAP control that would work # with both python-ldap 2.4.x and 2.3.x, thus there is mix of properties -- 2.4.3