#1081 Add the initial gpg signature check code
Merged 7 years ago by pingou. Opened 7 years ago by puiterwijk.
puiterwijk/pagure signaturecheck  into  gpg_check

@@ -206,6 +206,10 @@ 

  # List of blacklisted group names

  BLACKLISTED_GROUPS = ['forks']

  

+ # GnuPG configuration

+ GPG_BINARY = 'gpg2'

+ GPG_HOMEDIR = 'gpghome'

+ 

  

  ACLS = {

      'create_project': 'Create a new project',

file modified
+53
@@ -11,6 +11,7 @@ 

  

  import datetime

  import hashlib

+ import gnupg

  import json

  import os

  import shutil
@@ -1243,6 +1244,56 @@ 

      return tags

  

  

+ def _check_signature(message, signature):

+     """ This function performs the actual signature checking. """

+     gpg = gnupg.GPG(gnupghome=pagure.APP.config['GPG_HOMEDIR'],

+                     gpgbinary=pagure.APP.config['GPG_BINARY'])

+     with tempfile.NamedTemporaryFile() as sigfile:

+         sigfile.write(signature)

+         sigfile.flush()

+         verified = gpg.verify_data(sigfile.name, message)

+         return {'valid': verified.valid,

+                 'signer': verified.username,

+                 'keyid': verified.key_id}

+     return None

+ 

+ 

+ def check_signature(raw, is_simple):

+     """ Returns signature state.

+ 

+     is_simple is a flag whether this is a simple signature (case with tags)

+     where the signature is just at the end of the raw string, or if it's a

+     complicated (case with commit) format where we need to parse it."""

+     if not 'BEGIN PGP SIGNATURE' in raw:

+         return None

+ 

+     if is_simple:

+         message, line, sig = raw.partition('-----BEGIN PGP SIGNATURE-----')

+         sig = line + sig

+     else:

+         message = ''

+         sig = ''

+         in_sig = False

+         for line in raw.split('\n'):

+             if line.startswith('gpgsig -----BEGIN PGP SIGNATURE-----'):

+                 in_sig = True

+             if in_sig:

+                 # The lines are all indented with a single space, remove those

+                 # We also remove the remaining part of the "gpgsig" indicator

+                 sig += line[1:].replace('pgsig ', '')

+                 sig += '\n'

+             else:

+                 message += line

+                 message += '\n'

+ 

+             if in_sig and line.startswith(' -----END PGP SIGNATURE-----'):

+                 in_sig = False

+         # Remove the final newline, which is duplicate and breaks signature

+         message = message[:-1]

+ 

+     return _check_signature(message, sig)

+ 

+ 

  def get_git_tags_objects(project):

      """ Returns the list of references of the tags created in the git

      repositorie the specified project.
@@ -1278,6 +1329,8 @@ 

                          '-----BEGIN PGP SIGNATURE-----', 1)[0].strip()

                  tags[commit_time]["head_msg"] = head_msg

                  tags[commit_time]["body_msg"] = body_msg

+                 tags[commit_time]["signed"] = check_signature(

+                     tags[commit_time]["object"].read_raw(), True)

      sorted_tags = []

  

      for tag in sorted(tags, reverse=True):

file modified
+4
@@ -723,6 +723,9 @@ 

          # First commit in the repo

          diff = commit.tree.diff_to_tree(swap=True)

  

+     # Get signature info

+     signature = pagure.lib.git.check_signature(commit.read_raw(), False)

+ 

      return flask.render_template(

          'commit.html',

          select='commits',
@@ -734,6 +737,7 @@ 

          commit=commit,

          diff=diff,

          form=pagure.forms.ConfirmationForm(),

+         signature=signature,

      )

  

  

file modified
+1
@@ -11,6 +11,7 @@ 

  flask

  flask-wtf

  flask-multistatic

+ python-gnupg

  kitchen

  markdown

  munch

This does implement verification of signatures on commits and tags.
It does not implement getting the keys from a keyserver, verifying
the key is owned by the user, or any UI to indicate signature state.

Signed-off-by: Patrick Uiterwijk puiterwijk@redhat.com

rebased

7 years ago

There are quite a few 'print' remaining :)

rebased

7 years ago

Removed, sorry for that.

Why the delete=False?

Because I had left that over from debugging :)

rebased

7 years ago

rebased

7 years ago

rebased

7 years ago

This looks fine to me with two small remarks:

  • unit-tests?
  • it's incomplete to be fully functional (while it won't break anything it will also not provide any info)

As such, I am leaning on either leaving it as a PR or merging it to a dedicated branch that we'll merge into master when things are fully working

rebased

7 years ago

I think we should remove this one and let bleach pull the version it needs.

IIRC fedora-hubs had some problem with this one :(

rebased

7 years ago

rebased

7 years ago

Merging this to its own dedicated branch until we can finish the code :)

Pull-Request has been merged by pingou

7 years ago