157 lines
5.3 KiB
Python
157 lines
5.3 KiB
Python
#!/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()
|