system: Linux mars.sprixweb.com 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
# pygpgme - a Python wrapper for the gpgme library
# Copyright (C) 2006 James Henstridge
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""Utilities related to editing keys.
Currently only contains a utility function for editing the owner trust
value of a key in a keyring.
"""
__metaclass__ = type
__all__ = ['edit_sign', 'edit_trust']
import functools
import os
try:
from io import BytesIO
except ImportError:
from StringIO import StringIO as BytesIO
import gpgme
def key_editor(function):
"""A decorator that lets key editor callbacks be written as generators."""
@functools.wraps(function)
def wrapper(ctx, key, *args, **kwargs):
# Start the generator and run it once.
gen = function(ctx, key, *args, **kwargs)
try:
# XXX: this is for Python 2.x compatibility.
try:
gen.__next__()
except AttributeError:
gen.next()
except StopIteration:
return
def edit_callback(status, args, fd):
if status in (gpgme.STATUS_EOF,
gpgme.STATUS_GOT_IT,
gpgme.STATUS_NEED_PASSPHRASE,
gpgme.STATUS_GOOD_PASSPHRASE,
gpgme.STATUS_BAD_PASSPHRASE,
gpgme.STATUS_USERID_HINT,
gpgme.STATUS_SIGEXPIRED,
gpgme.STATUS_KEYEXPIRED,
gpgme.STATUS_PROGRESS,
gpgme.STATUS_KEY_CREATED,
gpgme.STATUS_ALREADY_SIGNED):
return
try:
data = gen.send((status, args))
except StopIteration:
raise gpgme.error(gpgme.ERR_SOURCE_UNKNOWN, gpgme.ERR_GENERAL)
if data is not None:
os.write(fd, data.encode('ASCII'))
output = BytesIO()
try:
ctx.edit(key, edit_callback, output)
finally:
gen.close()
return wrapper
@key_editor
def edit_trust(ctx, key, trust):
"""Edit the trust level of the given key."""
if trust not in (gpgme.VALIDITY_UNDEFINED,
gpgme.VALIDITY_NEVER,
gpgme.VALIDITY_MARGINAL,
gpgme.VALIDITY_FULL,
gpgme.VALIDITY_ULTIMATE):
raise ValueError('Bad trust value %d' % trust)
status, args = yield None
assert args == 'keyedit.prompt'
status, args = yield 'trust\n'
assert args == 'edit_ownertrust.value'
status, args = yield '%d\n' % trust
if args == 'edit_ownertrust.set_ultimate.okay':
status, args = yield 'Y\n'
assert args == 'keyedit.prompt'
status, args = yield 'quit\n'
assert args == 'keyedit.save.okay'
status, args = yield 'Y\n'
@key_editor
def edit_sign(ctx, key, index=0, local=False, norevoke=False,
expire=True, check=0):
"""Sign the given key.
index: the index of the user ID to sign, starting at 1. Sign all
user IDs if set to 0.
local: make a local signature
norevoke: make a non-revokable signature
command: the type of signature. One of sign, lsign, tsign or nrsign.
expire: whether the signature should expire with the key.
check: Amount of checking performed. One of:
0 - no answer
1 - no checking
2 - casual checking
3 - careful checking
"""
if index < 0 or index > len(key.uids):
raise ValueError('user ID index out of range')
command = 'sign'
if local:
command = 'l%s' % command
if norevoke:
command = 'nr%s' % command
if check not in [0, 1, 2, 3]:
raise ValueError('check must be one of 0, 1, 2, 3')
status, args = yield None
assert args == 'keyedit.prompt'
status, args = yield 'uid %d\n' % index
assert args == 'keyedit.prompt'
status, args = yield '%s\n' % command
while args != 'keyedit.prompt':
if args == 'keyedit.sign_all.okay':
status, args = yield 'Y\n'
elif args == 'sign_uid.expire':
status, args = yield '%s\n' % ('Y' if expire else 'N')
elif args == 'sign_uid.class':
status, args = yield '%d\n' % check
elif args == 'sign_uid.okay':
status, args = yield 'Y\n'
else:
raise AssertionError("Unexpected state %r" % ((status, args),))
status, args = yield 'quit\n'
assert args == 'keyedit.save.okay'
status, args = yield 'Y\n'