Kallithea issues archive

Issue #325: Upgrade to SHA hashing

Reported by: James Shewey
State: new
Created on: 2018-06-27 05:29
Updated on: 2018-06-30 20:31

Description

The FIPS 140-2 standard, published by NIST disables support in the kernel and in OpenSSL. Basically, this breaks md5 hashing support through OpenSSL libraries. Thus, if a system sets the kernel flag fips=1, it breaks Kallithea. The service will start, but upon accessing the page, the stack trace below is recieved:

2018-06-26 18:47:59.806 ERROR [waitress] Exception when serving /favicon.ico

Traceback (most recent call last):

  File "/usr/lib/python2.7/site-packages/waitress-0.8.8-py2.7.egg/waitress/channel.py", line 337, in service

    task.service()

  File "/usr/lib/python2.7/site-packages/waitress-0.8.8-py2.7.egg/waitress/task.py", line 173, in service

    self.execute()

  File "/usr/lib/python2.7/site-packages/waitress-0.8.8-py2.7.egg/waitress/task.py", line 392, in execute

    app_iter = self.channel.server.application(env, start_response)

  File "/usr/lib/python2.7/site-packages/paste/gzipper.py", line 38, in __call__

    response.gzip_start_response)

  File "/usr/lib/python2.7/site-packages/paste/cascade.py", line 130, in __call__

    return self.apps[-1](environ, start_response)

  File "/usr/lib/python2.7/site-packages/paste/registry.py", line 379, in __call__

    app_iter = self.application(environ, start_response)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/middleware/wrapper.py", line 43, in __call__

    return self.application(environ, start_response)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/base.py", line 312, in __call__

    return self._handle_request(environ, start_response)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/middleware/simplegit.py", line 68, in _handle_request

    return self.application(environ, start_response)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/base.py", line 312, in __call__

    return self._handle_request(environ, start_response)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/middleware/simplehg.py", line 73, in _handle_request

    return self.application(environ, start_response)

  File "/usr/lib/python2.7/site-packages/pylons/middleware.py", line 177, in __call__

    self.app, new_environ, catch_exc_info=True)

  File "/usr/lib/python2.7/site-packages/pylons/util.py", line 50, in call_wsgi_application

    app_iter = application(environ, start_response)

  File "/usr/lib/python2.7/site-packages/weberror/errormiddleware.py", line 156, in __call__

    return self.application(environ, start_response)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/middleware/sessionmiddleware.py", line 62, in __call__

    return self.wrap_app(environ, session_start_response)

  File "/usr/lib/python2.7/site-packages/routes/middleware.py", line 131, in __call__

    response = self.app(environ, start_response)

  File "/usr/lib/python2.7/site-packages/pylons/wsgiapp.py", line 103, in __call__

   response = self.dispatch(controller, environ, start_response)

  File "/usr/lib/python2.7/site-packages/pylons/wsgiapp.py", line 313, in dispatch

    return controller(environ, start_response)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/base.py", line 439, in __call__

    session.get('authuser'),

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/base.py", line 424, in _determine_auth_user

    return AuthUser()

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/lib/auth.py", line 488, in __init__

    self.anonymous_user = User.get_default_user(cache=True)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/model/db.py", line 649, in get_default_user

    user = User.get_by_username(User.DEFAULT_USER, cache=cache)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/model/db.py", line 559, in get_by_username

    "get_user_%s" % _hash_key(username)

  File "/usr/lib/python2.7/site-packages/Kallithea-0.3.5-py2.7.egg/kallithea/model/db.py", line 68, in <lambda>

    _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

ValueError: error:060800A3:digital envelope routines:EVP_DigestInit_ex:disabled for fips

The basic fix here is to switch to using a sha1 or better hash instead of an MD5 hash. A cursory grep of the source code results in the following files that would need to be swapped to a stronger hash:

./kallithea/lib/celerylib/__init__.py:from hashlib import md5

./kallithea/lib/celerylib/__init__.py:        md5(func_name + '-' + '-'.join(map(safe_str, params))).hexdigest()

./kallithea/tests/other/test_libs.py:        _md5 = lambda s: hashlib.md5(s).hexdigest()

./kallithea/lib/dbmigrate/schema/db_2_0_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_2_0_1.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_1_5_2.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_2_2_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_1_6_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_1_7_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_2_0_2.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_1_8_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_1_4_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_2_2_3.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_1_3_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_2_1_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/lib/dbmigrate/schema/db_1_5_0.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/model/db.py:_hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()

./kallithea/model/db.py:    DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'

./kallithea/lib/helpers.py:    return 'C-%s-%s' % (short_id(raw_id), hashlib.md5(safe_str(path)).hexdigest()[:12])

./kallithea/lib/helpers.py:        _md5 = lambda s: hashlib.md5(s).hexdigest()

./kallithea/lib/helpers.py:                   .replace('{md5email}', _md5(safe_str(email_address).lower())) \

./kallithea/lib/markup_renderer.py:        from hashlib import md5

./kallithea/lib/markup_renderer.py:            digest = md5(matchobj.group(0)).hexdigest()

Upgrading this hashing will allow companies who undergo NIST auditing and require NIST compliance to use Kallithea, however I could see that this might cause an issue for an upgrade to newer versions and hashes might need to be converted or regenerated somehow.

Attachments

Comments

Comment by Thomas De Schampheleire, on 2018-06-30 20:31

Hello, welcome to Kallithea and thanks for reporting this.

First of all, new development is happening on the default branch, in which many changes have already been done. For example, dbmigrate is no longer used, so these no longer need changes.

While I guess that some of the internal hashes could equally be some other hash algorithm, the gravatar one is an example that could not change. The Gravatar service (which is of course optional and could be skipped for FIPS compliance, requires emails to be hashed using MD5.

Change in hash algorithm for cache-related hashes would cause cache misses, but otherwise I would assume it's only a transitional problem at the time of the upgrade.

If you have an interest in this and have some programming skills, you are very welcome to propose patches. I think that would definitely be the fastest way forward.