Esempio n. 1
0
def bin2str(token_bplist, account_bplist=None):
    # Convert the decrypted binary plist to an NSData object that can be read.
    bin_list = NSData.dataWithBytes_length_(token_bplist, len(token_bplist))

    # Convert the binary NSData object into a dictionary object.
    token_plist = NSPropertyListSerialization.propertyListWithData_options_format_error_(
        bin_list, 0, None, None)[0]

    # Accounts DB cache
    if "$objects" in token_plist:
        # Because it is accounts db cache, we should also have been passed
        # account_bplist.
        bin_list = NSData.dataWithBytes_length_(account_bplist,
                                                len(account_bplist))
        dsid_plist = NSPropertyListSerialization.propertyListWithData_options_format_error_(
            bin_list, 0, None, None)[0]

        for obj in dsid_plist["$objects"]:
            if "{}".format(obj).startswith("urn:ds:"):
                dsid = obj.replace("urn:ds:", "")

        token_dict = {"dsid": dsid}

        # Do some parsing to get the data out because it is not stored
        # in a format that is easy to process with stdlibs
        token_l = [
            x.strip().replace(",", "")
            for x in "{}".format(token_plist["$objects"]).splitlines()
        ]

        pos_start = token_l.index("mmeBTMMInfiniteToken")
        pos_end = (token_l.index("cloudKitToken") - pos_start + 1) * 2

        token_short = token_l[pos_start:pos_start + pos_end]
        zipped = zip(token_short[:len(token_short) / 2],
                     token_short[len(token_short) / 2:])

        for token_type, token_value in zipped:
            # Attempt to get generation time
            # this parsing is a little hacky, but it seems to be the best way
            # to handle all different kinds of iCloud tokens (new and old)
            gen_time = get_generation_time(token_value)

            token_dict[token_type] = (token_value, gen_time)

        return token_dict

    else:
        return token_plist
Esempio n. 2
0
 def writeBytes_(self, data):
     # NSLog(u'Writing bytes: %s', data)
     try:
         self.remoteFileHandle.writeData_(
             NSData.dataWithBytes_length_(data, len(data)))
     except objc.error:
         self.close()
Esempio n. 3
0
 def value(self, data):
     if not self.properties["write"]:
         return
     # data needs to be byte array
     if not isinstance(data, bytearray):
         raise TypeError("data needs to be a bytearray")
     rawdata = NSData.dataWithBytes_length_(data, len(data))
     self.service.peripheral.writeValueForCharacteristic(rawdata, self.instance)
Esempio n. 4
0
def nsdata(obj):
    """Convert ``object`` to `NSData`."""
    if isinstance(obj, unicode):
        s = obj.encode('utf-8')
    else:
        s = str(obj)

    return NSData.dataWithBytes_length_(s, len(s))
Esempio n. 5
0
def nsdata(obj):
    """Convert ``object`` to `NSData`."""
    if isinstance(obj, unicode):
        s = obj.encode('utf-8')
    else:
        s = str(obj)

    return NSData.dataWithBytes_length_(s, len(s))
Esempio n. 6
0
def nsdata(s):
    """Return an NSData instance for string `s`."""
    if isinstance(s, unicode):
        s = s.encode('utf-8')
    else:
        s = str(s)

    return NSData.dataWithBytes_length_(s, len(s))
Esempio n. 7
0
 def value_async_nr(self, data):
     if not self.properties["write"]:
         return
     # data needs to be byte array
     if not isinstance(data, bytearray) and not isinstance(data, bytes):
         raise TypeError("data needs to be a bytearray or bytes")
     rawdata = NSData.dataWithBytes_length_(data, len(data))
     self.service.peripheral.writeValueForCharacteristicAsync(
         rawdata, self.instance, withResponse=False)
def decode_bdisk(key):
    """Return the relative path of file referenced by key """
    decodedBytes = base64.b64decode(key)
    nsData = NSData.dataWithBytes_length_(decodedBytes, len(decodedBytes))
    plist, fmt, error = NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_(
        nsData, 0, None, None)
    if plist is None:
        return "Missed"
    else:
        return plist['relativePath']
Esempio n. 9
0
def __ns_data_from_array(a):
    
    from Foundation import NSData
    
    a = np.asarray(a).flatten()
    if a.dtype == np.uint8 or a.dtype == np.int8:
        datasize = 1
    elif a.dtype == np.uint16 or a.dtype == np.int16:
        datasize = 2
    elif a.dtype == np.float32:
        datasize = 4
    else:
        assert 0, "unhandled data type %s" % (a.dtype)
        
    buf = buffer(a)
    
    return datasize, NSData.dataWithBytes_length_(buf, len(buf) * datasize)
Esempio n. 10
0
 def getStoredHeaders(self):
     '''Returns any stored headers for self.destination_path'''
     # try to read stored headers
     try:
         stored_plist_bytestr = xattr.getxattr(self.destination_path,
                                               self.GURL_XATTR)
     except (KeyError, IOError):
         return {}
     data = NSData.dataWithBytes_length_(stored_plist_bytestr,
                                         len(stored_plist_bytestr))
     dataObject, _plistFormat, error = (
         NSPropertyListSerialization.
         propertyListFromData_mutabilityOption_format_errorDescription_(
             data, NSPropertyListMutableContainersAndLeaves, None, None))
     if error:
         return {}
     return dataObject
def readPlistFromString(data):
    '''Read a plist data from a (byte)string. Return the root object.'''
    plistData = NSData.dataWithBytes_length_(data, len(data))
    if not plistData:
        raise NSPropertyListSerializationException(
            "Could not convert string to NSData")
    dataObject, dummy_plistFormat, error = (
        NSPropertyListSerialization.
        propertyListFromData_mutabilityOption_format_errorDescription_(
            plistData, NSPropertyListMutableContainers, None, None))
    if dataObject is None:
        if error:
            error = error.encode('ascii', 'ignore')
        else:
            error = "Unknown error"
        raise NSPropertyListSerializationException(error)
    else:
        return dataObject
Esempio n. 12
0
    def start(self):
        '''Start the connection'''
        if not self.destination_path:
            self.log('No output file specified.')
            self.done = True
            return
        url = NSURL.URLWithString_(self.url)
        request = (
            NSMutableURLRequest.requestWithURL_cachePolicy_timeoutInterval_(
                url, NSURLRequestReloadIgnoringLocalCacheData,
                self.connection_timeout))
        if self.post_data:
            request.setHTTPMethod_('POST')
            data_unicode = unicode(self.post_data)
            data = NSData.dataWithBytes_length_(
                NSString.stringWithString_(data_unicode).UTF8String(),
                len(data_unicode.encode('utf-8')))
            request.setHTTPBody_(data)

        if self.additional_headers:
            for header, value in self.additional_headers.items():
                request.setValue_forHTTPHeaderField_(value, header)
        # does the file already exist? See if we can resume a partial download
        if os.path.isfile(self.destination_path):
            stored_data = self.get_stored_headers()
            if (self.can_resume and 'expected-length' in stored_data and
                ('last-modified' in stored_data or 'etag' in stored_data)):
                # we have a partial file and we're allowed to resume
                self.resume = True
                local_filesize = os.path.getsize(self.destination_path)
                byte_range = 'bytes=%s-' % local_filesize
                request.setValue_forHTTPHeaderField_(byte_range, 'Range')
        if self.download_only_if_changed and not self.resume:
            stored_data = self.cache_data or self.get_stored_headers()
            if 'last-modified' in stored_data:
                request.setValue_forHTTPHeaderField_(
                    stored_data['last-modified'], 'if-modified-since')
            if 'etag' in stored_data:
                request.setValue_forHTTPHeaderField_(stored_data['etag'],
                                                     'if-none-match')

        self.connection = NSURLConnection.alloc().initWithRequest_delegate_(
            request, self)
Esempio n. 13
0
    def start(self):
        '''Start the connection'''
        if not self.destination_path:
            self.log('No output file specified.')
            self.done = True
            return
        url = NSURL.URLWithString_(self.url)
        request = (
            NSMutableURLRequest.requestWithURL_cachePolicy_timeoutInterval_(
                url, NSURLRequestReloadIgnoringLocalCacheData,
                self.connection_timeout))
        if self.post_data:
            request.setHTTPMethod_('POST')
            data_unicode = unicode(self.post_data)
            data = NSData.dataWithBytes_length_(NSString.stringWithString_(data_unicode).UTF8String(), len(data_unicode.encode('utf-8')))
            request.setHTTPBody_(data)

        if self.additional_headers:
            for header, value in self.additional_headers.items():
                request.setValue_forHTTPHeaderField_(value, header)
        # does the file already exist? See if we can resume a partial download
        if os.path.isfile(self.destination_path):
            stored_data = self.get_stored_headers()
            if (self.can_resume and 'expected-length' in stored_data and
                    ('last-modified' in stored_data or 'etag' in stored_data)):
                # we have a partial file and we're allowed to resume
                self.resume = True
                local_filesize = os.path.getsize(self.destination_path)
                byte_range = 'bytes=%s-' % local_filesize
                request.setValue_forHTTPHeaderField_(byte_range, 'Range')
        if self.download_only_if_changed and not self.resume:
            stored_data = self.cache_data or self.get_stored_headers()
            if 'last-modified' in stored_data:
                request.setValue_forHTTPHeaderField_(
                    stored_data['last-modified'], 'if-modified-since')
            if 'etag' in stored_data:
                request.setValue_forHTTPHeaderField_(
                    stored_data['etag'], 'if-none-match')

        self.connection = NSURLConnection.alloc().initWithRequest_delegate_(
            request, self)
Esempio n. 14
0
    def start(self):
        """Start the connection."""
        url = NSURL.URLWithString_(self.url)
        request = NSMutableURLRequest.requestWithURL_cachePolicy_timeoutInterval_(
            url, NSURLRequestReloadIgnoringLocalCacheData,
            self.connection_timeout)
        if self.additional_headers:
            for header, value in self.additional_headers.items():
                request.setValue_forHTTPHeaderField_(value, header)
        request.setHTTPMethod_(self.method)

        if self.method == "POST":
            body_unicode = unicode(self.body)
            body_data = NSData.dataWithBytes_length_(
                NSString.stringWithString_(body_unicode).UTF8String(),
                len(body_unicode.encode("utf-8")),
            )
            request.setHTTPBody_(body_data)

        self.connection = NSURLConnection.alloc().initWithRequest_delegate_(
            request, self)
Esempio n. 15
0
def unplist(s):
    from Foundation import NSData, NSPropertyListSerialization
    d = NSData.dataWithBytes_length_(s, len(s))
    return NSPropertyListSerialization.propertyListWithData_options_format_error_(
        d, 0, None, None)
Esempio n. 16
0
        sys.exit()

    msg = base64.b64decode(icloud_key)
    key = "t9s\"lx^awe.580Gj%'ld+0LG<#9xa?>vb)-fkwb92[}"  # Constant key used for hashing Hmac on all versions of macOS.

    # Create Hmac with this key and icloud_key using MD5
    hashed = hmac.new(key, msg, digestmod=hashlib.md5).digest()
    hexed_key = binascii.hexlify(hashed)  # Turn into hex for openssl subprocess
    IV = 16 * '0'
    mme_token_file = glob.glob("%s/Library/Application Support/iCloud/Accounts/*" % os.path.expanduser("~"))

    for x in mme_token_file:
        try:
            int(x.split("/")[-1])  # If we can cast to int we have the DSID / account file.
            mme_token_file = x
        except ValueError:
            continue
    if not isinstance(mme_token_file, str):
        print "Failed to find MMeTokenFile."
        sys.exit()

    # Perform decryption with zero dependencies by using openssl binary
    decrypted_binary = subprocess.check_output(
        "openssl enc -d -aes-128-cbc -iv '%s' -K %s < '%s'" % (IV, hexed_key, mme_token_file), shell=True)
    # Convert the decrypted binary plist to an NSData object that can be read
    bin_to_plist = NSData.dataWithBytes_length_(decrypted_binary, len(decrypted_binary))
    # Convert the binary NSData object into a dictionary object
    token_plist = NSPropertyListSerialization.propertyListWithData_options_format_error_(bin_to_plist, 0, None, None)[0]

    print_tokens_json(token_plist)
Esempio n. 17
0
def get_input():
    try:        
        while True:
            line = sys.stdin.readline()
            if not line:
                break

            if line == '':
                continue

            print "info:Read %s" % line
            sys.stdout.flush()
            cfg = None
            try:
                cfg = json.loads(line)
            except:
                pass

            if cfg == None:
                print "info:Unable to parse line"
                sys.stdout.flush()
                continue

            if cfg.has_key("Action"):
                print "info:Running %s" % cfg["Action"]
                sys.stdout.flush()

                if cfg["Action"] == "setmenu":
                    menu = cfg["Menu"]

                    if lookup.has_key(menu["Key"]):
                        lookup[menu["Key"]].title = menu["Text"]

                        if menu.has_key("Enabled") and not menu["Enabled"]:
                            lookup[menu["Key"]].set_callback(None)
                        else:
                            lookup[menu["Key"]].set_callback(item_clicked)
                        app.menu.update([])
                    else:
                        print "warn:Key not found %s" % cfg["Action"]
                        sys.stdout.flush()



                elif cfg["Action"] == "setmenus":
                    app.menu.clear()
                    app.menu = parsemenus(cfg)
                    print "info:Updated menus"
                    sys.stdout.flush()
                elif cfg["Action"] == "seticon":

                    try:
                        raw = base64.b64decode(cfg["Image"])
                        data = NSData.dataWithBytes_length_(raw, len(raw))
                        img = NSImage.alloc().initWithData_(data)    
                        img.setScalesWhenResized_(True)
                        img.setSize_((18, 18))
                        img.setTemplate_(True)
                        app.icon = img

                        print "info:Image updated"
                        sys.stdout.flush()

                    except:
                        print "warn:Failed to set image"
                        sys.stdout.flush()

                elif cfg["Action"] == "setappicon":

                    try:
                        raw = base64.b64decode(cfg["Image"])
                        data = NSData.dataWithBytes_length_(raw, len(raw))
                        img = NSImage.alloc().initWithData_(data)    
                        #img.setScalesWhenResized_(True)
                        #img.setSize_((21, 21))
                        NSApplication.sharedApplication().setApplicationIconImage_(img)

                        print "info:AppImage updated"
                        sys.stdout.flush()

                    except:
                        print "warn:Failed to set image"
                        sys.stdout.flush()

                elif cfg["Action"] == "shutdown":
                    break

                elif cfg["Action"] == "foreground":
                    transform_app_type(True)
                elif cfg["Action"] == "background":
                    transform_app_type(False)

                elif cfg["Action"] == "notification":
                    if rumps._NOTIFICATIONS:
                        title = cfg["Title"]
                        message = cfg["Message"]
                        subtitle = ''
                        playSound = True
                        image = None

                        if cfg.has_key("SubTitle"):
                            subtitle = cfg["SubTitle"]

                        if cfg.has_key("PlaySound"):
                            playSound = cfg["PlaySound"]
                        if cfg.has_key("Image"):
                            try:
                                raw = base64.b64decode(cfg["Image"])
                                data = NSData.dataWithBytes_length_(raw, len(raw))
                                image = NSImage.alloc().initWithData_(data)
                            except:
                                print "warn:Failed to decode image"
                                sys.stdout.flush()

                        rumps.notification(cfg["Title"], subtitle, cfg["Message"], sound=playSound, image=image)

    finally:
        try:
            traceback.print_exc()
        except:
            pass

        rumps.quit_application()     
        print "info:Shutdown"
        sys.stdout.flush()

    print "info:Stdin close"
    sys.stdout.flush()
    sys.stdin.close()
Esempio n. 18
0
def main():
    parser = argparse.ArgumentParser(
        description=
        'Sign or encrypt mobileconfig profiles, using either a cert + key file, or a keychain certificate.'
    )
    parser.add_argument(
        'sign',
        choices=('sign', 'encrypt', 'both'),
        help='Choose to sign, encrypt, or do both on a profile.')
    key_group = parser.add_argument_group(
        'Keychain arguments',
        description='Use these if you wish to sign with a Keychain certificate.'
    )
    key_group.add_argument(
        '-k',
        '--keychain',
        help='Name of keychain to search for cert. Defaults to login.keychain',
        default='login.keychain')
    key_group.add_argument(
        '-n',
        '--name',
        help='Common name of certificate to use from keychain.',
        required=True)
    parser.add_argument('infile', help='Path to input .mobileconfig file')
    parser.add_argument(
        'outfile',
        help=
        'Path to output .mobileconfig file. Defaults to outputting into the same directory.'
    )
    args = parser.parse_args()
    print "f**k yeah"

    if args.sign == 'encrypt' or args.sign == 'both':
        # encrypt the profile only, do not sign
        # Encrypting a profile:
        # 1. Extract payload content into its own file
        # 2. Serial that file as its own plist
        # 3. CMS-envelope that content (using openssl for now)
        # 4. Remove "PayloadContent" key and replace with "EncryptedPayloadContent" key
        # 5. Replace the PayloadContent <array> with <data> tags instead

        # Step 1: Extract payload content into its own file
        myProfile = plistlib.readPlist(args.infile)
        payloadContent = myProfile['PayloadContent']

        # Step 2: Serialize that file into its own plist
        (pContentFile, pContentPath) = tempfile.mkstemp()
        plistlib.writePlist(payloadContent, pContentPath)

        # Step 3: Use openssl to encrypt that content
        # First, we need to extract the certificate we want to use from the keychain
        security_cmd = [
            '/usr/bin/security', 'find-certificate', '-c', args.name, '-p'
        ]
        if args.keychain:
            security_cmd += [args.keychain]
        print security_cmd
        proc = subprocess.Popen(security_cmd,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        (sout, serr) = proc.communicate()
        if serr:
            print >> sys.stderr, "Error: %s" % serr
            sys.exit(1)
        # Now write the certificate to a temp file
        (certfile, certpath) = tempfile.mkstemp('.pem')
        try:
            with open(certpath, 'wb') as f:
                f.write(sout)
        except IOError:
            print >> sys.stderr, "Could not write to file!"
            sys.exit(1)
        # Now use openssl to encrypt the payload content using that certificate
        (encPContentfile, encPContentPath) = tempfile.mkstemp('.plist')
        enc_cmd = [
            '/usr/bin/openssl', 'smime', '-encrypt', '-aes256', '-outform',
            'pem', '-in', pContentPath, '-out', encPContentPath
        ]
        enc_cmd += [certpath]
        proc = subprocess.Popen(enc_cmd,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        (encout, encerr) = proc.communicate()
        if encerr:
            print >> sys.stderr, "Error: %s" % encerr
            sys.exit(1)
        # openssl smime -encrypt produces no output if successful

        # Step 4: Add the new encrypted payload content back into the plist
        with open(encPContentPath, 'rb') as f:
            content = f.readlines()
            content = content[
                1:
                -1]  #this is to skip the ---BEGIN PKCS7--- and ----END PKCS7---- lines
        encPayload = ""
        for line in content:
            encPayload += ''.join(
                line.rstrip())  # to get rid of Python's \n everywhere
        del myProfile['PayloadContent']

        binaryEncPayload = base64.b64decode(encPayload)
        wrapped_data = NSData.dataWithBytes_length_(binaryEncPayload,
                                                    len(binaryEncPayload))
        myProfile['EncryptedPayloadContent'] = wrapped_data
        plistData, error = NSPropertyListSerialization.dataFromPropertyList_format_errorDescription_(
            myProfile, NSPropertyListXMLFormat_v1_0, None)
        plistData.writeToFile_atomically_(args.outfile, True)

        # Step 5: Use plistlib.Data to properly encode the content
        # myProfile['EncryptedPayloadContent'] = plistlib.Data(encPayload)
        # now save the profile
        # plistlib.writePlist(myProfile, args.outfile)

        # Now clean up after ourselves

    if args.sign == 'sign' or args.sign == 'both':
        # sign the profile only
        # Keychain check:
        if not args.name:
            print >> sys.stderr, 'Error: A certificate common name is required to sign profiles with the Keychain.'
            sys.exit(22)
        cmd = [
            '/usr/bin/security', 'cms', '-S', '-N', args.name, '-i',
            args.infile, '-o', args.outfile
        ]
        proc = subprocess.Popen(cmd,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        (sout, serr) = proc.communicate()
        if serr:
            print >> sys.stderr, 'Error: %s' % serr
            sys.exit(1)
Esempio n. 19
0
paperpath = os.path.join(os.environ['HOME'], 'Documents', 'Papers')

with open(mainfile) as f:
    bib = f.read()

aliases = re.findall(r"Bdsk-File-\d = {(\S*)}", bib)

files = []
for a in aliases:
    tmp = base64.b64decode(a.encode())
    files.append(
        os.path.join(
            paperpath,
            re.search(b"Documents/Papers/(.+?)(?=\x00)",
                      tmp).groups()[0].decode()))

diskfiles = glob.glob(os.path.join(paperpath, '*.*'))

set(files) - set(diskfiles)

missing = list(set(diskfiles) - set(files))
np.sort(missing)

#for when pyobjc is fixed:
from Foundation import NSPropertyListSerialization, NSData
decodedBytes = base64.b64decode(a)
nsData = NSData.dataWithBytes_length_(decodedBytes, len(decodedBytes))
plist, fmt, error = NSPropertyListSerialization\
    .propertyListFromData_mutabilityOption_format_errorDescription_(
        nsData, 0, None, None)
Esempio n. 20
0
def main():
    parser = argparse.ArgumentParser(description='Sign or encrypt mobileconfig profiles, using either a cert + key file, or a keychain certificate.')
    parser.add_argument('sign', choices=('sign', 'encrypt', 'both'), help='Choose to sign, encrypt, or do both on a profile.')
    key_group = parser.add_argument_group('Keychain arguments', description='Use these if you wish to sign with a Keychain certificate.')
    key_group.add_argument('-k', '--keychain', help='Name of keychain to search for cert. Defaults to login.keychain',
                        default='login.keychain')
    key_group.add_argument('-n', '--name', help='Common name of certificate to use from keychain.', required=True)
    parser.add_argument('infile', help='Path to input .mobileconfig file')
    parser.add_argument('outfile', help='Path to output .mobileconfig file. Defaults to outputting into the same directory.')
    args = parser.parse_args()
    
    if args.sign == 'encrypt' or args.sign == 'both':
        if args.sign == 'both':
            outputFile = args.outfile + '_unsigned'
        else:
            outputFile = args.outfile
        # encrypt the profile only, do not sign
        # Encrypting a profile:
        # 1. Extract payload content into its own file
        # 2. Serial that file as its own plist
        # 3. CMS-envelope that content (using openssl for now)
        # 4. Remove "PayloadContent" key and replace with "EncryptedPayloadContent" key
        # 5. Replace the PayloadContent <array> with <data> tags instead

        # Step 1: Extract payload content into its own file
        myProfile = readPlist(args.infile)
        payloadContent = myProfile['PayloadContent']

        # Step 2: Serialize that file into its own plist
        (pContentFile, pContentPath) = tempfile.mkstemp()
        #print "pContentPath: %s" % pContentPath
        writePlist(payloadContent, pContentPath)
        
        # Step 3: Use openssl to encrypt that content
        # First, we need to extract the certificate we want to use from the keychain
        security_cmd = ['/usr/bin/security', 'find-certificate', '-c', args.name, '-p' ]
        if args.keychain:
            security_cmd += [args.keychain]
        proc = subprocess.Popen(security_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (sout, serr) = proc.communicate()
        if serr:
            print >> sys.stderr, "Error: %s" % serr
            sys.exit(1)
        # Now write the certificate to a temp file
        (certfile, certpath) = tempfile.mkstemp('.der')
        #print "Certpath: %s" % certpath
        try:
            with open(certpath, 'wb') as f:
                f.write(sout)
        except IOError:
            print >> sys.stderr, "Could not write to file!"
            sys.exit(1)      
        # Now use openssl to encrypt the payload content using that certificate
        (encPContentfile, encPContentPath) = tempfile.mkstemp('.plist')
        #print "encPContentPath: %s" % encPContentPath
        enc_cmd = ['/usr/bin/openssl', 'smime', '-encrypt', '-aes256', '-outform', 'der', 
                '-in', pContentPath, '-out', encPContentPath]
        enc_cmd += [certpath]
        proc = subprocess.Popen(enc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (encout, encerr) = proc.communicate()
        if encerr:
            print >> sys.stderr, "Error: %s" % encerr
            sys.exit(1)
        # openssl smime -encrypt produces no output if successful
        
        # Step 4: Add the new encrypted payload content back into the plist
        with open(encPContentPath, 'rb') as f:
            binaryEncPayload = f.read()
        del myProfile['PayloadContent']
        wrapped_data = NSData.dataWithBytes_length_(binaryEncPayload, len(binaryEncPayload))
        myProfile['EncryptedPayloadContent'] = wrapped_data

        # Step 5: Replace the plist with the new content
        plistData, error = NSPropertyListSerialization.dataFromPropertyList_format_errorDescription_(myProfile, NSPropertyListXMLFormat_v1_0, None)
        plistData.writeToFile_atomically_(outputFile, True)

        # Now clean up after ourselves
        os.remove(pContentPath)
        os.remove(certpath)
        os.remove(encPContentPath)
    
    if args.sign == 'sign' or args.sign == 'both':
        # Keychain check:
        if not args.name:
            print >> sys.stderr, 'Error: A certificate common name is required to sign profiles with the Keychain.'
            sys.exit(22)
        if args.sign == 'both':
            # If we already encrypted it, then the correct file is already in outputFile
            inputFile = outputFile
        else:
            inputFile = args.infile
        cmd = ['/usr/bin/security', 'cms', '-S', '-N', args.name, '-i', inputFile, '-o', args.outfile ]
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (sout, serr) = proc.communicate()
        if serr:
            print >> sys.stderr, 'Error: %s' % serr
            sys.exit(1)
        if args.sign == 'both':
            os.remove(outputFile)
Esempio n. 21
0
def unplist(s):
    from Foundation import NSData, NSPropertyListSerialization
    d = NSData.dataWithBytes_length_(s, len(s))
    return NSPropertyListSerialization.propertyListWithData_options_format_error_(d, 0, None, None)
Esempio n. 22
0
def main():
    parser = argparse.ArgumentParser(description='Sign or encrypt mobileconfig profiles, using either a cert + key file, or a keychain certificate.')
    parser.add_argument('sign', choices=('sign', 'encrypt', 'both'), help='Choose to sign, encrypt, or do both on a profile.')
    key_group = parser.add_argument_group('Keychain arguments', description='Use these if you wish to sign with a Keychain certificate.')
    key_group.add_argument('-k', '--keychain', help='Name of keychain to search for cert. Defaults to login.keychain',
                        default='login.keychain')
    key_group.add_argument('-n', '--name', help='Common name of certificate to use from keychain.', required=True)
    parser.add_argument('infile', help='Path to input .mobileconfig file')
    parser.add_argument('outfile', help='Path to output .mobileconfig file. Defaults to outputting into the same directory.')
    args = parser.parse_args()
    print "f**k yeah"
    
    if args.sign == 'encrypt' or args.sign == 'both':
        # encrypt the profile only, do not sign
        # Encrypting a profile:
        # 1. Extract payload content into its own file
        # 2. Serial that file as its own plist
        # 3. CMS-envelope that content (using openssl for now)
        # 4. Remove "PayloadContent" key and replace with "EncryptedPayloadContent" key
        # 5. Replace the PayloadContent <array> with <data> tags instead

        # Step 1: Extract payload content into its own file
        myProfile = plistlib.readPlist(args.infile)
        payloadContent = myProfile['PayloadContent']

        # Step 2: Serialize that file into its own plist
        (pContentFile, pContentPath) = tempfile.mkstemp()
        plistlib.writePlist(payloadContent, pContentPath)
        
        # Step 3: Use openssl to encrypt that content
        # First, we need to extract the certificate we want to use from the keychain
        security_cmd = ['/usr/bin/security', 'find-certificate', '-c', args.name, '-p' ]
        if args.keychain:
            security_cmd += [args.keychain]
        print security_cmd
        proc = subprocess.Popen(security_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (sout, serr) = proc.communicate()
        if serr:
            print >> sys.stderr, "Error: %s" % serr
            sys.exit(1)
        # Now write the certificate to a temp file
        (certfile, certpath) = tempfile.mkstemp('.pem')
        try:
            with open(certpath, 'wb') as f:
                f.write(sout)
        except IOError:
            print >> sys.stderr, "Could not write to file!"
            sys.exit(1)      
        # Now use openssl to encrypt the payload content using that certificate
        (encPContentfile, encPContentPath) = tempfile.mkstemp('.plist')
        enc_cmd = ['/usr/bin/openssl', 'smime', '-encrypt', '-aes256', '-outform', 'pem', 
                '-in', pContentPath, '-out', encPContentPath]
        enc_cmd += [certpath] 
        proc = subprocess.Popen(enc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (encout, encerr) = proc.communicate()
        if encerr:
            print >> sys.stderr, "Error: %s" % encerr
            sys.exit(1)
        # openssl smime -encrypt produces no output if successful
        
        # Step 4: Add the new encrypted payload content back into the plist
        with open(encPContentPath, 'rb') as f:
            content = f.readlines()
            content = content[1:-1] #this is to skip the ---BEGIN PKCS7--- and ----END PKCS7---- lines
        encPayload = ""
        for line in content:
            encPayload += ''.join(line.rstrip()) # to get rid of Python's \n everywhere
        del myProfile['PayloadContent']

        binaryEncPayload = base64.b64decode(encPayload)
        wrapped_data = NSData.dataWithBytes_length_(binaryEncPayload, len(binaryEncPayload))
        myProfile['EncryptedPayloadContent'] = wrapped_data
        plistData, error = NSPropertyListSerialization.dataFromPropertyList_format_errorDescription_(myProfile, NSPropertyListXMLFormat_v1_0, None)
        plistData.writeToFile_atomically_(args.outfile, True)

        # Step 5: Use plistlib.Data to properly encode the content
        # myProfile['EncryptedPayloadContent'] = plistlib.Data(encPayload)
        # now save the profile
        # plistlib.writePlist(myProfile, args.outfile)

        # Now clean up after ourselves
    
    if args.sign == 'sign' or args.sign == 'both':
        # sign the profile only
        # Keychain check:
        if not args.name:
            print >> sys.stderr, 'Error: A certificate common name is required to sign profiles with the Keychain.'
            sys.exit(22)
        cmd = ['/usr/bin/security', 'cms', '-S', '-N', args.name, '-i', args.infile, '-o', args.outfile ]
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (sout, serr) = proc.communicate()
        if serr:
            print >> sys.stderr, 'Error: %s' % serr
            sys.exit(1)
Esempio n. 23
0
 def set_clipboard(self, data):
     ns_data = NSData.dataWithBytes_length_(data, len(data))
     pb = self._ns_pasteboard
     pb.clearContents()
     pb.setData_forType_(ns_data, NSStringPboardType)
Esempio n. 24
0
def main():
    parser = argparse.ArgumentParser(description='Sign or encrypt mobileconfig profiles, using either a cert + key file, or a keychain certificate.')
    parser.add_argument('sign', choices=('sign', 'encrypt', 'both'), help='Choose to sign, encrypt, or do both on a profile.')
    key_group = parser.add_argument_group('Keychain arguments', description='Use these if you wish to sign with a Keychain certificate.')
    key_group.add_argument('-k', '--keychain', help='Name of keychain to search for cert. Defaults to login.keychain',
                        default='login.keychain')
    key_group.add_argument('-n', '--name', help='Common name of certificate to use from keychain.', required=True)
    parser.add_argument('infile', help='Path to input .mobileconfig file')
    parser.add_argument('outfile', help='Path to output .mobileconfig file. Defaults to outputting into the same directory.')
    args = parser.parse_args()
    
    if args.sign == 'encrypt' or args.sign == 'both':
        if args.sign == 'both':
            outputFile = args.outfile + '_unsigned'
        else:
            outputFile = args.outfile
        # encrypt the profile only, do not sign
        # Encrypting a profile:
        # 1. Extract payload content into its own file
        # 2. Serial that file as its own plist
        # 3. CMS-envelope that content (using openssl for now)
        # 4. Remove "PayloadContent" key and replace with "EncryptedPayloadContent" key
        # 5. Replace the PayloadContent <array> with <data> tags instead

        # Step 1: Extract payload content into its own file
        myProfile = readPlist(args.infile)
        payloadContent = myProfile['PayloadContent']

        # Step 2: Serialize that file into its own plist
        (pContentFile, pContentPath) = tempfile.mkstemp()
        #print "pContentPath: %s" % pContentPath
        writePlist(payloadContent, pContentPath)
        
        # Step 3: Use openssl to encrypt that content
        # First, we need to extract the certificate we want to use from the keychain
        security_cmd = ['/usr/bin/security', 'find-certificate', '-c', args.name, '-p' ]
        if args.keychain:
            security_cmd += [args.keychain]
        proc = subprocess.Popen(security_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (sout, serr) = proc.communicate()
        if serr:
            print >> sys.stderr, "Error: %s" % serr
            sys.exit(1)
        # Now write the certificate to a temp file
        (certfile, certpath) = tempfile.mkstemp('.der')
        #print "Certpath: %s" % certpath
        try:
            with open(certpath, 'wb') as f:
                f.write(sout)
        except IOError:
            print >> sys.stderr, "Could not write to file!"
            sys.exit(1)      
        # Now use openssl to encrypt the payload content using that certificate
        (encPContentfile, encPContentPath) = tempfile.mkstemp('.plist')
        #print "encPContentPath: %s" % encPContentPath
        enc_cmd = ['/usr/bin/openssl', 'smime', '-encrypt', '-aes256', '-outform', 'der', 
                '-in', pContentPath, '-out', encPContentPath]
        enc_cmd += [certpath]
        proc = subprocess.Popen(enc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (encout, encerr) = proc.communicate()
        if encerr:
            print >> sys.stderr, "Error: %s" % encerr
            sys.exit(1)
        # openssl smime -encrypt produces no output if successful
        
        # Step 4: Add the new encrypted payload content back into the plist
        with open(encPContentPath, 'rb') as f:
            binaryEncPayload = f.read()
        del myProfile['PayloadContent']
        wrapped_data = NSData.dataWithBytes_length_(binaryEncPayload, len(binaryEncPayload))
        myProfile['EncryptedPayloadContent'] = wrapped_data

        # Step 5: Replace the plist with the new content
        plistData, error = NSPropertyListSerialization.dataFromPropertyList_format_errorDescription_(myProfile, NSPropertyListXMLFormat_v1_0, None)
        plistData.writeToFile_atomically_(outputFile, True)

        # Now clean up after ourselves
        os.remove(pContentPath)
        os.remove(certpath)
        os.remove(encPContentPath)
    
    if args.sign == 'sign' or args.sign == 'both':
        # Keychain check:
        if not args.name:
            print >> sys.stderr, 'Error: A certificate common name is required to sign profiles with the Keychain.'
            sys.exit(22)
        if args.sign == 'both':
            # If we already encrypted it, then the correct file is already in outputFile
            inputFile = outputFile
        else:
            inputFile = args.infile
        cmd = ['/usr/bin/security', 'cms', '-S', '-N', args.name, '-i', inputFile, '-o', args.outfile ]
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (sout, serr) = proc.communicate()
        if serr:
            print >> sys.stderr, 'Error: %s' % serr
            sys.exit(1)
        if args.sign == 'both':
            os.remove(outputFile)
Esempio n. 25
0
                         os.path.expanduser("~"))
for x in mmeTokenFile:
    try:
        int(
            x.split("/")[-1]
        )  #if we can cast to int, that means we have the DSID / account file.
        mmeTokenFile = x
    except ValueError:
        continue
if not isinstance(mmeTokenFile, str):
    print "Could not find MMeTokenFile. You can specify the file manually."
    sys.exit()
else:
    print "Decrypting token plist -> [%s]\n" % mmeTokenFile
#perform decryption with zero dependencies by using openssl binary
decryptedBinary = subprocess.check_output(
    "openssl enc -d -aes-128-cbc -iv '%s' -K %s < '%s'" %
    (IV, hexedKey, mmeTokenFile),
    shell=True)
#convert the decrypted binary plist to an NSData object that can be read
binToPlist = NSData.dataWithBytes_length_(decryptedBinary,
                                          len(decryptedBinary))
#convert the binary NSData object into a dictionary object
tokenPlist = NSPropertyListSerialization.propertyListWithData_options_format_error_(
    binToPlist, 0, None, None)[0]
#ta-da
print "Successfully decrypted token plist!\n"
print "%s [%s -> %s]" % (tokenPlist["appleAccountInfo"]["primaryEmail"],
                         tokenPlist["appleAccountInfo"]["fullName"],
                         tokenPlist["appleAccountInfo"]["dsPrsID"])
print tokenPlist["tokens"]
Esempio n. 26
0
def get_input():
    try:        
        while True:
            line = sys.stdin.readline()
            if not line:
                break

            if line == '':
                continue

            print "info:Read %s" % line
            sys.stdout.flush()
            cfg = None
            try:
                cfg = json.loads(line)
            except:
                pass

            if cfg == None:
                print "info:Unable to parse line"
                sys.stdout.flush()
                continue

            if cfg.has_key("Action"):
                print "info:Running %s" % cfg["Action"]
                sys.stdout.flush()

                if cfg["Action"] == "setmenu":
                    menu = cfg["Menu"]

                    if lookup.has_key(menu["Key"]):
                        lookup[menu["Key"]].title = menu["Text"]

                        if menu.has_key("Enabled") and not menu["Enabled"]:
                            lookup[menu["Key"]].set_callback(None)
                        else:
                            lookup[menu["Key"]].set_callback(item_clicked)
                        app.menu.update([])
                    else:
                        print "warn:Key not found %s" % cfg["Action"]
                        sys.stdout.flush()



                elif cfg["Action"] == "setmenus":
                    app.menu.clear()
                    app.menu = parsemenus(cfg)
                    print "info:Updated menus"
                    sys.stdout.flush()
                elif cfg["Action"] == "seticon":

                    try:
                        raw = base64.b64decode(cfg["Image"])
                        data = NSData.dataWithBytes_length_(raw, len(raw))
                        img = NSImage.alloc().initWithData_(data)    
                        img.setScalesWhenResized_(True)
                        img.setSize_((21, 21))
                        app.icon = img

                        print "info:Image updated"
                        sys.stdout.flush()

                    except:
                        print "warn:Failed to set image"
                        sys.stdout.flush()

                elif cfg["Action"] == "shutdown":
                    break
                elif cfg["Action"] == "notification":
                    if rumps_NOTIFICATIONS:
                        rumps.notification(cfg["Title"], '', cfg["Message"])

    finally:
        rumps.quit_application()     
        print "info:Shutdown"
        sys.stdout.flush()

    print "info:Stdin close"
    sys.stdout.flush()
    sys.stdin.close()
Esempio n. 27
0
def parse_plist(info_plist_string):
  # Use PyObjC, pre-installed in Apple's Python dist.
  data = NSData.dataWithBytes_length_(info_plist_string, len(info_plist_string))
  return NSPropertyListSerialization.propertyListWithData_options_format_error_(data, 0, None, None)
Esempio n. 28
0
def update_user_account(user_data):
    """
    Updates the user account. When being executed on a booted volume, updates
    via the Open Directory API. When being executed on a targeted volume,
    updates via the user account Property List.
    """

    name = user_data["name"]

    if is_booted_volume():
        node = get_od_node()

        if not node:
            print "Unable to look up OpenDirectory node, aborting..."
            exit(1)

        record, error = node.recordWithRecordType_name_attributes_error_(
            kODRecordTypeUsers, name, None, None)

        if error:
            print error
            exit(1)

        for attribute, value in user_data.items():

            # jpegphoto and ShadowHashData are data blobs, not strings, so a
            # little conversion is required
            if attribute == "jpegphoto" or attribute == "ShadowHashData":
                data = NSData.dataWithBytes_length_(value, len(value))
                value = NSArray.alloc().initWithObjects_(data)

            success, error = record.setValue_forAttribute_error_(
                value, attribute, None)

            if error:
                print error
                exit(1)

            # we don't want to spew out the data blobs to stdout, so we just
            # replace it with something simple. this is purely for formatting
            # reasons
            if attribute == "jpegphoto" or attribute == "ShadowHashData":
                value = "DATA"

            print "User account '" + name + "' updated attribute " + \
                attribute + ": " + str(value)
    else:  # Property List logic
        path = get_target() + get_user_plist_path() + name + ".plist"
        dictionary = plistlib.readPlist(path)

        for attribute, value in user_data.items():

            # jpegphoto and ShadowHashData are data blobs, not strings, so a
            # little conversion is required
            if attribute == "jpegphoto" or attribute == "ShadowHashData":
                value = plistlib.Data(value)

            dictionary[attribute] = [value]

            # we don't want to spew out the data blobs to stdout, so we just
            # replace it with something simple. this is purely for formatting
            # reasons
            if attribute == "jpegphoto" or attribute == "ShadowHashData":
                value = "DATA"

            print "User account '" + name + "' updated attribute " + \
                attribute + ": " + str(value)

        plistlib.writePlist(dictionary, path)
Esempio n. 29
0
 def set_clipboard(self, data):
     ns_data = NSData.dataWithBytes_length_(data, len(data))
     pb = self._ns_pasteboard
     pb.clearContents()
     pb.setData_forType_(ns_data, NSStringPboardType)
Esempio n. 30
0
def parse_plist(info_plist_string):
    # Use PyObjC, pre-installed in Apple's Python dist.
    data = NSData.dataWithBytes_length_(info_plist_string,
                                        len(info_plist_string))
    return NSPropertyListSerialization.propertyListWithData_options_format_error_(
        data, 0, None, None)