Esempio n. 1
0
 def __init__(self, filename):
     magic = open(filename, "rb").read(16)
     if magic.startswith("SQLite"):
         self.store = SQLiteKeychain(filename)
     elif magic.startswith("bplist"):
         self.store = PlistKeychain(filename)
     else:
         raise Exception("Unknown keychain format for %s" % filename)
     self.bsanitize = True
     self.items = {"genp": None, "inet": None, "cert": None, "keys": None}
Esempio n. 2
0
class Keychain(object):
    def __init__(self, filename):
        magic = open(filename, "rb").read(16)
        if magic.startswith("SQLite"):
            self.store = SQLiteKeychain(filename)
        elif magic.startswith("bplist"):
            self.store = PlistKeychain(filename)
        else:
            raise Exception("Unknown keychain format for %s" % filename)
        self.bsanitize = True
        self.items = {"genp": None, "inet": None, "cert": None, "keys": None}

    def decrypt_data(self, data):
        return data  #override this method

    def decrypt_item(self, res):
        res["data"] = self.decrypt_data(res["data"])
        if not res["data"]:
            return {}
        return res

    def get_items(self, table):
        if self.items[table]:
            return self.items[table]
        self.items[table] = filter(
            lambda x: x != {},
            map(self.decrypt_item, self.store.get_items(table)))
        return self.items[table]

    def get_passwords(self):
        return self.get_items("genp")

    def get_inet_passwords(self):
        return self.get_items("inet")

    def get_keys(self):
        return self.get_items("keys")

    def get_cert(self):
        return self.get_items("cert")

    def get_certs(self):
        certs = {}
        pkeys = {}
        keys = self.get_keys()
        for row in self.get_cert():
            cert = M2Crypto.X509.load_cert_der_string(row["data"])
            subject = cert.get_subject().as_text()
            common_name = cert.get_subject().get_entries_by_nid(
                M2Crypto.X509.X509_Name.nid['CN'])
            if len(common_name):
                subject = str(common_name[0].get_data())
            else:
                subject = "cn_unknown_%d" % row["rowid"]
            certs[subject + "_%s" % row["agrp"]] = cert

            for k in keys:
                if k["agrp"] == row["agrp"] and k["klbl"] == row["pkhh"]:
                    pkey_der = k["data"]
                    pkey_der = RSA_KEY_DER_to_PEM(pkey_der)
                    pkeys[subject + "_%s" % row["agrp"]] = pkey_der
                    break

        return certs, pkeys

    def save_passwords(self):
        passwords = "\n".join(map(render_password, self.get_passwords()))
        inetpasswords = "\n".join(
            map(render_password, self.get_inet_passwords()))
        print "Writing passwords to keychain.csv"
        write_file(
            "keychain.csv", "Passwords;;\n" + passwords +
            "\nInternet passwords;;\n" + inetpasswords)

    def save_certs_keys(self):
        certs, pkeys = self.get_certs()
        for c in certs:
            filename = c + ".crt"
            print "Saving certificate %s" % filename
            certs[c].save_pem(filename)
        for k in pkeys:
            filename = k + ".key"
            print "Saving key %s" % filename
            write_file(filename, pkeys[k])

    def sanitize(self, pw):
        if pw.startswith("bplist"):
            return "<binary plist data>"
        elif not set(pw).issubset(printset):
            pw = "<binary data> : " + pw.encode("hex")
        if self.bsanitize:
            return pw[:2] + ("*" * (len(pw) - 2))
        return pw

    def print_all(self, sanitize=True):
        self.bsanitize = sanitize
        print "-" * 60
        print " " * 20 + "Passwords"
        print "-" * 60

        for p in self.get_passwords():
            print "Service :\t" + p["svce"]
            print "Account :\t" + str(p["acct"])
            print "Password :\t" + self.sanitize(p["data"])
            print "Agrp :\t" + p["agrp"]
            print "-" * 60

        for p in self.get_inet_passwords():
            print "Server : \t" + p["srvr"] + ":" + str(p["port"])
            print "Account : \t" + str(p["acct"])
            print "Password : \t" + self.sanitize(p["data"])
            print "-" * 60

        certs, pkeys = self.get_certs()

        print " " * 20 + "Certificates"
        print "-" * 60
        for c in sorted(certs.keys()):
            print c

        print "-" * 60
        print " " * 20 + "Private keys"

        for k in sorted(pkeys.keys()):
            print k
        print "-" * 60

    def get_push_token(self):
        for p in self.get_passwords():
            if p["svce"] == "push.apple.com":
                return p["data"]

    def get_managed_configuration(self):
        for p in self.get_passwords():
            if p["acct"] == "Private" and p[
                    "svce"] == "com.apple.managedconfiguration" and p[
                        "agrp"] == "apple":
                return BPlistReader.plistWithString(p["data"])

    def _diff(self, older, res, func, key):
        res.setdefault(key, [])
        current = func(self)
        for p in func(older):
            if not p in current and not p in res[key]:
                res[key].append(p)

    def diff(self, older, res):
        self._diff(older, res, Keychain.get_passwords, "genp")
        self._diff(older, res, Keychain.get_inet_passwords, "inet")
        self._diff(older, res, Keychain.get_cert, "cert")
        self._diff(older, res, Keychain.get_keys, "keys")
Esempio n. 3
0
class Keychain(object):
    def __init__(self, filename):
        magic = open(filename, "rb").read(16)
        if magic.startswith("SQLite"):
            self.store = SQLiteKeychain(filename)
        elif magic.startswith("bplist"):
            self.store = PlistKeychain(filename)
        else:
            raise Exception("Unknown keychain format for %s" % filename)
        self.bsanitize = True
        self.items = {"genp": None, "inet": None, "cert": None, "keys": None}
        
    def decrypt_data(self, data):
        return data #override this method

    def decrypt_item(self, res):
        res["data"] = self.decrypt_data(res["data"])
        if not res["data"]:
            return {}             
        return res

    def get_items(self, table):
        if self.items[table]:
            return self.items[table]
        self.items[table] = filter(lambda x:x!={}, map(self.decrypt_item, self.store.get_items(table)))
        return self.items[table]

    def get_passwords(self):
        return self.get_items("genp")

    def get_inet_passwords(self):
        return self.get_items("inet")

    def get_keys(self):
        return self.get_items("keys")

    def get_cert(self):
        return self.get_items("cert")

    def get_certs(self):
        certs = {}
        pkeys = {}
        if not M2Crypto:
            print "M2Crypto missing for get_certs"
            return certs, pkeys
        keys = self.get_keys()
        for row in self.get_cert():
            subject = get_CN_from_der_cert(row["data"])
            if not subject:
                subject = "cn_unknown_%d" % row["rowid"]
            certs[subject+ "_%s" % row["agrp"]] = cert
            
            #print subject
            #print "Access :\t" + KSECATTRACCESSIBLE.get(row["clas"])
            
            for k in keys:
                if k["agrp"] == row["agrp"] and k["klbl"] == row["pkhh"]:
                    pkey_der = k["data"]
                    pkey_der = RSA_KEY_DER_to_PEM(pkey_der)
                    pkeys[subject + "_%s" % row["agrp"]] = pkey_der
                    break

        return certs, pkeys


    def save_passwords(self):
        passwords = "\n".join(map(render_password,  self.get_passwords()))
        inetpasswords = "\n".join(map(render_password,  self.get_inet_passwords()))
        print "Writing passwords to keychain.csv"
        write_file("keychain.csv", "Passwords;;\n"+passwords+"\nInternet passwords;;\n"+ inetpasswords)

    def save_certs_keys(self):
        certs, pkeys = self.get_certs()
        for c in certs:
            filename = c + ".crt"
            print "Saving certificate %s" % filename
            certs[c].save_pem(filename)
        for k in pkeys:
            filename = k + ".key"
            print "Saving key %s" % filename
            write_file(filename, pkeys[k])

    def sanitize(self, pw):
        if pw.startswith("bplist"):
            return "<binary plist data>"
        elif not set(pw).issubset(printset):
            pw = ">"+ pw.encode("hex")
            #pw = "<binary data> : " + pw.encode("hex")
        if self.bsanitize:
            return pw[:2] + ("*" * (len(pw) - 2))
        return pw

    def print_all(self, sanitize=True):
        self.bsanitize = sanitize
        headers = ["Service", "Account", "Data", "Access group", "Protection class"]
        rows = []
        for p in self.get_passwords():
            row = [p.get("svce","?"),
                   str(p.get("acct","?"))[:40],
                   self.sanitize(p.get("data","?"))[:20],
                   p.get("agrp","?"),
                   KSECATTRACCESSIBLE.get(p["clas"])[18:]]
            rows.append(row)
        
        print_table("Passwords", headers, rows)

        headers = ["Server", "Account", "Data", "Access group", "Protection class"]
        rows = []

        for p in self.get_inet_passwords():
            addr = "?"
            if p.has_key("srvr"):
                addr = p["srvr"] + ":" + str(p["port"])
            row = [addr,
                   str(p.get("acct","?")),
                   self.sanitize(p.get("data","?"))[:20],
                   p.get("agrp","?"),
                   KSECATTRACCESSIBLE.get(p["clas"])[18:]]
            rows.append(row)

        print_table("Internet Passwords", headers, rows)

        headers = ["Id", "Common Name", "Access group", "Protection class"]
        rows = []
        c  = {}

        for row in self.get_cert():
            subject = "?"
            if row.has_key("data"):
                subject = get_CN_from_der_cert(row["data"])
                if not subject:
                    subject = "cn_unknown_%d" % row["rowid"]
                c[hashlib.sha1(str(row["pkhh"])).hexdigest() + row["agrp"]] = subject
            row = [str(row["rowid"]), 
                   subject[:81],
                   row.get("agrp","?")[:31],
                   KSECATTRACCESSIBLE.get(row["clas"])[18:]
                   ]
            rows.append(row)
        
        print_table("Certificates", headers, rows)
        
        headers = ["Id", "Label", "Common Name", "Access group", "Protection class"]
        rows = []
        for row in self.get_keys():
            subject = ""
            if row.has_key("klbl"):
                subject = c.get(hashlib.sha1(str(row["klbl"])).hexdigest() + row["agrp"], "")
            row = [str(row["rowid"]), row.get("labl", "?")[:30], subject[:39], row.get("agrp","?")[:31],
                KSECATTRACCESSIBLE.get(row["clas"])[18:]]
            rows.append(row)
        print_table("Keys", headers, rows)

    def get_push_token(self):
        for p in self.get_passwords():
            if p["svce"] == "push.apple.com":
                return p["data"]
    
    def get_managed_configuration(self):
        for p in self.get_passwords():
            if p["acct"] == "Private" and p["svce"] == "com.apple.managedconfiguration" and p["agrp"] == "apple":
                return BPlistReader.plistWithString(p["data"])
    
    def _diff(self, older, res, func, key):
        res.setdefault(key, []) 
        current = func(self)  
        for p in func(older):
            if not p in current and not p in res[key]:
                res[key].append(p)

    def diff(self, older, res):
        self._diff(older, res, Keychain.get_passwords, "genp")
        self._diff(older, res, Keychain.get_inet_passwords, "inet")
        self._diff(older, res, Keychain.get_cert, "cert")
        self._diff(older, res, Keychain.get_keys, "keys")

    def cert(self, rowid, filename=""):
        for row in self.get_cert():
            if row["rowid"] == rowid:
                blob = CERT_DER_to_PEM(row["data"])
                if filename:
                    write_file(filename, blob)
                if not M2Crypto: continue
                cert = M2Crypto.X509.load_cert_der_string(row["data"])
                print cert.as_text()
                return

    def key(self, rowid, filename=""):
        for row in self.get_keys():
            if row["rowid"] == rowid:
                blob =  RSA_KEY_DER_to_PEM(row["data"])
                if filename:
                    write_file(filename, blob)
                #k = M2Crypto.RSA.load_key_string(blob)
                print blob
                return
Esempio n. 4
0
class Keychain(object):
    def __init__(self, filename):
        magic = open(filename, "rb").read(16)
        if magic.startswith("SQLite"):
            self.store = SQLiteKeychain(filename)
        elif magic.startswith("bplist"):
            self.store = PlistKeychain(filename)
        else:
            raise Exception("Unknown keychain format for %s" % filename)
        self.bsanitize = True
        self.items = {"genp": None, "inet": None, "cert": None, "keys": None}
        
    def decrypt_data(self, data):
        return data #override this method

    def decrypt_item(self, res):
        res["data"] = self.decrypt_data(res["data"])
        if not res["data"]:
            return {}             
        return res

    def get_items(self, table):
        if self.items[table]:
            return self.items[table]
        self.items[table] = filter(lambda x:x!={}, map(self.decrypt_item, self.store.get_items(table)))
        return self.items[table]

    def get_passwords(self):
        return self.get_items("genp")

    def get_inet_passwords(self):
        return self.get_items("inet")

    def get_keys(self):
        return self.get_items("keys")

    def get_cert(self):
        return self.get_items("cert")

    def get_certs(self):
        certs = {}
        pkeys = {}
        keys = self.get_keys()
        for row in self.get_cert():
            cert = M2Crypto.X509.load_cert_der_string(row["data"])
            subject = cert.get_subject().as_text()
            common_name = cert.get_subject().get_entries_by_nid(M2Crypto.X509.X509_Name.nid['CN'])
            if len(common_name):
                subject = str(common_name[0].get_data())
            else:
                subject = "cn_unknown_%d" % row["rowid"]
            certs[subject+ "_%s" % row["agrp"]] = cert
            
            for k in keys:
                if k["agrp"] == row["agrp"] and k["klbl"] == row["pkhh"]:
                    pkey_der = k["data"]
                    pkey_der = RSA_KEY_DER_to_PEM(pkey_der)
                    pkeys[subject + "_%s" % row["agrp"]] = pkey_der
                    break

        return certs, pkeys


    def save_passwords(self):
        passwords = "\n".join(map(render_password,  self.get_passwords()))
        inetpasswords = "\n".join(map(render_password,  self.get_inet_passwords()))
        print "Writing passwords to keychain.csv"
        write_file("keychain.csv", "Passwords;;\n"+passwords+"\nInternet passwords;;\n"+ inetpasswords)

    def save_certs_keys(self):
        certs, pkeys = self.get_certs()
        for c in certs:
            filename = c + ".crt"
            print "Saving certificate %s" % filename
            certs[c].save_pem(filename)
        for k in pkeys:
            filename = k + ".key"
            print "Saving key %s" % filename
            write_file(filename, pkeys[k])

    def sanitize(self, pw):
        if pw.startswith("bplist"):
            return "<binary plist data>"
        elif not set(pw).issubset(printset):
            pw = "<binary data> : " + pw.encode("hex")
        if self.bsanitize:
            return pw[:2] + ("*" * (len(pw) - 2))
        return pw

    def print_all(self, sanitize=True):
        self.bsanitize = sanitize
        print "-"*60
        print " " * 20 + "Passwords"
        print "-"*60

        for p in self.get_passwords():
            print "Service :\t" + p["svce"]
            print "Account :\t" + str(p["acct"])
            print "Password :\t" + self.sanitize(p["data"])
            print "Agrp :\t" + p["agrp"]
            print "-"*60

        for p in self.get_inet_passwords():
            print "Server : \t" + p["srvr"] + ":" + str(p["port"])
            print "Account : \t" + str(p["acct"])
            print "Password : \t" + self.sanitize(p["data"])
            print "-"*60

        certs, pkeys = self.get_certs()

        print " " * 20 + "Certificates"
        print "-"*60
        for c in sorted(certs.keys()):
            print c

        print "-"*60
        print " " * 20 + "Private keys"

        for k in sorted(pkeys.keys()):
            print k
        print "-"*60

    def get_push_token(self):
        for p in self.get_passwords():
            if p["svce"] == "push.apple.com":
                return p["data"]
    
    def get_managed_configuration(self):
        for p in self.get_passwords():
            if p["acct"] == "Private" and p["svce"] == "com.apple.managedconfiguration" and p["agrp"] == "apple":
                return BPlistReader.plistWithString(p["data"])
    
    def _diff(self, older, res, func, key):
        res.setdefault(key, []) 
        current = func(self)  
        for p in func(older):
            if not p in current and not p in res[key]:
                res[key].append(p)

    def diff(self, older, res):
        self._diff(older, res, Keychain.get_passwords, "genp")
        self._diff(older, res, Keychain.get_inet_passwords, "inet")
        self._diff(older, res, Keychain.get_cert, "cert")
        self._diff(older, res, Keychain.get_keys, "keys")