diff --git a/install/conf/ipa.conf b/install/conf/ipa.conf index d41f9eb06..696e5aab1 100644 --- a/install/conf/ipa.conf +++ b/install/conf/ipa.conf @@ -48,7 +48,8 @@ WSGISocketPrefix /run/httpd/wsgi # Configure mod_wsgi handler for /ipa WSGIDaemonProcess ipa processes=2 threads=1 maximum-requests=500 \ - user=ipaapi group=ipaapi display-name=%{GROUP} socket-timeout=2147483647 + user=ipaapi group=ipaapi display-name=%{GROUP} socket-timeout=2147483647 \ + lang=C.UTF-8 locale=C.UTF-8 WSGIImportScript /usr/share/ipa/wsgi.py process-group=ipa application-group=ipa WSGIScriptAlias /ipa /usr/share/ipa/wsgi.py WSGIScriptReloading Off diff --git a/install/share/ipa-httpd.conf.template b/install/share/ipa-httpd.conf.template index 39bcfcca7..210d5d388 100644 --- a/install/share/ipa-httpd.conf.template +++ b/install/share/ipa-httpd.conf.template @@ -4,4 +4,5 @@ Environment=KRB5CCNAME=$KRB5CC_HTTPD Environment=GSS_USE_PROXY=yes Environment=KDCPROXY_CONFIG=$KDCPROXY_CONFIG +Environment=LC_ALL=C.UTF-8 ExecStartPre=$IPA_HTTPD_KDCPROXY diff --git a/ipalib/errors.py b/ipalib/errors.py index fb7fb4e2a..3a40fa28d 100644 --- a/ipalib/errors.py +++ b/ipalib/errors.py @@ -452,6 +452,18 @@ class EnvironmentError(PublicError): errno = 912 + +class SystemEncodingError(PublicError): + """ + **913** Raised when system encoding is not UTF-8 + """ + + errno = 913 + format = _( + "System encoding must be UTF-8, '%(encoding)s' is not supported. " + "Set LC_ALL=\"C.UTF-8\", or LC_ALL=\"\" and LC_CTYPE=\"C.UTF-8\"." + ) + ############################################################################## # 1000 - 1999: Authentication errors class AuthenticationError(PublicError): diff --git a/ipalib/plugable.py b/ipalib/plugable.py index 66a200ea3..b1fba368d 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -485,6 +485,11 @@ class API(ReadOnly): handler.setFormatter(ipa_log_manager.Formatter(LOGGING_FORMAT_STDERR)) root_logger.addHandler(handler) + # check after logging is set up but before we create files. + fse = sys.getfilesystemencoding() + if fse.lower() not in {'utf-8', 'utf8'}: + raise errors.SystemEncodingError(encoding=fse) + # Add file handler: if self.env.mode in ('dummy', 'unit_test'): return # But not if in unit-test mode diff --git a/ipatests/test_cmdline/test_cli.py b/ipatests/test_cmdline/test_cli.py index 4585126d9..eec0be739 100644 --- a/ipatests/test_cmdline/test_cli.py +++ b/ipatests/test_cmdline/test_cli.py @@ -1,6 +1,8 @@ -import shlex -import sys import contextlib +import os +import shlex +import subprocess +import sys import nose import six @@ -15,6 +17,8 @@ if six.PY3: TEST_ZONE = u'zoneadd.%(domain)s' % api.env +HERE = os.path.abspath(os.path.dirname(__file__)) +BASE_DIR = os.path.abspath(os.path.join(HERE, os.pardir, os.pardir)) @pytest.mark.tier0 class TestCLIParsing(object): @@ -305,3 +309,22 @@ class TestCLIParsing(object): if not adtrust_is_enabled: mockldap.del_entry(adtrust_dn) + + +def test_cli_fsencoding(): + # https://pagure.io/freeipa/issue/5887 + env = { + key: value for key, value in os.environ.items() + if not key.startswith(('LC_', 'LANG')) + } + env['LC_ALL'] = 'C' + env['PYTHONPATH'] = BASE_DIR + p = subprocess.Popen( + [sys.executable, '-m', 'ipaclient', 'help'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env, + ) + out, err = p.communicate() + assert p.returncode > 0, (out, err) + assert b'System encoding must be UTF-8' in err, (out, err)