URL: https://github.com/freeipa/freeipa/pull/393
Author: MartinBasti
 Title: #393: [Py3] allow to run wsgi - part1
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/393/head:pr393
git checkout pr393
From 7916e9756da15bbeb06256101b8316c5e8dc9f80 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Wed, 11 Jan 2017 16:54:25 +0100
Subject: [PATCH 01/15] py3: session.py decode server name to str

This fix is temporal because Memcache will be removed soon, so it is
more workaround than fix

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/session.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipaserver/session.py b/ipaserver/session.py
index 85deb15..020dcc1 100644
--- a/ipaserver/session.py
+++ b/ipaserver/session.py
@@ -828,7 +828,7 @@ def get_server_statistics(self):
         result = {}
         stats = self.mc.get_stats()
         for server in stats:
-            match = self.mc_server_stat_name_re.search(server[0])
+            match = self.mc_server_stat_name_re.search(server[0].decode())
             if match:
                 name = match.group(1)
                 result[name] = server[1]

From be4ab4f89262f33d71b4bf29937deef09e2527e8 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Wed, 11 Jan 2017 17:13:52 +0100
Subject: [PATCH 02/15] py3: rpcserver: decode input because json requires
 string

json library parses string so input must be decoded

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/rpcserver.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index 1da4ec4..7f800ac 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -195,7 +195,7 @@ def read_input(environ):
         length = int(environ.get('CONTENT_LENGTH'))
     except (ValueError, TypeError):
         return
-    return environ['wsgi.input'].read(length)
+    return environ['wsgi.input'].read(length).decode('utf-8')
 
 
 def params_2_args_options(params):

From 11c15490e6ee911d386b94282300a2435b60e822 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Wed, 11 Jan 2017 17:15:49 +0100
Subject: [PATCH 03/15] Py3: Fix undefined variable

Variable 'e' has only local scope in except block in Py3

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/rpcserver.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index 7f800ac..306d085 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -404,7 +404,7 @@ def wsgi_execute(self, environ):
                       type(self).__name__,
                       principal,
                       name,
-                      type(e).__name__)
+                      type(error).__name__)
 
         version = options.get('version', VERSION_WITHOUT_CAPABILITIES)
         return self.marshal(result, error, _id, version)

From 2a8cd79a2291300d26470af2cd27dd197271a632 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Wed, 11 Jan 2017 17:24:16 +0100
Subject: [PATCH 04/15] py3: session: fix r/w ccache data

ccache contains binary data, so it should be read and write in binary
mode

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/session.py | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/ipaserver/session.py b/ipaserver/session.py
index 020dcc1..0f3a9ad 100644
--- a/ipaserver/session.py
+++ b/ipaserver/session.py
@@ -21,6 +21,7 @@
 import os
 import re
 import time
+import io
 
 # pylint: disable=import-error
 from six.moves.urllib.parse import urlparse
@@ -1228,9 +1229,8 @@ def load_ccache_data(ccache_name):
     scheme, name = krb5_parse_ccache(ccache_name)
     if scheme == 'FILE':
         root_logger.debug('reading ccache data from file "%s"', name)
-        src = open(name)
-        ccache_data = src.read()
-        src.close()
+        with io.open(name, "rb") as src:
+            ccache_data = src.read()
         return ccache_data
     else:
         raise ValueError('ccache scheme "%s" unsupported (%s)', scheme, ccache_name)
@@ -1239,9 +1239,8 @@ def bind_ipa_ccache(ccache_data, scheme='FILE'):
     if scheme == 'FILE':
         name = _get_krbccache_pathname()
         root_logger.debug('storing ccache data into file "%s"', name)
-        dst = open(name, 'w')
-        dst.write(ccache_data)
-        dst.close()
+        with io.open(name, 'wb') as dst:
+            dst.write(ccache_data)
     else:
         raise ValueError('ccache scheme "%s" unsupported', scheme)
 

From 36f849e2c876c6418db99d8cf72b54026d32a18f Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Thu, 12 Jan 2017 18:50:56 +0100
Subject: [PATCH 05/15] py3: WSGI executioners must return bytes in list

WSGI prints TypeError into error log when IPA doesn't return bytes in
list as result

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/rpcserver.py | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index 306d085..8a18f94 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -144,7 +144,7 @@ def not_found(self, environ, start_response, url, message):
         self.info('%s: URL="%s", %s', status, url, message)
         start_response(status, response_headers)
         output = _not_found_template % dict(url=escape(url))
-        return [output]
+        return [output.encode('utf-8')]
 
     def bad_request(self, environ, start_response, message):
         """
@@ -157,7 +157,7 @@ def bad_request(self, environ, start_response, message):
 
         start_response(status, response_headers)
         output = _bad_request_template % dict(message=escape(message))
-        return [output]
+        return [output.encode('utf-8')]
 
     def internal_error(self, environ, start_response, message):
         """
@@ -170,7 +170,7 @@ def internal_error(self, environ, start_response, message):
 
         start_response(status, response_headers)
         output = _internal_error_template % dict(message=escape(message))
-        return [output]
+        return [output.encode('utf-8')]
 
     def unauthorized(self, environ, start_response, message, reason):
         """
@@ -185,7 +185,7 @@ def unauthorized(self, environ, start_response, message, reason):
 
         start_response(status, response_headers)
         output = _unauthorized_template % dict(message=escape(message))
-        return [output]
+        return [output.encode('utf-8')]
 
 def read_input(environ):
     """
@@ -427,7 +427,7 @@ def __call__(self, environ, start_response):
         except Exception:
             self.exception('WSGI %s.__call__():', self.name)
             status = HTTP_STATUS_SERVER_ERROR
-            response = status
+            response = status.encode('utf-8')
             headers = [('Content-Type', 'text/plain; charset=utf-8')]
 
         session_data = getattr(context, 'session_data', None)
@@ -489,7 +489,8 @@ def marshal(self, result, error, _id=None,
             version=unicode(VERSION),
         )
         response = json_encode_binary(response, version)
-        return json.dumps(response, sort_keys=True, indent=4)
+        dump = json.dumps(response, sort_keys=True, indent=4)
+        return dump.encode('utf-8')
 
     def unmarshal(self, data):
         try:
@@ -672,7 +673,7 @@ def __call__(self, environ, start_response):
                     'xmlserver', user_ccache, environ, start_response, headers)
         except PublicError as e:
             status = HTTP_STATUS_SUCCESS
-            response = status
+            response = status.encode('utf-8')
             start_response(status, headers)
             return self.marshal(None, e)
         finally:
@@ -758,7 +759,8 @@ def marshal(self, result, error, _id=None,
             if isinstance(result, dict):
                 self.debug('response: entries returned %d', result.get('count', 1))
             response = (result,)
-        return xml_dumps(response, version, methodresponse=True)
+        dump = xml_dumps(response, version, methodresponse=True)
+        return dump.encode('utf-8')
 
 
 class jsonserver_session(jsonserver, KerberosSession):
@@ -782,7 +784,7 @@ def _on_finalize(self):
     def need_login(self, start_response):
         status = '401 Unauthorized'
         headers = []
-        response = ''
+        response = b''
 
         self.debug('jsonserver_session: %s need login', status)
 
@@ -1252,7 +1254,7 @@ def _on_finalize(self):
     def need_login(self, start_response):
         status = '401 Unauthorized'
         headers = []
-        response = ''
+        response = b''
 
         self.debug('xmlserver_session: %s need login', status)
 

From d19f16d6bbd05360920806d9a82c35dd4639fa83 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Fri, 13 Jan 2017 12:11:19 +0100
Subject: [PATCH 06/15] py3: rpcserver fix undefined variable

variable 'e' is valid only in except block in py3, so it must be
assigned to different variable for further usage

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/rpcserver.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py
index 8a18f94..45550fb 100644
--- a/ipaserver/rpcserver.py
+++ b/ipaserver/rpcserver.py
@@ -389,8 +389,9 @@ def wsgi_execute(self, environ):
                 )
                 # get at least some context of what is going on
                 params = options
+                error = e
             if error:
-                result_string = type(e).__name__
+                result_string = type(error).__name__
             else:
                 result_string = 'SUCCESS'
             self.info('[%s] %s: %s(%s): %s',

From bd05cfd4855fd24476c7b826fbd114fe03d72980 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Fri, 13 Jan 2017 12:16:28 +0100
Subject: [PATCH 07/15] py3: ipaldap: update encode/decode methods

Update encoding/decoding accordingly to work under Py3

Removing functions that were used only once in code and give no real
improvements

https://fedorahosted.org/freeipa/ticket/4985
---
 ipapython/ipaldap.py | 41 +++++++----------------------------------
 1 file changed, 7 insertions(+), 34 deletions(-)

diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
index 81d8c8d..bb14b45 100644
--- a/ipapython/ipaldap.py
+++ b/ipapython/ipaldap.py
@@ -69,36 +69,6 @@
 DIRMAN_DN = DN(('cn', 'directory manager'))
 
 
-def unicode_from_utf8(val):
-    '''
-    val is a UTF-8 encoded string, return a unicode object.
-    '''
-    return val.decode('utf-8')
-
-
-def value_to_utf8(val):
-    '''
-    Coerce the val parameter to a UTF-8 encoded string representation
-    of the val.
-    '''
-
-    # If val is not a string we need to convert it to a string
-    # (specifically a unicode string). Naively we might think we need to
-    # call str(val) to convert to a string. This is incorrect because if
-    # val is already a unicode object then str() will call
-    # encode(default_encoding) returning a str object encoded with
-    # default_encoding. But we don't want to apply the default_encoding!
-    # Rather we want to guarantee the val object has been converted to a
-    # unicode string because from a unicode string we want to explicitly
-    # encode to a str using our desired encoding (utf-8 in this case).
-    #
-    # Note: calling unicode on a unicode object simply returns the exact
-    # same object (with it's ref count incremented). This means calling
-    # unicode on a unicode object is effectively a no-op, thus it's not
-    # inefficient.
-
-    return unicode(val).encode('utf-8')
-
 class _ServerSchema(object):
     '''
     Properties of a schema retrieved from an LDAP server.
@@ -877,7 +847,7 @@ def encode(self, val):
                 return 'FALSE'
         elif isinstance(val, (unicode, six.integer_types, Decimal, DN,
                               Principal)):
-            return value_to_utf8(val)
+            return six.text_type(val).encode('utf-8')
         elif isinstance(val, DNSName):
             return val.to_text()
         elif isinstance(val, bytes):
@@ -909,9 +879,12 @@ def decode(self, val, attr):
                 elif target_type is unicode:
                     return val.decode('utf-8')
                 elif target_type is datetime.datetime:
-                    return datetime.datetime.strptime(val, LDAP_GENERALIZED_TIME_FORMAT)
+                    return datetime.datetime.strptime(
+                        val.decode('utf-8'), LDAP_GENERALIZED_TIME_FORMAT)
                 elif target_type is DNSName:
-                    return DNSName.from_text(val)
+                    return DNSName.from_text(val.decode('utf-8'))
+                elif target_type in (DN, Principal):
+                    return target_type(val.decode('utf-8'))
                 else:
                     return target_type(val)
             except Exception:
@@ -923,7 +896,7 @@ def decode(self, val, attr):
         elif isinstance(val, tuple):
             return tuple(self.decode(m, attr) for m in val)
         elif isinstance(val, dict):
-            dct = dict((unicode_from_utf8(k), self.decode(v, k)) for k, v in val.items())
+            dct = dict((k.decode('utf-8'), self.decode(v, k)) for k, v in val.items())
             return dct
         elif val is None:
             return None

From c53d4c0bea967242b5bd4f9128dd2d65d13e1738 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Fri, 13 Jan 2017 12:37:47 +0100
Subject: [PATCH 08/15] py3: get_effective_rights: values passed to ldap must
 be bytes

Values passed to LDAP must be bytes

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/plugins/ldap2.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index 25fbfb8..c4b7580 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -289,7 +289,10 @@ def get_effective_rights(self, dn, attrs_list):
         principal = getattr(context, 'principal')
         entry = self.find_entry_by_attr("krbprincipalname", principal,
             "krbPrincipalAux", base_dn=self.api.env.basedn)
-        sctrl = [GetEffectiveRightsControl(True, "dn: " + str(entry.dn))]
+        sctrl = [
+            GetEffectiveRightsControl(
+                True, "dn: {0}".format(entry.dn).encode('utf-8'))
+        ]
         self.conn.set_option(_ldap.OPT_SERVER_CONTROLS, sctrl)
         try:
             entry = self.get_entry(dn, attrs_list)

From 339af52060f9aeefd52184167478fe952d7f7171 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Fri, 13 Jan 2017 12:40:20 +0100
Subject: [PATCH 09/15] py3: can_read: attributelevelrights is already string

Remove decode() as it causes error in py3 because the attribute is
already string not bytes

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/plugins/ldap2.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index c4b7580..71c095d 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -310,7 +310,7 @@ def can_write(self, dn, attr):
 
         attrs = self.get_effective_rights(dn, [attr])
         if 'attributelevelrights' in attrs:
-            attr_rights = attrs.get('attributelevelrights')[0].decode('UTF-8')
+            attr_rights = attrs.get('attributelevelrights')[0]
             (attr, rights) = attr_rights.split(':')
             if 'w' in rights:
                 return True

From a89cd037e5b2338151b61d0be2a083e0dd17592b Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Fri, 13 Jan 2017 13:04:07 +0100
Subject: [PATCH 10/15] Use dict comprehension

---
 ipapython/ipaldap.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
index bb14b45..497b947 100644
--- a/ipapython/ipaldap.py
+++ b/ipapython/ipaldap.py
@@ -896,7 +896,9 @@ def decode(self, val, attr):
         elif isinstance(val, tuple):
             return tuple(self.decode(m, attr) for m in val)
         elif isinstance(val, dict):
-            dct = dict((k.decode('utf-8'), self.decode(v, k)) for k, v in val.items())
+            dct = {
+                k.decode('utf-8'): self.decode(v, k) for k, v in val.items()
+            }
             return dct
         elif val is None:
             return None

From fc63cb684ecb3700640cfb2064d5e9768f183fd1 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Fri, 13 Jan 2017 14:50:11 +0100
Subject: [PATCH 11/15] Principal: validate type of input parameter

Bytes are unsupported and we should raise a TypeError from Principal
__init__ method otherwise we get hard to debug result
---
 ipapython/kerberos.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/ipapython/kerberos.py b/ipapython/kerberos.py
index 3d3530c..9b02790 100644
--- a/ipapython/kerberos.py
+++ b/ipapython/kerberos.py
@@ -66,7 +66,12 @@ class Principal(object):
     Container for the principal name and realm according to RFC 1510
     """
     def __init__(self, components, realm=None):
-        if isinstance(components, six.string_types):
+        if isinstance(components, six.binary_type):
+            raise TypeError(
+                "Cannot create a principal object from bytes: {!r}".format(
+                    components)
+            )
+        elif isinstance(components, six.string_types):
             # parse principal components from realm
             self.components, self.realm = self._parse_from_text(
                 components, realm)

From 86e5442030070b20df50310792f946eab02dd649 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Fri, 13 Jan 2017 18:54:34 +0100
Subject: [PATCH 12/15] py3: fix CSR encoding inside framework

csr must be in string because framework excpects only strings, so we
have to decode it back

https://fedorahosted.org/freeipa/ticket/4985
---
 ipaserver/plugins/cert.py   | 4 +++-
 ipaserver/plugins/dogtag.py | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
index d8bfc1c..4d3f1cf 100644
--- a/ipaserver/plugins/cert.py
+++ b/ipaserver/plugins/cert.py
@@ -804,7 +804,9 @@ def execute(self, csr, all=False, raw=False, **kw):
         try:
             # re-serialise to PEM, in case the user-supplied data has
             # extraneous material that will cause Dogtag to freak out
-            csr_pem = csr_obj.public_bytes(serialization.Encoding.PEM)
+            # keep it as string not bytes, it is required later
+            csr_pem = csr_obj.public_bytes(
+                serialization.Encoding.PEM).decode('utf-8')
             result = self.Backend.ra.request_certificate(
                 csr_pem, profile_id, ca_id, request_type=request_type)
         except errors.HTTPRequestError as e:
diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py
index fbfe608..7ea1b56 100644
--- a/ipaserver/plugins/dogtag.py
+++ b/ipaserver/plugins/dogtag.py
@@ -1634,7 +1634,7 @@ def request_certificate(
         self.debug('%s.request_certificate()', type(self).__name__)
 
         # Call CMS
-        template = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+        template = u'''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
             <CertEnrollmentRequest>
                 <ProfileID>{profile}</ProfileID>
                 <Input id="i1">

From 4ea0339b93f0e2f08a3abcd8ecefe08024b9b9c4 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Thu, 19 Jan 2017 14:30:23 +0100
Subject: [PATCH 13/15] py3: fingerprint_hex_sha256: fix encoding/decoding

https://fedorahosted.org/freeipa/ticket/4985
---
 ipapython/ssh.py | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/ipapython/ssh.py b/ipapython/ssh.py
index 57752ae..2edfa8a 100644
--- a/ipapython/ssh.py
+++ b/ipapython/ssh.py
@@ -192,9 +192,8 @@ def openssh(self):
 
     def fingerprint_hex_sha256(self):
         # OpenSSH trims the trailing '=' of base64 sha256 FP representation
-        # Using unicode argument converts the result to unicode object
-        fp = base64.b64encode(sha256(self._key).digest()).rstrip(u'=')
-        return 'SHA256:{fp}'.format(fp=fp)
+        fp = base64.b64encode(sha256(self._key).digest()).rstrip(b'=')
+        return u'SHA256:{fp}'.format(fp=fp.decode('utf-8'))
 
     def _fingerprint_dns(self, fpfunc, fptype):
         if self._keytype == 'ssh-rsa':

From c00a509ad803fb694de3bcbf71b840c75d81a53d Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Thu, 19 Jan 2017 15:28:15 +0100
Subject: [PATCH 14/15] py3: strip_header: support both bytes and unicode

Various method passed various bytes or unicode as parameter

https://fedorahosted.org/freeipa/ticket/4985
---
 ipalib/x509.py | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/ipalib/x509.py b/ipalib/x509.py
index 13327c1..bc25390 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -85,9 +85,16 @@ def strip_header(pem):
     """
     Remove the header and footer from a certificate.
     """
-    s = pem.find("-----BEGIN CERTIFICATE-----")
+    if isinstance(pem, bytes):
+        re_begin = b"-----BEGIN CERTIFICATE-----"
+        re_end = b"-----END CERTIFICATE-----"
+    else:
+        re_begin = u"-----BEGIN CERTIFICATE-----"
+        re_end = u"-----END CERTIFICATE-----"
+
+    s = pem.find(re_begin)
     if s >= 0:
-        e = pem.find("-----END CERTIFICATE-----")
+        e = pem.find(re_end)
         pem = pem[s+27:e]
 
     return pem

From 8e8ee0952651a58c7e9cd5aef4b4bc0c7120007e Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Thu, 19 Jan 2017 16:11:08 +0100
Subject: [PATCH 15/15] py3: normalize_certificate: support both bytes and
 unicode

https://fedorahosted.org/freeipa/ticket/4985
---
 ipalib/x509.py | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/ipalib/x509.py b/ipalib/x509.py
index bc25390..83b9330 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -254,13 +254,22 @@ def normalize_certificate(rawcert):
 
     rawcert = strip_header(rawcert)
 
-    if util.isvalid_base64(rawcert):
-        try:
-            dercert = base64.b64decode(rawcert)
-        except Exception as e:
-            raise errors.Base64DecodeError(reason=str(e))
-    else:
+    try:
+        if isinstance(rawcert, bytes):
+            # base64 must work with utf-8, otherwise it is raw bin certificate
+            decoded_cert = rawcert.decode('utf-8')
+        else:
+            decoded_cert = rawcert
+    except UnicodeDecodeError:
         dercert = rawcert
+    else:
+        if util.isvalid_base64(decoded_cert):
+            try:
+                dercert = base64.b64decode(decoded_cert)
+            except Exception as e:
+                raise errors.Base64DecodeError(reason=str(e))
+        else:
+            dercert = rawcert
 
     # At this point we should have a DER certificate.
     # Attempt to decode it.
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to