def write_KAP(kap, kap_file, do_encrypt = True, teambox_email_skey = None, encrypt_pkey = None): workdir = Workdir() workdir_sig = Workdir() if do_encrypt and (not teambox_email_skey or not encrypt_pkey): raise KAPException("Encryption demanded but no key used.") try: # Copy the generated key files in $workdir/kap os.mkdir(os.path.join(workdir.path(), "kap")) os.mkdir(os.path.join(workdir.path(), "kap", "keys")) # Build the KAP. if kap.email_sig_pkey: kap.email_sig_pkey.save(os.path.join(workdir.path(), "kap", "keys", "email.sig.pkey")) if kap.email_sig_skey: kap.email_sig_skey.save(os.path.join(workdir.path(), "kap", "keys", "email.sig.skey")) if kap.email_enc_pkey: kap.email_enc_pkey.save(os.path.join(workdir.path(), "kap", "keys", "email.enc.pkey")) if kap.bundle: bundle_path = os.path.join(workdir.path(), "kap", "kps.bundle") write_file(bundle_path, kap.bundle) if kap.kdn: kdn_path = os.path.join(workdir.path(), "kap", "kdn") write_file(kdn_path, kap.kdn) if kap.key_id: key_id_path = os.path.join(workdir.path(), "kap", "keyid") write_file(key_id_path, str(kap.key_id)) if kap.license: license_file_path = os.path.join(workdir.path(), "kap", "lic") write_file(license_file_path, kap.license) workdir.tar(os.path.join(workdir_sig.path(), "kap.tar.gz"), compressed = True) # Encrypt the KAP. kap_zip = os.path.join(workdir_sig.path(), "kap.tar.gz") if do_encrypt: encrypt = Popen(args = ["kpsinstalltool", "sign_encrypt", teambox_email_skey, encrypt_pkey, kap_zip, kap_file], shell = False, stdout = PIPE, stderr = PIPE) (_, err_text) = encrypt.communicate() encrypt.wait() if encrypt.returncode != 0: raise KAPException("kpsinstalltool error: %s" % err_text) else: shutil.copyfile(kap_zip, kap_file) finally: workdir_sig.close() workdir.close()
def read_KAP(kap_file, teambox_email_pkey = None, encrypt_skey = None): workdir = Workdir() try: kap = KAPData() # Check if this is an encrypted file. is_true_KAP = False kap_header_check = None try: kap_header_check = open(kap_file, "r") kap_header = kap_header_check.read(39) if kap_header == "--- Encrypted chunk for KPS version 1.0": is_true_KAP = True finally: kap_header_check.close() # Decrypt the KAP. if is_true_KAP: decrypt = Popen(args = ["kpsinstalltool", "decrypt_verify", teambox_email_pkey, encrypt_skey, kap_file, os.path.join(workdir.path(), "kap.tar.gz")], shell = False, stdout = PIPE, stderr = PIPE) (_, err_text) = decrypt.communicate() decrypt.wait() if decrypt.returncode != 0: raise KAPException("kpsinstalltool error: %s" % err_text) else: shutil.copyfile(kap_file, os.path.join(workdir.path(), "kap.tar.gz")) # Uncompress the KAP. if not os.path.exists(os.path.join(workdir.path(), "kap.tar.gz")): raise KAPException("Extracted KAP file does not exists.") t = tarfile.open(os.path.join(workdir.path(), "kap.tar.gz")) t.extractall(workdir.path()) # Extract the KAP's content. fn = os.path.join(workdir.path(), "kap", "keys", "email.sig.pkey") if os.path.exists(fn): kap.email_sig_pkey = Key.fromBuffer(read_file(fn)) fn = os.path.join(workdir.path(), "kap", "keys", "email.sig.skey") if os.path.exists(fn): kap.email_sig_skey = Key.fromBuffer(read_file(fn)) fn = os.path.join(workdir.path(), "kap", "keys", "email.enc.pkey") if os.path.exists(fn): kap.email_enc_pkey = Key.fromBuffer(read_file(fn)) fn = os.path.join(workdir.path(), "kap", "kps.bundle") if os.path.exists(fn): kap.bundle = read_file(fn) fn = os.path.join(workdir.path(), "kap", "kdn") if os.path.exists(fn): kap.kdn = read_file(fn).strip() fn = os.path.join(workdir.path(), "kap", "keyid") if os.path.exists(fn): kap.key_id = int(read_file(fn).strip()) fn = os.path.join(workdir.path(), "kap", "lic") if os.path.exists(fn): kap.license = read_file(fn) finally: workdir.close() return kap
def read_KAR(teambox_ssl_key, teambox_ssl_cert, kar_file): workdir = Workdir() try: # Decrypt the file. s = SMIME.SMIME() s.set_cipher(SMIME.Cipher('aes_256_cbc')) s.load_key(teambox_ssl_key.as_path(), teambox_ssl_cert.as_path()) pkcs7 = SMIME.load_pkcs7(kar_file) data = s.decrypt(pkcs7) data = write_file(os.path.join(workdir.path(), "signed_kar.tar"), data) kar_tar_file = tarfile.TarFile(os.path.join(workdir.path(), "signed_kar.tar"), "r") # Verify the sanity of KAR level 2 file members. m_tar = tar_getfirstmember(kar_tar_file, ["kar.tar.gz", "./kar.tar.gz"]) if not m_tar: raise KARException("KAR is missing 'kar.tar.gz'.") if not m_tar.isfile() and not m_tar.isdir(): raise KARException("%s is not a regular file or a directory." % (m.name)) m_sig = tar_getfirstmember(kar_tar_file, ["kar_sig", "./kar_sig"]) if not m_sig: raise KARException("KAR is missing 'kar_sig'.") if not m_sig.isfile() and not m_sig.isdir(): raise KARException("%s is not a regular file or a directory." % (m.name)) # Extract the KAR level 2 file members. tar_list = kar_tar_file.getmembers() for i in tar_list: if not i.isfile() and not i.isdir(): raise KARException("%s is not a regular file or directory." % (m.name)) kar_tar_file.extract(i, workdir.path()) # Calculate the hash of the data file to validate the KAR # signature. kar_hasher = hashlib.sha256() kar_hasher.update(kar_tar_file.extractfile(m_tar).read()) write_file(os.path.join(workdir.path(), "kar_hash"), kar_hasher.hexdigest() + "\n") # Extract the KAR data file. tf = tarfile.TarFile(mode = "r", fileobj = gzip.GzipFile(os.path.join(workdir.path(), "kar.tar.gz"), "r")) tf.extractall(path = os.path.join(workdir.path())) # Verify the KAR signature. signverify = Popen(args = ["sslsigntool", "verify", "kar/cert.pem", "kar_hash", "kar_sig"], stdout = PIPE, stderr = PIPE, cwd = workdir.path()) (out_text, err_text) = signverify.communicate() if signverify.returncode != 0: raise KARException("sslsigntool exception: %s" % err_text.strip()); # Extract some informations from the signing certificate. kar = KARData() fn = os.path.join(workdir.path(), "kar", "cert.pem") if os.path.exists(fn): kar.cert = ssl.Cert(cert_data = read_file(fn)) # Read level 1 KAR data fn = os.path.join(workdir.path(), "kar", "product_name") if os.path.exists(fn): kar.product_name = read_file(fn).strip() fn = os.path.join(workdir.path(), "kar", "product_version") if os.path.exists(fn): kar.product_version = read_file(fn).strip() fn = os.path.join(workdir.path(), "kar", "info") if os.path.exists(fn): kar.info = read_file(fn) fn = os.path.join(workdir.path(), "kar", "parent_kdn") if os.path.exists(fn): kar.parent_kdn = read_file(fn).strip() fn = os.path.join(workdir.path(), "kar", "admin") if os.path.exists(fn): kar.admin = read_file(fn).strip() fn = os.path.join(workdir.path(), "kar", "kar.enc.pkey") if os.path.exists(fn): kar.enc_pkey = Key.fromFile(fn) fn = os.path.join(workdir.path(), "kar", "info") if os.path.exists(fn): kar.info = read_file(fn) finally: # Remove the temporaries workdir.close() # Return the KAR data. return kar
def write_KAR(kar, kar_file, teambox_ssl_cert, client_ssl_cert, client_ssl_key): workdir = Workdir() workdir_sig = Workdir() try: # Make sure we have everything that is mandatory in the KAR. for i in ['cert', 'enc_pkey', 'product_name', 'product_version', 'info', 'admin']: if not kar.__dict__.has_key(i): raise KARException("Value for %s field missing from KAR." % i) # Add the level 1 KAR data. os.mkdir(os.path.join(workdir.path(), "kar")) fn = os.path.join(workdir.path(), "kar", "cert.pem") kar.cert.save(fn) fn = os.path.join(workdir.path(), "kar", "kar.enc.pkey") kar.enc_pkey.save(fn) fn = os.path.join(workdir.path(), "kar", "product_name") write_file(fn, kar.product_name) fn = os.path.join(workdir.path(), "kar", "product_version") write_file(fn, kar.product_version) fn = os.path.join(workdir.path(), "kar", "info") write_file(fn, kar.info) fn = os.path.join(workdir.path(), "kar", "admin") write_file(fn, kar.admin) if kar.parent_kdn: fn = os.path.join(workdir.path(), "kar", "parent_kdn") write_file(fn, kar.parent_kdn) # Zip the level 1 KAR. workdir.tar(os.path.join(workdir.path(), "kar.tar.gz"), compressed = True) # Create the KAR file level 2 files. shutil.copy(os.path.join(workdir.path(), "kar.tar.gz"), workdir_sig.path()) # Sign the KAR level 2. kar_hasher = hashlib.sha256() kar_hasher.update(read_file(os.path.join(workdir_sig.path(), "kar.tar.gz"))) hash_path = os.path.join(workdir_sig.path(), "kar_hash") sig_path = os.path.join(workdir_sig.path(), "kar_sig") write_file(hash_path, kar_hasher.hexdigest() + "\n") sslsign = Popen(args = ["sslsigntool", "sign", client_ssl_cert.as_path(), client_ssl_key.as_path(), hash_path, sig_path], stdout = PIPE, stderr = PIPE, cwd = workdir_sig.path()) (out_text, err_text) = sslsign.communicate() if sslsign.returncode != 0: raise KARException("sslsigntool exception: %s" % err_text.strip()) os.unlink(hash_path) workdir_sig.tar(os.path.join(workdir_sig.path(), "signed_kar.tar")) # Encrypt the KAR level 2. inf = BIO.openfile(os.path.join(workdir_sig.path(), "signed_kar.tar"), "r") outf = BIO.openfile(kar_file, "w") xs = X509.X509_Stack() xs.push(teambox_ssl_cert.as_cert()) s = SMIME.SMIME() s.set_cipher(SMIME.Cipher('aes_256_cbc')) s.set_x509_stack(xs) s.load_key(client_ssl_key.as_path(), certfile = teambox_ssl_cert.as_path()) pkcs7 = s.encrypt(inf, flags = SMIME.PKCS7_BINARY) pkcs7.write(outf) finally: # Remove the temporaries. workdir.close() workdir_sig.close()