예제 #1
0
    def __init__(self, path):
        "new(path) path - location of the glade file"
        gladefile = os.path.join(path, "PyGtkGpgKeys.glade")
        self.wtree = gtk.glade.XML(gladefile)
        self.wtree.signal_autoconnect(self)

        self.mainwin = self.wtree.get_widget("GPGAdminWindow")
        self.treeview = self.wtree.get_widget("GPGKeysView")

        self.model = gtk.TreeStore(
            *[x.type for x in visible_columns + helper_columns])

        self.context = Context()
        self.context.set_passphrase_cb(self.get_password, "")
        self.progress = None
        self.context.set_progress_cb(self.gen_progress, None)
        # Use mode.SIGS to include signatures in the list.
        self.context.set_keylist_mode(mode.SIGS)
        self.load_keys(True)

        self.treeview.set_model(self.model)
        self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        self.add_columns()

        gtk.main()
예제 #2
0
def load_keys():
    "Download keys from the keyring"
    context = Context()
    sec_keys = {}
    for key in context.op_keylist_all(None, 1):
        sec_keys[key.subkeys[0].fpr] = 1
    # print sec_keys
    context.set_keylist_mode(keylist.mode.SIGS)
    for key in context.op_keylist_all(None, 0):
        secret = sec_keys.has_key(key.subkeys[0].fpr)
        # print key, secret
        if key.can_encrypt: print key
예제 #3
0
    def __init__(self, path):
        "new(path) path - location of the glade file"
        gladefile = os.path.join(path, "PyGtkGpgKeys.glade")
        self.wtree = gtk.glade.XML(gladefile)
        self.wtree.signal_autoconnect(self)

        self.mainwin = self.wtree.get_widget("GPGAdminWindow")
        self.treeview = self.wtree.get_widget("GPGKeysView")

        self.model = gtk.TreeStore(*[x.type for x in visible_columns +
                                     helper_columns])        

        self.context = Context()
        self.context.set_passphrase_cb(self.get_password, "")
        self.progress = None
        self.context.set_progress_cb(self.gen_progress, None)
        # Use mode.SIGS to include signatures in the list.
        self.context.set_keylist_mode(mode.SIGS)
        self.load_keys(True)

        self.treeview.set_model(self.model)
        self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        self.add_columns()

        gtk.main()
예제 #4
0
def aroundKeyPressEvent(self, evt, _old=''):
	if self.state == "showAnswer":
		key = unicode(evt.text())
		if evt.key() == SHOW_PASS_KEY:
			if self.currentCard.fact.model.name == MODEL:
				mf = self.mainWin.mainText.page().mainFrame()

				""" Set up the PyMe stuff """
				c = Context();
				c.set_passphrase_cb(passCallback)
				c.set_armor(1);
				cipher = Data(re.sub("<br[^>]*>","\n",self.currentCard.fact['GPG'].encode('ascii')))
				cipher.seek(0,0)

				""" Try to decrypt the password """
				try:
					plain = Data();
					c.op_decrypt(cipher, plain);
					plain.seek(0,0);
					QMessageBox.information(mw, "Password", "Your password is %s" % unicode(plain.read(), 'utf-8'))
				except GPGMEError, e:
					QMessageBox.information(mw, "Error", "Could not decrypt your password.\nError: " + str(e))
					
				evt.accept()
				return
예제 #5
0
def load_keys():
    "Download keys from the keyring"
    context = Context()
    sec_keys = {}
    for key in context.op_keylist_all(None, 1):
        sec_keys[key.subkeys[0].fpr] = 1
    # print sec_keys
    context.set_keylist_mode(keylist.mode.SIGS)
    for key in context.op_keylist_all(None, 0):
        secret = sec_keys.has_key(key.subkeys[0].fpr)
        # print key, secret
        if key.can_encrypt: print key
예제 #6
0
    def edit_fnc(self, status, args, out):
        print "[-- Response --]"
        out.seek(0,0)
        print out.read(),
        print "[-- Code: %d, %s --]" % (status, args)
    
        if args == "keyedit.prompt":
            result = self.steps[self.step]
            self.step += 1
        elif args == "keyedit.save.okay":
            result = "Y"
        elif args == "keygen.valid":
            result = "0"
        else:
            result = None

        return result

if not os.getenv("GNUPGHOME"):
    print "Please, set GNUPGHOME env.var. pointing to GPGME's tests/gpg dir"
else:
    c = Context()
    c.set_passphrase_cb(lambda x,y,z: "abc")
    out = Data()
    c.op_keylist_start("Alpha", 0)
    key = c.op_keylist_next()
    c.op_edit(key, KeyEditor().edit_fnc, out, out)
    print "[-- Last response --]"
    out.seek(0,0)
    print out.read(),
예제 #7
0
파일: inter-edit.py 프로젝트: gpg/gpgme
    if not name.startswith('__') and name != "util":
        stat2str[getattr(status, name)] = name


# Print the output received since the last prompt before giving the new prompt
def edit_fnc(stat, args, helper):
    global stat_strings
    try:
        while True:
            helper["data"].seek(helper["skip"], 0)
            data = helper["data"].read()
            helper["skip"] += len(data)
            sys.stdout.buffer.write(data)
            return input("(%s) %s > " % (stat2str[stat], args))
    except EOFError:
        pass

# Simple interactive editor to test editor scripts
if len(sys.argv) != 2:
    sys.stderr.write("Usage: %s <Gpg key pattern>\n" % sys.argv[0])
else:
    c = Context()
    out = Data()
    c.op_keylist_start(sys.argv[1], 0)
    key = c.op_keylist_next()
    helper = {"skip": 0, "data": out}
    c.op_edit(key, edit_fnc, helper, out)
    print("[-- Final output --]")
    out.seek(helper["skip"], 0)
    sys.stdout.buffer.write(out.read())
예제 #8
0
파일: encrypt-to-all.py 프로젝트: gpg/gpgme
"""
This program will try to encrypt a simple message to each key on your
keyring.  If your keyring has any invalid keys on it, those keys will
be skipped and it will re-try the encryption."""

import sys
import os
from pyme import core
from pyme.core import Data, Context

core.check_version(None)

plain = Data('This is my message.')

c = Context()
c.set_armor(1)

def sendto(keylist):
    cipher = Data()
    c.op_encrypt(keylist, 1, plain, cipher)
    cipher.seek(0, os.SEEK_SET)
    return cipher.read()

names = []
for key in c.op_keylist_all(None, 0):
    try:
        print(" *** Found key for %s" % key.uids[0].uid)
        valid = 0
        for subkey in key.subkeys:
            keyid = subkey.keyid
예제 #9
0
        stat2str[getattr(status, name)] = name


# Print the output received since the last prompt before giving the new prompt
def edit_fnc(stat, args, helper):
    global stat_strings
    try:
        while True:
            helper["data"].seek(helper["skip"], 0)
            data = helper["data"].read()
            helper["skip"] += len(data)
            print data
            return raw_input("(%s) %s > " % (stat2str[stat], args))
    except EOFError:
        pass


# Simple interactive editor to test editor scripts
if len(sys.argv) != 2:
    sys.stderr.write("Usage: %s <Gpg key patter>\n" % sys.argv[0])
else:
    c = Context()
    out = Data()
    c.op_keylist_start(sys.argv[1], 0)
    key = c.op_keylist_next()
    helper = {"skip": 0, "data": out}
    c.op_edit(key, edit_fnc, helper, out)
    print "[-- Final output --]"
    out.seek(helper["skip"], 0)
    print out.read()
예제 #10
0
class PyGtkGpgKeys:
    "Main class representing PyGtkGpgKeys application"
    def error_message(self, text, parent=None):
        dialog = gtk.MessageDialog(parent or self.mainwin,
                                   gtk.DIALOG_MODAL |
                                   gtk.DIALOG_DESTROY_WITH_PARENT,
                                   gtk.MESSAGE_ERROR,
                                   gtk.BUTTONS_OK,
                                   text)
        dialog.run()
        dialog.destroy()        

    def yesno_message(self, text, parent=None):
        dialog = gtk.MessageDialog(parent or self.mainwin,
                                   gtk.DIALOG_MODAL |
                                   gtk.DIALOG_DESTROY_WITH_PARENT,
                                   gtk.MESSAGE_QUESTION,
                                   gtk.BUTTONS_YES_NO,
                                   text)
        result = dialog.run() == gtk.RESPONSE_YES
        dialog.destroy()
        return result
    
    def load_keys(self, first_time=False):
        if not first_time: self.model.clear()
        secret_keys = {}
        for key in self.context.op_keylist_all(None, 1):
            secret_keys[key.subkeys[0].fpr] = 1
        for key in self.context.op_keylist_all(None, 0):
            self.add_key(key, secret_keys.has_key(key.subkeys[0].fpr))
    
    def add_key(self, key, secret):
        "self.add_key(key) - add key to the TreeStore model"
        iter = self.model.append(None)
        # Can delete only the whole key
        param = (iter,) + pair("Secret", secret)
        # Key information is a combination of the key and first uid and subkey
        for col in key_columns: param += pair(col, key)
        for col in uid_columns: param += pair(col, key.uids[0])
        for col in sub_columns: param += pair(col, key.subkeys[0])
        for col in sub_sign_columns: param += pair(col, key.subkeys[0])
        self.model.set(*param)
        if key.uids:
            self.add_signatures(key.uids[0].signatures, iter)
            self.add_uids(key.uids[1:], iter)
        self.add_subkeys(key.subkeys[1:], iter)

    def add_subkeys(self, subkeys, iter):
        "self.add_subkeys(subkey, iter) - add subkey as child to key's iter"
        if not subkeys:
            return
        key_iter = self.model.append(iter)
        self.model.set(key_iter, columns["Name"].index, "Subkeys", *name_only)
        for subkey in subkeys:
            child_iter = self.model.append(key_iter)
            param = (child_iter,)
            for col in sub_columns: param += pair(col, subkey)
            for col in sub_sign_columns: param += pair(col, subkey)
            self.model.set(*param)

    def add_uids(self, uids, iter):
        "self.add_uids(uid, iter) - add uid as a child to key's iter"
        if not uids:
            return
        uid_iter = self.model.append(iter)
        self.model.set(uid_iter,columns["Name"].index,"Other UIDs",*name_only)
        for uid in uids:
            child_iter = self.model.append(uid_iter)
            param = (child_iter,)
            for col in uid_columns: param += pair(col, uid)
            self.model.set(*param)
            self.add_signatures(uid.signatures, child_iter)

    def add_signatures(self, signs, iter):
        "self.add_signatures(sign, iter) - add signature as a child to iter"
        if not signs:
            return
        sign_iter = self.model.append(iter)
        self.model.set(sign_iter,columns["Name"].index,"Signatures",*name_only)
        for sign in signs:
            child_iter = self.model.append(sign_iter)
            param = (child_iter,)
            for col in uid_columns: param += pair(col, sign)
            for col in sign_columns: param += pair(col, sign)
            for col in sub_sign_columns: param += pair(col, sign)
            self.model.set(*param)

    def add_columns(self):
        "Add viewable columns for the data in TreeStore model"
        view_menu = gtk.Menu()
        for item in visible_columns:
            if item.type == gobject.TYPE_BOOLEAN:
                renderer = gtk.CellRendererToggle()
                item.attrs["active"] = item.index
            else:
                renderer = gtk.CellRendererText()
                item.attrs["text"] = item.index
            column = self.treeview.insert_column_with_attributes(
                item.index, item.name, renderer, **item.attrs)
            column.set_sort_column_id(item.index)
            # Create callback for a View menu item
            if item.view != None:
                check = gtk.CheckMenuItem(item.name)
                check.set_active(item.view)
                check.connect("activate",
                              lambda x, y: y.set_visible(x.get_active()),
                              column)
                view_menu.append(check)
                column.set_visible(check.get_active())
                
        view_menu.show_all()
        self.wtree.get_widget("view_menu").set_submenu(view_menu)

    def on_GPGKeysView_button_press_event(self, obj, event):
        if event.button != 3:
            return False

        menu = gtk.Menu()
        for title, callback in [
            ("Reload", self.on_reload_activate),
            (None, None),
            ("Delete", self.on_delete_activate),
            ("Export (txt)", self.on_export_keys_text_activate),
            ("Export (bin)", self.on_export_keys_activate)
            ]:
            if title:
                item = gtk.MenuItem(title)
                item.connect("activate", callback)
            else:
                item = gtk.SeparatorMenuItem()
            menu.append(item)
        menu.show_all()
        
        menu.popup(None, None, None, event.button, event.time)
        return True

    def editor_func(self, status, args, val_dict):
        state = val_dict["state"]
        prompt = "%s %s" % (state, args)
        if val_dict.has_key(prompt):
            val_dict["state"] = val_dict[prompt][0]
            return val_dict[prompt][1]
        elif args:
            sys.stderr.write("Unexpected prompt in editor_func: %s\n" % prompt)
            raise EOFError()
        return ""

    def change_key_trust(self, key, new_trust):
        val_dict = {
            "state": "start",
            "start keyedit.prompt": ("trust", "trust"),
            "trust edit_ownertrust.value": ("prompt", "%d" % new_trust),
            "prompt edit_ownertrust.set_ultimate.okay": ("prompt", "Y"),
            "prompt keyedit.prompt": ("finish", "quit")
            }
        out = Data()
        self.context.op_edit(key, self.editor_func, val_dict, out)

    def on_change_trust(self, new_trust):
        selection = self.treeview.get_selection()
        if selection.count_selected_rows() <= 0:
            return
        
        key_list = []
        selection.selected_foreach(self.collect_keys, key_list)

        message = "Change trust to %s on the following keys?\n" % \
                  trusts[new_trust]
        for key, row in key_list:
            message += "\n%s\t" % key.subkeys[0].keyid
            if key.uids: message += key.uids[0].uid
            else:        message += "<undefined>"                
        if self.yesno_message(message):
            for key, row in key_list:
                if key.owner_trust != new_trust:
                    self.change_key_trust(key, new_trust)
                    row[columns["Owner Trust"].index] = trusts[new_trust]

    def on_undefined_trust_activate(self, obj):
        self.on_change_trust(1)

    def on_never_trust_activate(self, obj):
        self.on_change_trust(2)

    def on_marginal_trust_activate(self, obj):
        self.on_change_trust(3)

    def on_full_trust_activate(self, obj):
        self.on_change_trust(4)

    def on_ultimate_trust_activate(self, obj):
        self.on_change_trust(5)

    def collect_keys(self, model, path, iter, key_list):
        row = model[path[:1]]
        keyid = row[columns["FPR"].index]
        key = self.context.get_key(keyid, 0)
        key_list.append((key, row))

    def export_keys(self):
        selection = self.treeview.get_selection()
        if selection.count_selected_rows() <= 0:
            return
        
        export_file = None
        dialog = gtk.FileChooserDialog("Export Keys (Public only) into a File",
                                       self.mainwin,
                                       gtk.FILE_CHOOSER_ACTION_SAVE,
                                       (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        gtk.STOCK_OK, gtk.RESPONSE_OK))
        while dialog.run() == gtk.RESPONSE_OK:
            filename = dialog.get_filename()
            if os.path.exists(filename):
                if os.path.isdir(filename):
                    self.error_message("%s is a directory!" % filename,
                                       dialog)
                    continue
                elif not self.yesno_message("%s exists. Override?" % filename,
                                            dialog):
                    continue

            # FIXME. Verify that file can be written to
            export_file = file(filename, "wb")
            break
        dialog.destroy()
        if export_file == None:
            return

        key_list = []
        selection.selected_foreach(self.collect_keys, key_list)
        expkeys = Data()
        for key, row in key_list:
            self.context.op_export(key.subkeys[0].fpr, 0, expkeys)
        expkeys.seek(0,0)
        export_file.write(expkeys.read())
        export_file.close()
            
    def on_export_keys_activate(self, obj):
        self.context.set_armor(0)
        self.export_keys()

    def on_export_keys_text_activate(self, obj):
        self.context.set_armor(1)
        self.export_keys()

    def on_import_keys_activate(self, obj):
        import_file = None
        dialog = gtk.FileChooserDialog("Import Keys from a File",
                                       self.mainwin,
                                       gtk.FILE_CHOOSER_ACTION_OPEN,
                                       (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        gtk.STOCK_OK, gtk.RESPONSE_OK))
        while dialog.run() == gtk.RESPONSE_OK:
            filename = dialog.get_filename()
            if os.path.exists(filename):
                if os.path.isdir(filename):
                    self.error_message("%s is a directory!" % filename,
                                       dialog)
                else:
                    # FIXME. Verify that file can be open.
                    import_file = filename
                    break
            else:
                self.error_message("%s does not exist." % filename,
                                   dialog)
        dialog.destroy()
        if import_file == None:
            return

        impkeys = Data(file=import_file)
        status = self.context.op_import(impkeys)
        if status:
            self.error_message("Import return an error message %d" % status)
        result = self.context.op_import_result()
        if result.considered == 0:
            self.error_message("There's no keys in the file.")
        # FIXME. Instead of rereading everything we could find out what's new
        # from the result based on the ORed value of impkey:
        # constants.import.NEW    - The key was new.
        # constants.import.UID    - The key contained new user IDs.
        # constants.import.SIG    - The key contained new signatures.
        # constants.import.SUBKEY - The key contained new sub keys.
        # constants.import.SECRET - The key contained a secret key.
        # It would be nice to highlight new things as well.
        self.load_keys()
        #if result:
        #    impkey = result.imports
        #    while impkey:
        #        if impkey.status & constants.import.NEW:
        #            self.add_key(self.context.get_key(impkey.fpr, 0))
        #        impkey = impkey.next

    def on_delete_activate(self, obj):
        "self.on_delete_activate(obj) - callback for key deletion request"
        selection = self.treeview.get_selection()
        if selection.count_selected_rows() > 0:
            key_list = []
            selection.selected_foreach(self.collect_keys, key_list)
            
            message = "Delete selected keys?\n"
            for key, row in key_list:
                message += "\n%s\t" % key.subkeys[0].keyid
                if key.uids: message += key.uids[0].uid
                else:        message += "<undefined>"                
            if self.yesno_message(message):
                for key, row in key_list:
                    self.context.op_delete(key, 1)
                    row.model.remove(row.iter)

    def get_widget_values(self, widgets):
        "Create an array of values from widgets' getter methods"
        return [getattr(self.wtree.get_widget(w),"get_"+f)() for w,f in widgets]

    def set_widget_values(self, widgets, values):
        "Set values using widgets' setter methods"
        for (w,f), v in zip(widgets, values):
            # ComboBox.set_active_iter(None) does not reset active. Fixing.
            if f == "active_iter" and v == None:
                f, v = "active", -1
            getattr(self.wtree.get_widget(w), "set_"+f)(v)

    def key_type_changed(self, which):
        """self.key_type_changed([\"key\"|\"subkey\"]) - helper function to
        adjust allowed key length based on the Algorithm selected"""
        (key_type,) = self.get_widget_values([(which+"_type", "active_iter")])
        if key_type:
            key_type = self.wtree.get_widget(which+"_type").get_model(
                ).get_value(key_type,0)
            length_widget = self.wtree.get_widget(which+"_length")
            if key_type == "DSA":
                length_widget.set_range(1024, 1024)
                length_widget.set_value(1024)
            elif key_type == "RSA" or key_type == "ELG-E":
                length_widget.set_range(1024, 4096)

    def on_key_type_changed(self, obj):
        self.key_type_changed("key")

    def on_subkey_type_changed(self, obj):
        self.key_type_changed("subkey")

    def on_expire_calendar_day_selected(self, obj):
        "Callback for selecting a day on the calendar"
        (year, month, day)=self.wtree.get_widget("expire_calendar").get_date()
        expander = self.wtree.get_widget("expire_date")
        # Past dates means no expiration date
        if time.localtime() < (year, month+1, day):
            expander.set_label("%04d-%02d-%02d" % (year, month+1, day))
        else:
            expander.set_label("Unlimited")
        expander.set_expanded(False)

    def on_generate_activate(self, obj):
        "Callback to generate new key"
        
        # Set of (widget, common suffix of getter/setter function) tuples
        # from the GenerateDialog prompt for new key properties.
        widgets = [
            ("key_type", "active_iter"),
            ("key_length", "value"),
            ("key_encrypt", "active"),
            ("key_sign", "active"),
            ("subkey_type", "active_iter"),
            ("subkey_length", "value"),
            ("subkey_encrypt", "active"),
            ("subkey_sign", "active"),
            ("name_real", "text"),
            ("name_comment", "text"),
            ("name_email", "text"),
            ("expire_date", "label"),
            ("passphrase", "text"),
            ("passphrase_repeat", "text")
            ]

        saved_values = self.get_widget_values(widgets)
        result = None
        dialog = self.wtree.get_widget("GenerateDialog")
        if dialog.run() == gtk.RESPONSE_OK:
            (key_type, key_length, key_encrypt, key_sign,
             subkey_type, subkey_length, subkey_encrypt, subkey_sign,
             name_real, name_comment, name_email, expire_date,
             passphrase, passphrase2) = self.get_widget_values(widgets)
            if key_type and passphrase == passphrase2:
                key_type = self.wtree.get_widget("key_type").get_model(
                    ).get_value(key_type,0)
                result = "<GnupgKeyParms format=\"internal\">\n"
                result += "Key-Type: %s\n" % key_type
                result += "Key-Length: %d\n" % int(key_length)
                if key_encrypt or key_sign:
                    result += "Key-Usage:" + \
                              ((key_encrypt and " encrypt") or "") + \
                              ((key_sign and " sign") or "") + "\n"
                if subkey_type:
                    subkey_type=self.wtree.get_widget("subkey_type").get_model(
                        ).get_value(subkey_type,0)
                    result += "Subkey-Type: %s\n" % subkey_type
                    result += "Subkey-Length: %d\n" % int(subkey_length)
                    if subkey_encrypt or subkey_sign:
                        result += "Subkey-Usage:" + \
                                  ((subkey_encrypt and " encrypt") or "") + \
                                  ((subkey_sign and " sign") or "") + "\n"
                if name_real:
                    result += "Name-Real: %s\n" % name_real
                if name_comment:
                    result += "Name-Comment: %s\n" % name_comment
                if name_email:
                    result += "Name-Email: %s\n" % name_email
                if passphrase:
                    result += "Passphrase: %s\n" % passphrase
                if expire_date != "Unlimited":
                    result += "Expire-Date: %s\n" % expire_date
                else:
                    result += "Expire-Date: 0\n"
                result += "</GnupgKeyParms>\n"
            else:
                if not key_type:
                    message = "Type of the primary key is not specified."
                elif passphrase != passphrase2:
                    message = "Passphrases do not match."
                else:
                    message = "Unknown error."
                self.error_message(message, dialog)
        else:
            self.set_widget_values(widgets, saved_values)

        dialog.hide()
        if result:
            # Setup and show progress Dialog
            self.progress = ""
            self.progress_entry = self.wtree.get_widget(
                "progress_entry").get_buffer()
            self.progress_entry.set_text("")
            gobject.timeout_add(500, self.update_progress)
            self.wtree.get_widget("GenerateProgress").show_all()
            # Start asynchronous key generation
            self.context.op_genkey_start(result, None, None)

    def gen_progress(self, what=None, type=None, current=None,
                     total=None, hook=None):
        "Gpg's progress_cb"
        if self.progress != None:
            self.progress += "%c" % type
        else:
            sys.stderr.write("%c" % type)

    def update_progress(self):
        "Timeout callback to yeild to gpg and update progress Dialog view"
        status = self.context.wait(False)
        if status == None:
            self.progress_entry.set_text(self.progress)
            return True
        elif status == 0:
            fpr = self.context.op_genkey_result().fpr
            self.add_key(self.context.get_key(fpr, 0), True)
        self.wtree.get_widget("GenerateProgress").hide()
        self.progress = None

        if status:
            self.error_message("Got an error during key generation:\n%s" %
                               errors.GPGMEError(status).getstring())

        # Let callback to be removed.
        return False

    def on_generating_close_clicked(self, obj):
        # Request cancelation of the outstanding asynchronous call
        self.context.cancel()

    def get_password(self, hint, desc, hook):
        "Gpg's password_cb"
        dialog = self.wtree.get_widget("PasswordDialog")
        label = self.wtree.get_widget("pwd_prompt")
        entry = self.wtree.get_widget("password")
        label.set_text("Please supply %s's password%s:" %
                       (hint, (hook and (' '+hook)) or ''))
        if dialog.run() == gtk.RESPONSE_OK:
            result = entry.get_text()
        else:
            result = ""
        entry.set_text("")
        dialog.hide()
        return result

    def on_reload_activate(self, obj):
        self.load_keys()

    def on_about_activate(self, obj):
        about = self.wtree.get_widget("AboutDialog")
        about.run()
        about.hide()

    def __init__(self, path):
        "new(path) path - location of the glade file"
        gladefile = os.path.join(path, "PyGtkGpgKeys.glade")
        self.wtree = gtk.glade.XML(gladefile)
        self.wtree.signal_autoconnect(self)

        self.mainwin = self.wtree.get_widget("GPGAdminWindow")
        self.treeview = self.wtree.get_widget("GPGKeysView")

        self.model = gtk.TreeStore(*[x.type for x in visible_columns +
                                     helper_columns])        

        self.context = Context()
        self.context.set_passphrase_cb(self.get_password, "")
        self.progress = None
        self.context.set_progress_cb(self.gen_progress, None)
        # Use mode.SIGS to include signatures in the list.
        self.context.set_keylist_mode(mode.SIGS)
        self.load_keys(True)

        self.treeview.set_model(self.model)
        self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        self.add_columns()

        gtk.main()

    def on_Exit(self, obj):
        gtk.main_quit()
예제 #11
0
def addPassword():
	""" Model's not there? Fix it before we get into worse trouble. """
	if not [m for m in mw.deck.models if m.name == MODEL]:
		m = Model(unicode(MODEL))
		m.addFieldModel(FieldModel(u'Description', True, True))
		m.addFieldModel(FieldModel(u'HMAC_%s' % HASH, True, True))
		m.addFieldModel(FieldModel(u'GPG', True, True))
		cm=CardModel(u'Password',u'%(Description)s',u'%%(HMAC_%s)s' % HASH)
		cm.typeAnswer = u'HMAC_%s' % HASH
		m.addCardModel(cm)
		mw.deck.addModel(m)
	else:
		m, = [m for m in mw.deck.models if m.name == MODEL]
		# Monkey patch existing models
		if 'HMAC_%s' % HASH not in [ a.name for a in m.fieldModels ]:
			m.addFieldModel(FieldModel(u'HMAC_%s' % HASH, True, True))

	ret = QInputDialog.getText(mw, "Description", "Enter a description for the password")
	if ret[1]:
		desc = unicode(ret[0])
	else:
		return

	ret = QInputDialog.getText(mw, "Password", "Enter the password", QLineEdit.Password)
	if ret[1]:
		pass1 = unicode(ret[0])
	else:
		return

	ret = QInputDialog.getText(mw, "Confirm", "Confirm the password", QLineEdit.Password)
	if ret[1]:
		pass2 = unicode(ret[0])
	else:
		return

	if pass1 != pass2:
		QMessageBox.information(mw, "Mismatch", "Your passwords didn't match")
		return

	""" Attempt to add the card. """
	try:
		fact = mw.deck.newFact()

		fact['Description'] = desc

		""" Fill in the MAC """
		mac = hmac.new(config.key, pass1.encode('utf-8'), getattr(hashlib, HASH))
		fact['HMAC_%s' % HASH] = unicode(mac.hexdigest())

		""" PyMe setup """
		c = Context();
		c.set_armor(1);
		c.op_keylist_start(GPG_USER_NAME, 0)
		key = c.op_keylist_next()

		if not key:
			QMessageBox.information(mw, "Error", "Could not find your key. Check you've set it up in the plugin file.")
			return

		print "Encrypting with key: " + key.uids[0].uid

		""" Do the encryption, or try to """
		plain = Data(pass1.encode('utf-8'))
		cipher = Data()
		try:
			c.op_encrypt([key], 1, plain, cipher)
			cipher.seek(0,0)
			fact['GPG'] = unicode(re.sub("\n","<br>",cipher.read()), 'ascii')
			mw.deck.addFact(fact)
		except GPGMEError, e:
			QMessageBox.information(mw, "Error", "Could not encrypt your password.\nError: " + str(e))

	except FactInvalidError, e:
		QMessageBox.information(mw, "Error", "Could not store your password.\nError: " + str(e))
예제 #12
0
class PyGtkGpgKeys:
    "Main class representing PyGtkGpgKeys application"

    def error_message(self, text, parent=None):
        dialog = gtk.MessageDialog(
            parent or self.mainwin,
            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
            gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, text)
        dialog.run()
        dialog.destroy()

    def yesno_message(self, text, parent=None):
        dialog = gtk.MessageDialog(
            parent or self.mainwin,
            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
            gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, text)
        result = dialog.run() == gtk.RESPONSE_YES
        dialog.destroy()
        return result

    def load_keys(self, first_time=False):
        if not first_time: self.model.clear()
        secret_keys = {}
        for key in self.context.op_keylist_all(None, 1):
            secret_keys[key.subkeys[0].fpr] = 1
        for key in self.context.op_keylist_all(None, 0):
            self.add_key(key, secret_keys.has_key(key.subkeys[0].fpr))

    def add_key(self, key, secret):
        "self.add_key(key) - add key to the TreeStore model"
        iter = self.model.append(None)
        # Can delete only the whole key
        param = (iter, ) + pair("Secret", secret)
        # Key information is a combination of the key and first uid and subkey
        for col in key_columns:
            param += pair(col, key)
        for col in uid_columns:
            param += pair(col, key.uids[0])
        for col in sub_columns:
            param += pair(col, key.subkeys[0])
        for col in sub_sign_columns:
            param += pair(col, key.subkeys[0])
        self.model.set(*param)
        if key.uids:
            self.add_signatures(key.uids[0].signatures, iter)
            self.add_uids(key.uids[1:], iter)
        self.add_subkeys(key.subkeys[1:], iter)

    def add_subkeys(self, subkeys, iter):
        "self.add_subkeys(subkey, iter) - add subkey as child to key's iter"
        if not subkeys:
            return
        key_iter = self.model.append(iter)
        self.model.set(key_iter, columns["Name"].index, "Subkeys", *name_only)
        for subkey in subkeys:
            child_iter = self.model.append(key_iter)
            param = (child_iter, )
            for col in sub_columns:
                param += pair(col, subkey)
            for col in sub_sign_columns:
                param += pair(col, subkey)
            self.model.set(*param)

    def add_uids(self, uids, iter):
        "self.add_uids(uid, iter) - add uid as a child to key's iter"
        if not uids:
            return
        uid_iter = self.model.append(iter)
        self.model.set(uid_iter, columns["Name"].index, "Other UIDs",
                       *name_only)
        for uid in uids:
            child_iter = self.model.append(uid_iter)
            param = (child_iter, )
            for col in uid_columns:
                param += pair(col, uid)
            self.model.set(*param)
            self.add_signatures(uid.signatures, child_iter)

    def add_signatures(self, signs, iter):
        "self.add_signatures(sign, iter) - add signature as a child to iter"
        if not signs:
            return
        sign_iter = self.model.append(iter)
        self.model.set(sign_iter, columns["Name"].index, "Signatures",
                       *name_only)
        for sign in signs:
            child_iter = self.model.append(sign_iter)
            param = (child_iter, )
            for col in uid_columns:
                param += pair(col, sign)
            for col in sign_columns:
                param += pair(col, sign)
            for col in sub_sign_columns:
                param += pair(col, sign)
            self.model.set(*param)

    def add_columns(self):
        "Add viewable columns for the data in TreeStore model"
        view_menu = gtk.Menu()
        for item in visible_columns:
            if item.type == gobject.TYPE_BOOLEAN:
                renderer = gtk.CellRendererToggle()
                item.attrs["active"] = item.index
            else:
                renderer = gtk.CellRendererText()
                item.attrs["text"] = item.index
            column = self.treeview.insert_column_with_attributes(
                item.index, item.name, renderer, **item.attrs)
            column.set_sort_column_id(item.index)
            # Create callback for a View menu item
            if item.view != None:
                check = gtk.CheckMenuItem(item.name)
                check.set_active(item.view)
                check.connect("activate",
                              lambda x, y: y.set_visible(x.get_active()),
                              column)
                view_menu.append(check)
                column.set_visible(check.get_active())

        view_menu.show_all()
        self.wtree.get_widget("view_menu").set_submenu(view_menu)

    def on_GPGKeysView_button_press_event(self, obj, event):
        if event.button != 3:
            return False

        menu = gtk.Menu()
        for title, callback in [
            ("Reload", self.on_reload_activate), (None, None),
            ("Delete", self.on_delete_activate),
            ("Export (txt)", self.on_export_keys_text_activate),
            ("Export (bin)", self.on_export_keys_activate)
        ]:
            if title:
                item = gtk.MenuItem(title)
                item.connect("activate", callback)
            else:
                item = gtk.SeparatorMenuItem()
            menu.append(item)
        menu.show_all()

        menu.popup(None, None, None, event.button, event.time)
        return True

    def editor_func(self, status, args, val_dict):
        state = val_dict["state"]
        prompt = "%s %s" % (state, args)
        if val_dict.has_key(prompt):
            val_dict["state"] = val_dict[prompt][0]
            return val_dict[prompt][1]
        elif args:
            sys.stderr.write("Unexpected prompt in editor_func: %s\n" % prompt)
            raise EOFError()
        return ""

    def change_key_trust(self, key, new_trust):
        val_dict = {
            "state": "start",
            "start keyedit.prompt": ("trust", "trust"),
            "trust edit_ownertrust.value": ("prompt", "%d" % new_trust),
            "prompt edit_ownertrust.set_ultimate.okay": ("prompt", "Y"),
            "prompt keyedit.prompt": ("finish", "quit")
        }
        out = Data()
        self.context.op_edit(key, self.editor_func, val_dict, out)

    def on_change_trust(self, new_trust):
        selection = self.treeview.get_selection()
        if selection.count_selected_rows() <= 0:
            return

        key_list = []
        selection.selected_foreach(self.collect_keys, key_list)

        message = "Change trust to %s on the following keys?\n" % \
                  trusts[new_trust]
        for key, row in key_list:
            message += "\n%s\t" % key.subkeys[0].keyid
            if key.uids: message += key.uids[0].uid
            else: message += "<undefined>"
        if self.yesno_message(message):
            for key, row in key_list:
                if key.owner_trust != new_trust:
                    self.change_key_trust(key, new_trust)
                    row[columns["Owner Trust"].index] = trusts[new_trust]

    def on_undefined_trust_activate(self, obj):
        self.on_change_trust(1)

    def on_never_trust_activate(self, obj):
        self.on_change_trust(2)

    def on_marginal_trust_activate(self, obj):
        self.on_change_trust(3)

    def on_full_trust_activate(self, obj):
        self.on_change_trust(4)

    def on_ultimate_trust_activate(self, obj):
        self.on_change_trust(5)

    def collect_keys(self, model, path, iter, key_list):
        row = model[path[:1]]
        keyid = row[columns["FPR"].index]
        key = self.context.get_key(keyid, 0)
        key_list.append((key, row))

    def export_keys(self):
        selection = self.treeview.get_selection()
        if selection.count_selected_rows() <= 0:
            return

        export_file = None
        dialog = gtk.FileChooserDialog("Export Keys (Public only) into a File",
                                       self.mainwin,
                                       gtk.FILE_CHOOSER_ACTION_SAVE,
                                       (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        gtk.STOCK_OK, gtk.RESPONSE_OK))
        while dialog.run() == gtk.RESPONSE_OK:
            filename = dialog.get_filename()
            if os.path.exists(filename):
                if os.path.isdir(filename):
                    self.error_message("%s is a directory!" % filename, dialog)
                    continue
                elif not self.yesno_message("%s exists. Override?" % filename,
                                            dialog):
                    continue

            # FIXME. Verify that file can be written to
            export_file = file(filename, "wb")
            break
        dialog.destroy()
        if export_file == None:
            return

        key_list = []
        selection.selected_foreach(self.collect_keys, key_list)
        expkeys = Data()
        for key, row in key_list:
            self.context.op_export(key.subkeys[0].fpr, 0, expkeys)
        expkeys.seek(0, 0)
        export_file.write(expkeys.read())
        export_file.close()

    def on_export_keys_activate(self, obj):
        self.context.set_armor(0)
        self.export_keys()

    def on_export_keys_text_activate(self, obj):
        self.context.set_armor(1)
        self.export_keys()

    def on_import_keys_activate(self, obj):
        import_file = None
        dialog = gtk.FileChooserDialog("Import Keys from a File", self.mainwin,
                                       gtk.FILE_CHOOSER_ACTION_OPEN,
                                       (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                        gtk.STOCK_OK, gtk.RESPONSE_OK))
        while dialog.run() == gtk.RESPONSE_OK:
            filename = dialog.get_filename()
            if os.path.exists(filename):
                if os.path.isdir(filename):
                    self.error_message("%s is a directory!" % filename, dialog)
                else:
                    # FIXME. Verify that file can be open.
                    import_file = filename
                    break
            else:
                self.error_message("%s does not exist." % filename, dialog)
        dialog.destroy()
        if import_file == None:
            return

        impkeys = Data(file=import_file)
        status = self.context.op_import(impkeys)
        if status:
            self.error_message("Import return an error message %d" % status)
        result = self.context.op_import_result()
        if result.considered == 0:
            self.error_message("There's no keys in the file.")
        # FIXME. Instead of rereading everything we could find out what's new
        # from the result based on the ORed value of impkey:
        # constants.import.NEW    - The key was new.
        # constants.import.UID    - The key contained new user IDs.
        # constants.import.SIG    - The key contained new signatures.
        # constants.import.SUBKEY - The key contained new sub keys.
        # constants.import.SECRET - The key contained a secret key.
        # It would be nice to highlight new things as well.
        self.load_keys()
        #if result:
        #    impkey = result.imports
        #    while impkey:
        #        if impkey.status & constants.import.NEW:
        #            self.add_key(self.context.get_key(impkey.fpr, 0))
        #        impkey = impkey.next

    def on_delete_activate(self, obj):
        "self.on_delete_activate(obj) - callback for key deletion request"
        selection = self.treeview.get_selection()
        if selection.count_selected_rows() > 0:
            key_list = []
            selection.selected_foreach(self.collect_keys, key_list)

            message = "Delete selected keys?\n"
            for key, row in key_list:
                message += "\n%s\t" % key.subkeys[0].keyid
                if key.uids: message += key.uids[0].uid
                else: message += "<undefined>"
            if self.yesno_message(message):
                for key, row in key_list:
                    self.context.op_delete(key, 1)
                    row.model.remove(row.iter)

    def get_widget_values(self, widgets):
        "Create an array of values from widgets' getter methods"
        return [
            getattr(self.wtree.get_widget(w), "get_" + f)() for w, f in widgets
        ]

    def set_widget_values(self, widgets, values):
        "Set values using widgets' setter methods"
        for (w, f), v in zip(widgets, values):
            # ComboBox.set_active_iter(None) does not reset active. Fixing.
            if f == "active_iter" and v == None:
                f, v = "active", -1
            getattr(self.wtree.get_widget(w), "set_" + f)(v)

    def key_type_changed(self, which):
        """self.key_type_changed([\"key\"|\"subkey\"]) - helper function to
        adjust allowed key length based on the Algorithm selected"""
        (key_type, ) = self.get_widget_values([(which + "_type", "active_iter")
                                               ])
        if key_type:
            key_type = self.wtree.get_widget(which +
                                             "_type").get_model().get_value(
                                                 key_type, 0)
            length_widget = self.wtree.get_widget(which + "_length")
            if key_type == "DSA":
                length_widget.set_range(1024, 1024)
                length_widget.set_value(1024)
            elif key_type == "RSA" or key_type == "ELG-E":
                length_widget.set_range(1024, 4096)

    def on_key_type_changed(self, obj):
        self.key_type_changed("key")

    def on_subkey_type_changed(self, obj):
        self.key_type_changed("subkey")

    def on_expire_calendar_day_selected(self, obj):
        "Callback for selecting a day on the calendar"
        (year, month,
         day) = self.wtree.get_widget("expire_calendar").get_date()
        expander = self.wtree.get_widget("expire_date")
        # Past dates means no expiration date
        if time.localtime() < (year, month + 1, day):
            expander.set_label("%04d-%02d-%02d" % (year, month + 1, day))
        else:
            expander.set_label("Unlimited")
        expander.set_expanded(False)

    def on_generate_activate(self, obj):
        "Callback to generate new key"

        # Set of (widget, common suffix of getter/setter function) tuples
        # from the GenerateDialog prompt for new key properties.
        widgets = [("key_type", "active_iter"), ("key_length", "value"),
                   ("key_encrypt", "active"), ("key_sign", "active"),
                   ("subkey_type", "active_iter"), ("subkey_length", "value"),
                   ("subkey_encrypt", "active"), ("subkey_sign", "active"),
                   ("name_real", "text"), ("name_comment", "text"),
                   ("name_email", "text"), ("expire_date", "label"),
                   ("passphrase", "text"), ("passphrase_repeat", "text")]

        saved_values = self.get_widget_values(widgets)
        result = None
        dialog = self.wtree.get_widget("GenerateDialog")
        if dialog.run() == gtk.RESPONSE_OK:
            (key_type, key_length, key_encrypt, key_sign, subkey_type,
             subkey_length, subkey_encrypt, subkey_sign, name_real,
             name_comment, name_email, expire_date, passphrase,
             passphrase2) = self.get_widget_values(widgets)
            if key_type and passphrase == passphrase2:
                key_type = self.wtree.get_widget(
                    "key_type").get_model().get_value(key_type, 0)
                result = "<GnupgKeyParms format=\"internal\">\n"
                result += "Key-Type: %s\n" % key_type
                result += "Key-Length: %d\n" % int(key_length)
                if key_encrypt or key_sign:
                    result += "Key-Usage:" + \
                              ((key_encrypt and " encrypt") or "") + \
                              ((key_sign and " sign") or "") + "\n"
                if subkey_type:
                    subkey_type = self.wtree.get_widget(
                        "subkey_type").get_model().get_value(subkey_type, 0)
                    result += "Subkey-Type: %s\n" % subkey_type
                    result += "Subkey-Length: %d\n" % int(subkey_length)
                    if subkey_encrypt or subkey_sign:
                        result += "Subkey-Usage:" + \
                                  ((subkey_encrypt and " encrypt") or "") + \
                                  ((subkey_sign and " sign") or "") + "\n"
                if name_real:
                    result += "Name-Real: %s\n" % name_real
                if name_comment:
                    result += "Name-Comment: %s\n" % name_comment
                if name_email:
                    result += "Name-Email: %s\n" % name_email
                if passphrase:
                    result += "Passphrase: %s\n" % passphrase
                if expire_date != "Unlimited":
                    result += "Expire-Date: %s\n" % expire_date
                else:
                    result += "Expire-Date: 0\n"
                result += "</GnupgKeyParms>\n"
            else:
                if not key_type:
                    message = "Type of the primary key is not specified."
                elif passphrase != passphrase2:
                    message = "Passphrases do not match."
                else:
                    message = "Unknown error."
                self.error_message(message, dialog)
        else:
            self.set_widget_values(widgets, saved_values)

        dialog.hide()
        if result:
            # Setup and show progress Dialog
            self.progress = ""
            self.progress_entry = self.wtree.get_widget(
                "progress_entry").get_buffer()
            self.progress_entry.set_text("")
            gobject.timeout_add(500, self.update_progress)
            self.wtree.get_widget("GenerateProgress").show_all()
            # Start asynchronous key generation
            self.context.op_genkey_start(result, None, None)

    def gen_progress(self,
                     what=None,
                     type=None,
                     current=None,
                     total=None,
                     hook=None):
        "Gpg's progress_cb"
        if self.progress != None:
            self.progress += "%c" % type
        else:
            sys.stderr.write("%c" % type)

    def update_progress(self):
        "Timeout callback to yeild to gpg and update progress Dialog view"
        status = self.context.wait(False)
        if status == None:
            self.progress_entry.set_text(self.progress)
            return True
        elif status == 0:
            fpr = self.context.op_genkey_result().fpr
            self.add_key(self.context.get_key(fpr, 0), True)
        self.wtree.get_widget("GenerateProgress").hide()
        self.progress = None

        if status:
            self.error_message("Got an error during key generation:\n%s" %
                               errors.GPGMEError(status).getstring())

        # Let callback to be removed.
        return False

    def on_generating_close_clicked(self, obj):
        # Request cancelation of the outstanding asynchronous call
        self.context.cancel()

    def get_password(self, hint, desc, hook):
        "Gpg's password_cb"
        dialog = self.wtree.get_widget("PasswordDialog")
        label = self.wtree.get_widget("pwd_prompt")
        entry = self.wtree.get_widget("password")
        label.set_text("Please supply %s's password%s:" %
                       (hint, (hook and (' ' + hook)) or ''))
        if dialog.run() == gtk.RESPONSE_OK:
            result = entry.get_text()
        else:
            result = ""
        entry.set_text("")
        dialog.hide()
        return result

    def on_reload_activate(self, obj):
        self.load_keys()

    def on_about_activate(self, obj):
        about = self.wtree.get_widget("AboutDialog")
        about.run()
        about.hide()

    def __init__(self, path):
        "new(path) path - location of the glade file"
        gladefile = os.path.join(path, "PyGtkGpgKeys.glade")
        self.wtree = gtk.glade.XML(gladefile)
        self.wtree.signal_autoconnect(self)

        self.mainwin = self.wtree.get_widget("GPGAdminWindow")
        self.treeview = self.wtree.get_widget("GPGKeysView")

        self.model = gtk.TreeStore(
            *[x.type for x in visible_columns + helper_columns])

        self.context = Context()
        self.context.set_passphrase_cb(self.get_password, "")
        self.progress = None
        self.context.set_progress_cb(self.gen_progress, None)
        # Use mode.SIGS to include signatures in the list.
        self.context.set_keylist_mode(mode.SIGS)
        self.load_keys(True)

        self.treeview.set_model(self.model)
        self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        self.add_columns()

        gtk.main()

    def on_Exit(self, obj):
        gtk.main_quit()
예제 #13
0
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
"""
This program will try to encrypt a simple message to each key on your keyring.
If your keyring has any invalid keys on it, those keys will be removed
and it will re-try the encryption."""

from pyme import core
from pyme.core import Data, Context
from pyme.constants import validity

core.check_version(None)

plain = Data('This is my message.')

c = Context()
c.set_armor(1)


def sendto(keylist):
    cipher = Data()
    c.op_encrypt(keylist, 1, plain, cipher)
    cipher.seek(0, 0)
    return cipher.read()


names = []
for key in c.op_keylist_all(None, 0):
    print " *** Found key for %s" % key.uids[0].uid
    valid = 0
    for subkey in key.subkeys: