#!/usr/bin/env python import sys, os from PyQt4 import QtGui, QtCore from backups.backup4 import MBDB from keychain.keychain4 import Keychain4 from util.bplist import BPlistReader from keystore.keybag import Keybag from util import readPlist class KeychainTreeWidget(QtGui.QTreeWidget): def __init__(self, parent=None): QtGui.QTreeWidget.__init__(self, parent) self.setGeometry(10, 10, 780, 380) self.header().hide() self.setColumnCount(2) class KeychainTreeWidgetItem(QtGui.QTreeWidgetItem): def __init__(self, title): QtGui.QTreeWidgetItem.__init__(self, [title]) fnt = self.font(0) fnt.setBold(True) self.setFont(0, fnt) self.setColors() def setText(self, column, title): QtGui.QTreeWidgetItem.setText(self, column, title) def setColors(self): self.setForeground(0, QtGui.QBrush(QtGui.QColor(80, 80, 80))) self.setBackground(0, QtGui.QBrush(QtGui.QColor(230, 230, 230))) self.setBackground(1, QtGui.QBrush(QtGui.QColor(230, 230, 230))) class LockedKeychainTreeWidgetItem(KeychainTreeWidgetItem): def setColors(self): self.setForeground(0, QtGui.QBrush(QtGui.QColor(255, 80, 80))) self.setBackground(0, QtGui.QBrush(QtGui.QColor(255, 230, 230))) self.setBackground(1, QtGui.QBrush(QtGui.QColor(255, 230, 230))) class KeychainWindow(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.setGeometry(100, 100, 800, 400) self.setWindowTitle('Keychain Explorer') self.passwordTree = KeychainTreeWidget(parent=self) def setGenericPasswords(self, pwds): self.genericPasswords = pwds self.passwordItems = KeychainTreeWidgetItem('Generic Passwords') for pwd in self.genericPasswords: if not pwd.has_key('acct'): continue if len(pwd['acct']) > 0: item_title = '%s (%s)' % (pwd['svce'], pwd['acct']) else: item_title = pwd['svce'] if pwd['data'] is None: item = LockedKeychainTreeWidgetItem(item_title) else: item = KeychainTreeWidgetItem(item_title) item.addChild(QtGui.QTreeWidgetItem(['Service', pwd['svce']])) item.addChild(QtGui.QTreeWidgetItem(['Account', pwd['acct']])) if pwd['data'] is not None: item.addChild(QtGui.QTreeWidgetItem(['Data', pwd['data']])) else: item.addChild(QtGui.QTreeWidgetItem(['Data', 'N/A'])) item.addChild(QtGui.QTreeWidgetItem(['Access Group', pwd['agrp']])) self.passwordItems.addChild(item) self.passwordTree.addTopLevelItem(self.passwordItems) self.passwordTree.expandAll() self.passwordTree.resizeColumnToContents(0) def setInternetPasswords(self, pwds): self.internetPasswords = pwds self.internetPasswordItems = KeychainTreeWidgetItem('Internet Passwords') for pwd in pwds: item_title = '%s (%s)' % (pwd['srvr'], pwd['acct']) item = KeychainTreeWidgetItem(item_title) item.addChild(QtGui.QTreeWidgetItem(['Server', pwd['srvr']])) item.addChild(QtGui.QTreeWidgetItem(['Account', pwd['acct']])) if pwd['data'] is not None: item.addChild(QtGui.QTreeWidgetItem(['Data', pwd['data']])) else: item.addChild(QtGui.QTreeWidgetItem(['Data', 'N/A'])) item.addChild(QtGui.QTreeWidgetItem(['Port', str(pwd['port'])])) item.addChild(QtGui.QTreeWidgetItem(['Access Group', pwd['agrp']])) self.internetPasswordItems.addChild(item) self.passwordTree.addTopLevelItem(self.internetPasswordItems) self.passwordTree.expandAll() self.passwordTree.resizeColumnToContents(0) def warn(msg): print "WARNING: %s" % msg def getBackupKeyBag(backupfolder, passphrase): manifest = readPlist(backupfolder + "/Manifest.plist") kb = Keybag(manifest["BackupKeyBag"].data) if kb.unlockBackupKeybagWithPasscode(passphrase): print "BackupKeyBag unlock OK" return kb else: return None def main(): app = QtGui.QApplication(sys.argv) init_path = "{0:s}/Apple Computer/MobileSync/Backup".format(os.getenv('APPDATA')) dirname = QtGui.QFileDialog.getExistingDirectory(None, "Select iTunes backup directory", init_path) kb = getBackupKeyBag(dirname, 'pouet') #XXX: hardcoded password for demo if not kb: warn("Backup keybag unlock fail : wrong passcode?") return db = MBDB(dirname) db.keybag = kb filename, record = db.get_file_by_name("keychain-backup.plist") keychain_data = db.read_file(filename, record) f = file('keychain.tmp', 'wb') f.write(keychain_data) f.close() kc = Keychain4('keychain.tmp', kb) pwds = kc.get_passwords() inet_pwds = kc.get_inet_passwords() qb = KeychainWindow() qb.setGenericPasswords(pwds) qb.setInternetPasswords(inet_pwds) qb.show() sys.exit(app.exec_()) pass if __name__ == '__main__': main()