Logo Search packages:      
Sourcecode: qa-assistant version File versions  Download package

gpg.py

# File: gpg.py
# Author: Toshio Kuratomi <toshio@tiki-lounge.com>
# Date: 27 Nov 2004
# Copyright: Toshio Kuratomi
# License: GPL
# Id: $Id: gpg.py 188 2005-06-14 00:55:59Z badger $
'''Invoke gpg from here.

Eventually we may want all of these to be superceded by gpgme calls.  OTOH
gpgme enables C code to use gpg the way a scripting language would.  Since
python is a glue language anyhow....
'''
__revision__ = '$Rev: 188 $'

import os

import error

# With gpgme, this function remains as the get passphrase callback.
# Use gpgme_set_passphrase_cb to set it.
import gtk

def get_passphrase(gpgId, badPass):
    '''Retrieve a passphrase from the user.

    Arguments:
    :gpgId: Id to send to gpg as the user requesting the signature
    :badPass: True if this is a repeat request for the password

    Return: The passphrase entered by the user.
    '''
    passDialog = gtk.Dialog('Enter Passphrase', None,
            gtk.DIALOG_DESTROY_WITH_PARENT,
            (gtk.STOCK_OK, gtk.RESPONSE_OK,
                gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
    passDialog.set_default_response(gtk.RESPONSE_OK)
    vbox = passDialog.vbox
    # Let the user know if the previous password didn't work.
    if badPass:
        reprompt = gtk.Label('The password you entered did not work.  Please'
        ' try reentering it.')
        reprompt.set_line_wrap(True)
        vbox.add(reprompt)
       
    prompt = gtk.Label('Please enter the passphrase for ' + gpgId)
    prompt.set_line_wrap(True)
    vbox.add(prompt)
    
    passphraseEntry = gtk.Entry()
    passphraseEntry.set_visibility(False)
    vbox.add(passphraseEntry)
    vbox.show_all()

    response = passDialog.run()
    if response == gtk.RESPONSE_OK:
        passphrase = passphraseEntry.get_text()
    else:
        passphrase = None
    
    passDialog.destroy()
    return passphrase

def list_secret_keys(pathToGpg):
    ''' List the secret key identities available for the user.

    Arguments
    :pathToGpg: Path to the gpg program binary.

    Returns: A list of the secret keys suitable for signing with.
    '''
    if not (os.path.isfile(pathToGpg) and os.access(pathToGpg, os.X_OK)):
        raise error.NotGPGCompatible, 'The specified program does not exist.'
    secretKeyList = []
    cmd = pathToGpg + ' --list-secret-keys --with-colons'
    gpgCmd = os.popen(cmd)
    for record in gpgCmd.readlines():
        recordArray = record.split(':')
        if recordArray[0] == 'sec':
            secretKeyList.append(recordArray[9])
    if gpgCmd.close():
        raise error.NotGPGCompatible, ('The signing program selected in the'
            ' Preferences is not command line compatible with gpg.')
    return secretKeyList

def sign_buffer(buf, gpgID, pathToGpg, passphrase):
    '''Sign an in-memory buffer.

    Arguments:
    :buf: Buffer to sign.
    :gpgID: Person whose key we are going to sign with.
    :pathToGpg: Path to the gpg program.
    :passphrase: The passphrase to unlock the gpg key.

    Returns: The signed buffer.
    '''
    if not (os.path.isfile(pathToGpg) and os.access(pathToGpg, os.X_OK)):
        raise error.NotGPGCompatible, 'The specified program does not exist.'
    cmd = (pathToGpg + " --local-user '" + gpgID +
            "' --clearsign --armor --status-fd 2 --command-fd 0")
    (gpgIn, gpgOut, gpgStatus) = os.popen3(cmd)
    gpgString = gpgStatus.readline().split(None, 2)
    if (gpgString[0] != 'gpg:') and (gpgString[0] != '[GNUPG:]'):
        raise error.NotGPGCompatible, ('The signing program selected in the'
            ' Preferences is not gpg compatible.')
    while True:
        if gpgString[1] == 'GET_HIDDEN':
            gpgIn.writelines((passphrase, '\n'))
            gpgIn.flush()
        elif gpgString[1] == 'GOOD_PASSPHRASE':
            gpgIn.write(buf)
            gpgIn.close()
        elif gpgString[1] == 'SIG_CREATED':
            outBuf = gpgOut.read()
            break
        elif gpgString[1] == 'BAD_PASSPHRASE':
            gpgIn.close()
            gpgOut.close()
            gpgStatus.close()
            raise error.BadPassphrase, ('The entered passphrase was not valid.')
        elif gpgString[1] == 'NO_SECKEY' or (gpgString[1] == 'skipped'
            and
                gpgString[2] == "`" + gpgID + "': secret key not available\n"):
            gpgIn.close()
            gpgOut.close()
            gpgStatus.close()
            raise error.NoSecretKey, ('No secret key for %s' % gpgID)

        gpgString = gpgStatus.readline().split(None, 2)
        
    gpgIn.close()
    gpgOut.close()
    gpgStatus.close()
    if not outBuf:
        raise error.NoOut, ('No output generated by GPG signing!')
    return outBuf

Generated by  Doxygen 1.6.0   Back to index