Example #1
0
    def checkRemovableDrives(self):
        drives = {}
        p = subprocess.Popen(["system_profiler", "SPUSBDataType", "-xml"], stdout=subprocess.PIPE)
        plist = plistlib.loads(p.communicate()[0])
        p.wait()

        for dev in self._findInTree(plist, "Mass Storage Device"):
            if "removable_media" in dev and dev["removable_media"] == "yes" and "volumes" in dev and len(dev["volumes"]) > 0:
                for vol in dev["volumes"]:
                    if "mount_point" in vol:
                        volume = vol["mount_point"]
                        drives[volume] = os.path.basename(volume)

        p = subprocess.Popen(["system_profiler", "SPCardReaderDataType", "-xml"], stdout=subprocess.PIPE)
        plist = plistlib.loads(p.communicate()[0])
        p.wait()

        for entry in plist:
            if "_items" in entry:
                for item in entry["_items"]:
                    for dev in item["_items"]:
                        if "removable_media" in dev and dev["removable_media"] == "yes" and "volumes" in dev and len(dev["volumes"]) > 0:
                            for vol in dev["volumes"]:
                                if "mount_point" in vol:
                                    volume = vol["mount_point"]
                                    drives[volume] = os.path.basename(volume)

        return drives
Example #2
0
    def checkRemovableDrives(self):
        drives = {}
        p = subprocess.Popen(["system_profiler", "SPUSBDataType", "-xml"], stdout = subprocess.PIPE)
        plist = plistlib.loads(p.communicate()[0])

        result = self._recursiveSearch(plist, "removable_media")

        p = subprocess.Popen(["system_profiler", "SPCardReaderDataType", "-xml"], stdout=subprocess.PIPE)
        plist = plistlib.loads(p.communicate()[0])

        result.extend(self._recursiveSearch(plist, "removable_media"))

        for drive in result:
            # Ignore everything not explicitly marked as removable
            if drive["removable_media"] != "yes":
                continue

            # Ignore any removable device that does not have an actual volume
            if "volumes" not in drive or not drive["volumes"]:
                continue

            for volume in drive["volumes"]:
                if not "mount_point" in volume:
                    continue

                mount_point = volume["mount_point"]

                if "_name" in volume:
                    drive_name = volume["_name"]
                else:
                    drive_name = os.path.basename(mount_point)

                drives[mount_point] = drive_name

        return drives
Example #3
0
def test_v1_plist():
    create_app_and_keys()
    data = {'app_id': 'com.mplewis.myapp', 'format': 'plist'}
    c = Client()
    resp = post_json(c, '/api/v1/', data)
    resp.status_code.should.eql(200)
    resp['Content-Type'].should.eql('application/x-plist')
    plistlib.loads(resp.content).should.eql(expected_keys)
 def test_appleformattingfromliteral(self):
     self.maxDiff = None
     for fmt in ALL_FORMATS:
         with self.subTest(fmt=fmt):
             pl = self._create(fmt=fmt)
             pl2 = plistlib.loads(TESTDATA[fmt], fmt=fmt)
             self.assertEqual(dict(pl), dict(pl2), "generated data was not identical to Apple's output")
             pl2 = plistlib.loads(TESTDATA[fmt])
             self.assertEqual(dict(pl), dict(pl2), "generated data was not identical to Apple's output")
 def test_nondictroot(self):
     for fmt in ALL_FORMATS:
         with self.subTest(fmt=fmt):
             test1 = "abc"
             test2 = [1, 2, 3, "abc"]
             result1 = plistlib.loads(plistlib.dumps(test1, fmt=fmt))
             result2 = plistlib.loads(plistlib.dumps(test2, fmt=fmt))
             self.assertEqual(test1, result1)
             self.assertEqual(test2, result2)
Example #6
0
 def test_invalid_binary(self):
     for data in [
             # too short data
             b'',
             # too large offset_table_offset and nonstandard offset_size
             b'\x00\x08'
             b'\x00\x00\x00\x00\x00\x00\x03\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x00'
             b'\x00\x00\x00\x00\x00\x00\x00\x2a',
             # integer overflow in offset_table_offset
             b'\x00\x08'
             b'\x00\x00\x00\x00\x00\x00\x01\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x00'
             b'\xff\xff\xff\xff\xff\xff\xff\xff',
             # offset_size = 0
             b'\x00\x08'
             b'\x00\x00\x00\x00\x00\x00\x00\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x00'
             b'\x00\x00\x00\x00\x00\x00\x00\x09',
             # ref_size = 0
             b'\xa1\x01\x00\x08\x0a'
             b'\x00\x00\x00\x00\x00\x00\x01\x00'
             b'\x00\x00\x00\x00\x00\x00\x00\x02'
             b'\x00\x00\x00\x00\x00\x00\x00\x00'
             b'\x00\x00\x00\x00\x00\x00\x00\x0b',
             # integer overflow in offset
             b'\x00\xff\xff\xff\xff\xff\xff\xff\xff'
             b'\x00\x00\x00\x00\x00\x00\x08\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x00'
             b'\x00\x00\x00\x00\x00\x00\x00\x09',
             # invalid ASCII
             b'\x51\xff\x08'
             b'\x00\x00\x00\x00\x00\x00\x01\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x00'
             b'\x00\x00\x00\x00\x00\x00\x00\x0a',
             # invalid UTF-16
             b'\x61\xd8\x00\x08'
             b'\x00\x00\x00\x00\x00\x00\x01\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x01'
             b'\x00\x00\x00\x00\x00\x00\x00\x00'
             b'\x00\x00\x00\x00\x00\x00\x00\x0b',
             ]:
         with self.assertRaises(plistlib.InvalidFileException):
             plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY)
    def test_skipkeys(self):
        pl = {42: "aNumber", "snake": "aWord"}

        for fmt in ALL_FORMATS:
            with self.subTest(fmt=fmt):
                data = plistlib.dumps(pl, fmt=fmt, skipkeys=True, sort_keys=False)

                pl2 = plistlib.loads(data)
                self.assertEqual(pl2, {"snake": "aWord"})

                fp = BytesIO()
                plistlib.dump(pl, fp, fmt=fmt, skipkeys=True, sort_keys=False)
                data = fp.getvalue()
                pl2 = plistlib.loads(fp.getvalue())
                self.assertEqual(pl2, {"snake": "aWord"})
Example #8
0
def read_property_list(*lines):
    """Portable front end to plistlib.readPlistFromString() or loads()."""
    import plistlib
    text = '\n'.join(lines)
    if sys.version_info.major == 2:
        return plistlib.readPlistFromString(text)   #pylint: disable=no-member
    return plistlib.loads(text.encode())
Example #9
0
def filtered_profiles(team=None, app_id=None, type=None):
	profile_dicts = {}
	filtered = []
	for profile_path in local_profiles():
		plist_string = plist_from_profile(profile_path)
		plist_dict = plistlib.loads(plist_string)
		profile_dicts[profile_path] = plist_dict
	profiles = list(profile_dicts.keys())
	if team is None:
		filtered = profiles
	else:
		for profile in profiles:
			profile_dict = profile_dicts[profile]
			if profile_dict["ApplicationIdentifierPrefix"][0] == team:
				filtered.append(profile)
	if app_id is not None:
		profiles = filtered
		filtered = []
		for profile in profiles:
			profile_dict = profile_dicts[profile]
			prof_app_id = profile_dict["Entitlements"]["application-identifier"]
			prof_app_id = prof_app_id.replace(profile_dict["ApplicationIdentifierPrefix"][0]+".", "")
			if prof_app_id == app_id:
				filtered.append(profile)
	# return dict[name]->file
	prof_name_dict = {}
	for profile in filtered:
		prof_dict = profile_dicts[profile]
		prof_name_dict[prof_dict["Name"]] = profile
	return prof_name_dict
    def plist_as_dict(self):
        """Makes the network request and returns data"""
        if self.data:
            return self.data

        purl = urlparse(self.url)
        if purl.scheme == "https":
            conn = http.HTTPSConnection(purl.hostname, purl.port)
        else:
            conn = http.HTTPConnection(purl.hostname, purl.port)

        conn.request(self.method, purl.path, self.body, self.headers)
        response = conn.getresponse()

        data = response.read()
        try:
            self.data = plistlib.loads(data)
        except ExpatError:
            self.data = None

        if response.status != 200:
            print("Request %s returned code %d" % (self.url, response.status))
            return None

        return self.data
Example #11
0
def com_google_fonts_check_ftxvalidator(font):
  """Checking with ftxvalidator."""
  import plistlib
  try:
    import subprocess
    ftx_cmd = [
        "ftxvalidator",
        "-t",
        "all",  # execute all checks
        font
    ]
    ftx_output = subprocess.check_output(ftx_cmd, stderr=subprocess.STDOUT)
    ftx_data = plistlib.loads(ftx_output)
    # we accept kATSFontTestSeverityInformation
    # and kATSFontTestSeverityMinorError
    if 'kATSFontTestSeverityFatalError' \
       not in ftx_data['kATSFontTestResultKey']:
      yield PASS, "ftxvalidator passed this file"
    else:
      ftx_cmd = [
          "ftxvalidator",
          "-T",  # Human-readable output
          "-r",  # Generate a full report
          "-t",
          "all",  # execute all checks
          font
      ]
      ftx_output = subprocess.check_output(ftx_cmd, stderr=subprocess.STDOUT)
      yield FAIL, f"ftxvalidator output follows:\n\n{ftx_output}\n"

  except subprocess.CalledProcessError as e:
    yield ERROR, ("ftxvalidator returned an error code. Output follows:"
                 "\n\n{}\n").format(e.output.decode('utf-8'))
  except OSError:
    yield ERROR, "ftxvalidator is not available!"
    def test_int(self):
        for pl in [
            0,
            2 ** 8 - 1,
            2 ** 8,
            2 ** 16 - 1,
            2 ** 16,
            2 ** 32 - 1,
            2 ** 32,
            2 ** 63 - 1,
            2 ** 64 - 1,
            1,
            -2 ** 63,
        ]:
            for fmt in ALL_FORMATS:
                with self.subTest(pl=pl, fmt=fmt):
                    data = plistlib.dumps(pl, fmt=fmt)
                    pl2 = plistlib.loads(data)
                    self.assertIsInstance(pl2, int)
                    self.assertEqual(pl, pl2)
                    data2 = plistlib.dumps(pl2, fmt=fmt)
                    self.assertEqual(data, data2)

        for fmt in ALL_FORMATS:
            for pl in (2 ** 64 + 1, 2 ** 127 - 1, -2 ** 64, -2 ** 127):
                with self.subTest(pl=pl, fmt=fmt):
                    self.assertRaises(OverflowError, plistlib.dumps, pl, fmt=fmt)
 def test_appleformatting(self):
     for use_builtin_types in (True, False):
         for fmt in ALL_FORMATS:
             with self.subTest(fmt=fmt, use_builtin_types=use_builtin_types):
                 pl = plistlib.loads(TESTDATA[fmt], use_builtin_types=use_builtin_types)
                 data = plistlib.dumps(pl, fmt=fmt)
                 self.assertEqual(data, TESTDATA[fmt], "generated data was not identical to Apple's output")
 def test_large_timestamp(self):
     # Issue #26709: 32-bit timestamp out of range
     for ts in -2 ** 31 - 1, 2 ** 31:
         with self.subTest(ts=ts):
             d = datetime.datetime.utcfromtimestamp(0) + datetime.timedelta(seconds=ts)
             data = plistlib.dumps(d, fmt=plistlib.FMT_BINARY)
             self.assertEqual(plistlib.loads(data), d)
Example #15
0
 def _call_ipptool(self, request):
     with tempfile.NamedTemporaryFile(delete=False) as temp_file:
         temp_file.write(bytes(request, encoding='utf-8'))
     process = subprocess.Popen([self.config['ipptool_path'],
                                 self.authenticated_uri,
                                 '-X',
                                 temp_file.name],
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
     future = []
     timer = threading.Timer(self.config['timeout'],
                             self.timeout_handler, (process, future))
     timer.start()
     try:
         stdout, stderr = process.communicate()
     finally:
         os.unlink(temp_file.name)
     timer.cancel()
     if future:
         raise TimeoutError
     if PY3:
         result = plistlib.loads(stdout)
     else:
         result = plistlib.readPlistFromString(stdout)
     try:
         return result['Tests'][0]
     except (IndexError, KeyError):
         logger = logging.getLogger(__name__)
         logger.error('ipptool command failed: {} {}'.format(stdout,
                                                             stderr))
         raise
Example #16
0
def status(job_label, runas=None):
    '''
    Return the status for a service, returns a bool whether the service is
    running.

    CLI Example:

    .. code-block:: bash

        salt '*' service.status <service label>
    '''
    service = _service_by_name(job_label)

    lookup_name = service['plist']['Label'] if service else job_label
    launchctl_data = _get_launchctl_data(lookup_name, runas=runas)

    if launchctl_data:
        if BEFORE_YOSEMITE:
            if six.PY3:
                return 'PID' in plistlib.loads(launchctl_data)
            else:
                return 'PID' in dict(plistlib.readPlistFromString(launchctl_data))
        else:
            pattern = '"PID" = [0-9]+;'
            return True if re.search(pattern, launchctl_data) else False
    else:
        return False
Example #17
0
 def test_cycles(self):
     # recursive list
     a = []
     a.append(a)
     b = plistlib.loads(plistlib.dumps(a, fmt=plistlib.FMT_BINARY))
     self.assertIs(b[0], b)
     # recursive tuple
     a = ([],)
     a[0].append(a)
     b = plistlib.loads(plistlib.dumps(a, fmt=plistlib.FMT_BINARY))
     self.assertIs(b[0][0], b)
     # recursive dict
     a = {}
     a['x'] = a
     b = plistlib.loads(plistlib.dumps(a, fmt=plistlib.FMT_BINARY))
     self.assertIs(b['x'], b)
Example #18
0
 def test_bytes(self):
     pl = self._create()
     data = plistlib.dumps(pl)
     pl2 = plistlib.loads(data)
     self.assertEqual(dict(pl), dict(pl2))
     data2 = plistlib.dumps(pl2)
     self.assertEqual(data, data2)
Example #19
0
def readPlist(pathOrFile):
    """Raises NotBinaryPlistException, InvalidPlistException"""
    didOpen = False
    result = None
    if isinstance(pathOrFile, (six.binary_type, six.text_type)):
        pathOrFile = open(pathOrFile, 'rb')
        didOpen = True
    try:
        reader = PlistReader(pathOrFile)
        result = reader.parse()
    except NotBinaryPlistException as e:
        try:
            pathOrFile.seek(0)
            result = None
            if hasattr(plistlib, 'loads'):
                contents = None
                if isinstance(pathOrFile, (six.binary_type, six.text_type)):
                    with open(pathOrFile, 'rb') as f:
                        contents = f.read()
                else:
                    contents = pathOrFile.read()
                result = plistlib.loads(contents)
            else:
                result = plistlib.readPlist(pathOrFile)
            result = wrapDataObject(result, for_binary=True)
        except Exception as e:
            raise InvalidPlistException(e)
    finally:
        if didOpen:
            pathOrFile.close()
    return result
Example #20
0
def _machine_id():
    """
    for informational purposes, try to get a machine unique id thing
    """
    if platform.isLinux():
        try:
            # why this? see: http://0pointer.de/blog/projects/ids.html
            with open('/var/lib/dbus/machine-id', 'r') as f:
                return f.read().strip()
        except:
            # Non-dbus using Linux, get a hostname
            return socket.gethostname()

    elif platform.isMacOSX():
        # Get the serial number of the platform
        import plistlib
        plist_data = subprocess.check_output(["ioreg", "-rd1", "-c", "IOPlatformExpertDevice", "-a"])

        if six.PY2:
            # Only API on 2.7
            return plistlib.readPlistFromString(plist_data)[0]["IOPlatformSerialNumber"]
        else:
            # New, non-deprecated 3.4+ API
            return plistlib.loads(plist_data)[0]["IOPlatformSerialNumber"]

    else:
        # Something else, just get a hostname
        return socket.gethostname()
Example #21
0
File: darwin.py Project: flit/pyOCD
def _plist_from_popen(popen):
    out, _ = popen.communicate()
    if not out:
        return []
    try:
        return loads(out)
    except ExpatError:
        return []
Example #22
0
 def test_bytes(self):
     pl = self._create()
     data = plistlib.dumps(pl)
     pl2 = plistlib.loads(data)
     self.assertNotIsInstance(pl, plistlib._InternalDict)
     self.assertEqual(dict(pl), dict(pl2))
     data2 = plistlib.dumps(pl2)
     self.assertEqual(data, data2)
Example #23
0
    def device_in_profile(udid):
        try:
            profile = subprocess.check_output(['security', 'cms', '-D', '-i',
                                              PROVISIONING_PROFILE])
            plist = plistlib.loads(profile)
            return udid in plist['ProvisionedDevices']

        except subprocess.CalledProcessError:
            return False
    def test_dict_members(self):
        pl = {"first": {"a": 1}, "second": {"a": 1}, "third": {"b": 2}}

        for fmt in ALL_FORMATS:
            with self.subTest(fmt=fmt):
                data = plistlib.dumps(pl, fmt=fmt)
                pl2 = plistlib.loads(data)
                self.assertEqual(pl2, {"first": {"a": 1}, "second": {"a": 1}, "third": {"b": 2}})
                self.assertIsNot(pl2["first"], pl2["second"])
Example #25
0
    def update(self, view):
        if not self.need_update:
            return
        self.need_update = False

        content = self.color_scheme.content()
        current_colors = set("#%s" % c.upper() for c in re.findall(r'\b%s([a-fA-F0-9]{8})\b' % self.prefix, content))

        bg_col = self.get_background_col(view)

        rules = []
        if not re.search(r'\b%sgutter\b' % self.prefix, content):
            rules.append({
                "scope": "%sgutter" % self.prefix,
                "background": "#000000",
                "foreground": "#ffffff",
            })
        for col, name in self.colors.items():
            if col not in current_colors:
                fg_col = self.get_inv_col(bg_col, col)
                rules.append({
                    "scope": name,
                    "background": col,
                    "foreground": fg_col,
                })

        if rules:
            try:
                # For sublime-color-scheme
                m = re.search(r'([\t ]*)"rules":\s*\[[\r\n]*', content)
                if m:
                    json_rules = json.dumps({"rules": rules}, indent=m.group(1))
                    json_rules = '\n'.join(map(str.rstrip, json_rules.split('\n')[2:-2])) + ',\n'
                    content = content[:m.end()] + json_rules + content[m.end():]
                    write_package(self.color_scheme.path, content)
                    log.debug("Updated sublime-color-scheme")
                    return

                # for tmTheme
                if re.match(r'\s*<(?:\?xml|!DOCTYPE|plist)\b', content):
                    plist_content = plistlib.loads(content.encode('utf-8'))
                    plist_content['settings'].extend({
                        "scope": r['scope'],
                        "settings": {
                            "foreground": r['foreground'],
                            "background": r['background'],
                        }
                    } for r in rules)
                    content = plistlib.dumps(plist_content).decode('utf-8')
                    write_package(self.color_scheme.path, content)
                    log.debug("Updated tmTheme")
                    return

                log.error("Not Updated: Schema format not recognized")
            except Exception as e:
                import traceback; traceback.print_exc();
                log.error("Not Updated: %r" % e)
Example #26
0
 def get_provisioning_profile_id():
     try:
         profile = subprocess.check_output(['security', 'cms', '-D', '-i',
                                           PROVISIONING_PROFILE],
                                           stderr=subprocess.STDOUT)
         plist = plistlib.loads(profile)
         return plist['UUID']
     except subprocess.CalledProcessError:
         return None
 def __init__(self, metadata_blob):
     metadata = plistlib.loads(metadata_blob)
     # The current version has a 1-element array at toplevel.
     # Future versions will have a dictionary at toplevel.
     if isinstance(metadata, list) and len(metadata) == 1:
         metadata = metadata[0]
     assert isinstance(metadata, dict)
     self.metadata = metadata
     self.secrets = None
Example #28
0
	def getpacket(self):
		resp, tag, payload = BinaryProtocol.getpacket(self)
		if resp != self.TYPE_PLIST:
			raise MuxError("Received non-plist type %d"%resp)
		if PY3:
			payload = plistlib.loads(payload)
		else:
			payload = plistlib.readPlistFromString(payload)
		return payload['MessageType'], tag, payload
Example #29
0
    def test_dataobject_deprecated(self):
        in_data = { 'key': plistlib.Data(b'hello') }
        out_data = { 'key': b'hello' }

        buf = plistlib.dumps(in_data)

        cur = plistlib.loads(buf)
        self.assertEqual(cur, out_data)
        self.assertNotEqual(cur, in_data)

        cur = plistlib.loads(buf, use_builtin_types=False)
        self.assertNotEqual(cur, out_data)
        self.assertEqual(cur, in_data)

        with self.assertWarns(DeprecationWarning):
            cur = plistlib.readPlistFromBytes(buf)
        self.assertNotEqual(cur, out_data)
        self.assertEqual(cur, in_data)
def get_usb_drives():
    """Enumerate USB Drives attached to Mac"""
    plist_byte_object = (subprocess.Popen(["system_profiler", "SPUSBDataType",
                                      "-xml"], stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE).communicate())[0]
    
    plist_object = plistlib.loads(plist_byte_object)
    valid_usb_drives = traverse_plist(plist_object, 0, [], [])
    return valid_usb_drives
Example #31
0
        ]

        notarizeStapler = [
            "xcrun",
            "stapler",
            "staple", existingDmgLocation
        ]

        print("notarizing app")
        notarisationRequestUUID = None
        with tempfile.TemporaryFile(mode='w+b') as stdoutFile:
            popen = subprocess.Popen(notarize, stdout=stdoutFile)
            popen.wait()
            stdoutFile.seek(0)
            data = stdoutFile.read()
            data = plistlib.loads(data)
            if "notarization-upload" in data:
                notarisationRequestUUID = data["notarization-upload"].get("RequestUUID")
                print("notarisation Request UUID:", notarisationRequestUUID)

            if "product-errors" in data:
                print("\n".join([e["message"] for e in data["product-errors"]]))
        print("done notarizing app")

        notarisationSucces = False
        if notarisationRequestUUID:
            print("getting notarization info")
            notarizeInfo = [
                "xcrun",
                "altool",
                "--notarization-info", notarisationRequestUUID,
Example #32
0
def wait_for_results(uuids, config):
    """Waits for results from the notarization service. This iterates the list
    of UUIDs and checks the status of each one. For each successful result, the
    function yields to the caller. If a request failed, this raises a
    NotarizationError. If no requests are ready, this operation blocks and
    retries until a result is ready. After a certain amount of time, the
    operation will time out with a NotarizationError if no results are
    produced.

    Args:
        uuids: List of UUIDs to check for results. The list must not be empty.
        config: The |config.CodeSignConfig| object.

    Yields:
        The UUID of a successful notarization request.
    """
    assert len(uuids)

    wait_set = set(uuids)

    sleep_time_seconds = 5
    total_sleep_time_seconds = 0

    while len(wait_set) > 0:
        for uuid in list(wait_set):
            try:
                command = [
                    'xcrun', 'altool', '--notarization-info', uuid,
                    '--username', config.notary_user, '--password',
                    config.notary_password, '--output-format', 'xml'
                ]
                if config.notary_asc_provider is not None:
                    command.extend(
                        ['--asc-provider', config.notary_asc_provider])
                output = commands.run_command_output(command)
            except subprocess.CalledProcessError as e:
                # A notarization request might report as "not found" immediately
                # after submission, which causes altool to exit non-zero. Check
                # for this case and parse the XML output to ensure that the
                # error code refers to the not-found state. The UUID is known-
                # good since it was a result of submit(), so loop to wait for
                # it to show up.
                if e.returncode == 239:
                    plist = plistlib.loads(e.output)
                    if plist['product-errors'][0]['code'] == 1519:
                        continue
                raise e

            plist = plistlib.loads(output)
            info = plist['notarization-info']
            status = info['Status']
            if status == 'in progress':
                continue
            elif status == 'success':
                print('Successfully notarized request {}. Log file: {}'.format(
                    uuid, info[_LOG_FILE_URL]))
                wait_set.remove(uuid)
                yield uuid
            else:
                print('Failed to notarize request {}. Log file: {}. Output:\n{}'
                      .format(uuid, info[_LOG_FILE_URL], output))
                raise NotarizationError(
                    'Notarization request {} failed with status: "{}". '
                    'Log file: {}.'.format(uuid, status, info[_LOG_FILE_URL]))

        if len(wait_set) > 0:
            # Do not wait more than 30 minutes for all the operations to
            # complete.
            if total_sleep_time_seconds < 30 * 60:
                # No results were available, so wait and try again in some
                # number of seconds. Do not wait more than 1 minute for any
                # iteration.
                time.sleep(sleep_time_seconds)
                total_sleep_time_seconds += sleep_time_seconds
                sleep_time_seconds = min(sleep_time_seconds * 2, 60)
            else:
                raise NotarizationError(
                    'Timed out waiting for notarization requests: {}'.format(
                        uuids))
Example #33
0
 def do_cat(self, p):
     data = self.afc.get_file_contents(self.curdir + "/" + p)
     if data and p.endswith(".plist"):
         pprint(plistlib.loads(data))
     else:
         print(data)
Example #34
0
 def test_indentation_dict(self):
     data = {'1': {'2': {'3': {'4': {'5': {'6': {'7': {'8': {'9': b'aaaaaa'}}}}}}}}}
     self.assertEqual(plistlib.loads(plistlib.dumps(data)), data)
Example #35
0
 def read(self):
     size, = struct.unpack('>L', self.pipe.read(4))
     response = self.pipe.read_all(size)
     return plistlib.loads(response)
Example #36
0
 def test_invalid_binary(self):
     for name, data in INVALID_BINARY_PLISTS:
         with self.subTest(name):
             with self.assertRaises(plistlib.InvalidFileException):
                 plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY)
Example #37
0
 def dump(self, file_obj: BinaryIO) -> None:  # type: ignore
     binary = plistlib.dumps(  # todo: change dumps to binary and remove this
         plistlib.loads(self.dumps().encode('utf-8')),  # type: ignore
         fmt=plistlib.FMT_BINARY,
     )
     file_obj.write(binary)
Example #38
0
 def test_indentation_dict_mix(self):
     data = {'1': {'2': [{'3': [[[[[{'test': b'aaaaaa'}]]]]]}]}}
     self.assertEqual(plistlib.loads(plistlib.dumps(data)), data)
Example #39
0
 def test_indentation_array(self):
     data = [[[[[[[[{'test': b'aaaaaa'}]]]]]]]]
     self.assertEqual(plistlib.loads(plistlib.dumps(data)), data)
Example #40
0
def ota_authenticate():
    """Over-The-Air Profile Delivery Phase 3 and 4.

    This endpoint represents the OTA Phase 3 and 4, "/profile" endpoint as specified in apples document "Over-The-Air
    Profile Delivery".

    There are two types of requests made here:
    - The first request is signed by the iPhone Device CA and contains the challenge in the `Profile Service` payload,
        we respond with the SCEP detail.
    - The second request is signed by the issued SCEP certificate. We should respond with an enrollment profile.
        It also contains the same device attributes sent in the previous step, but this time they are authenticated by
        our SCEP CA.

    Examples:

    Signed plist given in the first request::

        {
            'CHALLENGE': '<CHALLENGE FROM PROFILE HERE>',
            'IMEI': 'empty if macOS',
            'MEID': 'empty if macOS',
            'NotOnConsole': False,
            'PRODUCT': 'MacPro6,1',
            'SERIAL': 'C020000000000',
            'UDID': '00000000-0000-0000-0000-000000000000',
            'UserID': '00000000-0000-0000-0000-000000000000',
            'UserLongName': 'Joe User',
            'UserShortName': 'juser',
            'VERSION': '16F73'
        }

    See Also:
        - `Over-the-Air Profile Delivery and Configuration <https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/iPhoneOTAConfiguration/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009505-CH1-SW1>`_.
    """
    signed_data = g.signed_data
    signers = g.signers
    # TODO: This should Validate to iPhone Device CA but we can't because:
    # http://www.openradar.me/31423312
    device_attributes = plistlib.loads(signed_data)

    current_app.logger.debug(device_attributes)

    try:
        org = db.session.query(Organization).one()
    except NoResultFound:
        abort(
            500,
            'No organization is configured, cannot generate enrollment profile.'
        )
    except MultipleResultsFound:
        abort(500,
              'Multiple organizations, backup your database and start again')

    # TODO: Behold, the stupidest thing ever just to get this working, theres no way this should be prod:
    # Phase 4 does not send a challenge but phase 3 does
    if 'CHALLENGE' in device_attributes:
        # Reply SCEP
        profile = Profile(
            identifier=org.payload_prefix + '.ota.phase3',
            uuid=uuid4(),
            display_name='Commandment OTA SCEP Enrollment',
            description=
            'Retrieves a SCEP Certificate to complete OTA Enrollment',
            organization=org.name,
            version=1,
            scope=PayloadScope.System,
        )

        scep_payload = scep_payload_from_configuration()
        profile.payloads.append(scep_payload)
    else:
        profile = generate_enroll_profile()
    # profile = generate_enroll_profile()

    schema = profile_schema.ProfileSchema()
    result = schema.dump(profile)
    plist_data = dumps_none(result.data, skipkeys=True)

    return plist_data, 200, {'Content-Type': PROFILE_CONTENT_TYPE}
Example #41
0
def test_export_firmware_extended_macos(C):
    """
    Check, whether the firmware file is exported correctly, and in correct size.
    Apparently, the auto-remounting side effect of the v0.46 change, is disturbing the export process.
    Unmounting the UV just before the export gives the device 20/20 success rate.
    Test case for issue https://github.com/Nitrokey/nitrokey-app/issues/399
    """

    skip_if_device_version_lower_than({'S': 43})
    skip_if_not_macos(
        'macOS specific test, due to the mount path and command.')

    import pexpect
    from time import sleep
    import os
    from os.path import exists as exist
    import plistlib

    usb_devices = pexpect.run('system_profiler -xml SPUSBDataType')
    assert b'Nitrokey' in usb_devices, 'No Nitrokey devices connected'
    usb_devices_parsed = plistlib.loads(usb_devices)

    assert isinstance(usb_devices_parsed,
                      list), 'usb_devices_parsed has unexpected type'

    # Try to get all USB devices
    try:
        devices = usb_devices_parsed[0]['_items'][0]['_items']
    except KeyError:
        devices = None

    assert devices is not None, 'could not list USB devices'

    device_item = None

    for item in devices:
        if '_items' in item:
            # Fix for macOS 10.13.6, Python 3.6.2
            item = item['_items'][0]
        if 'manufacturer' in item and item['manufacturer'] == 'Nitrokey':
            device_item = item

    # Try to get first volume of USB device
    try:
        volume = device_item['Media'][0]['volumes'][0]
    except (KeyError, TypeError):
        volume = None

    assert volume is not None, 'could not determine volume'
    assert 'bsd_name' in volume, 'could not get BSD style device name'

    device = '/dev/' + volume['bsd_name']
    pexpect.run(f'diskutil mount {device}')
    sleep(3)
    assert 'mount_point' in volume, 'could not get mount point'
    firmware_abs_path = volume['mount_point'] + '/firmware.bin'
    checks = 0
    print('path: {}, device: {}'.format(firmware_abs_path, device))
    checks_add = 0

    if exist(firmware_abs_path):
        os.remove(firmware_abs_path)

    assert not exist(firmware_abs_path)

    ATTEMPTS = 20
    for i in range(ATTEMPTS):
        # if umount is disabled, success rate is 3/10, enabled: 10/10
        pexpect.run(f'diskutil unmount {device}')
        assert C.NK_export_firmware(
            DefaultPasswords.ADMIN) == DeviceErrorCode.STATUS_OK
        pexpect.run(f'diskutil mount {device}')
        sleep(1)
        firmware_file_exist = exist(firmware_abs_path)
        if firmware_file_exist:
            checks += 1
            getsize = os.path.getsize(firmware_abs_path)
            print('Firmware file exist, size: {}'.format(getsize))
            checks_add += 1 if getsize >= 100 * 1024 else 0
            # checks_add += 1 if os.path.getsize(firmware_abs_path) == 256*1024 else 0
            os.remove(firmware_abs_path)
        assert not exist(firmware_abs_path)

    print('CHECK {} ; CHECK ADDITIONAL {}'.format(checks, checks_add))

    assert checks == ATTEMPTS
    assert checks_add == checks
Example #42
0
def read_plist(p: Path) -> dict:
    escaped = "".join(
        (chr(ord(char) + OFFSET) if ord(char) in BAD_CODES else char)
        for char in p.read_text())
    return plistlib.loads(escaped.encode("utf-8"))
Example #43
0
 def parse_plist(catalog_data):
     if sys.version_info > (3, 0):
         root = plistlib.loads(catalog_data)
     else:
         root = plistlib.readPlistFromString(catalog_data)
     return root
Example #44
0
def profile_plist_for_args(args):
    pnargs = [CLT_BINARY]
    pnargs.extend(args)
    pnargs.extend(["-O", "-"])
    out = subprocess.check_output(pnargs)
    return plistlib.loads(out)
Example #45
0
 def getpacket(self):
     resp, tag, payload = super().getpacket()
     if resp != self.TYPE_PLIST:
         raise MuxError('Received non-plist type %d' % resp)
     payload = plistlib.loads(payload)
     return payload.get('MessageType', ''), tag, payload
Example #46
0
 def plist(self):
     import plistlib
     return plistlib.loads(self.content)
Example #47
0
    def ParseFileObject(self, parser_mediator, file_object):
        """Parses a plist file-like object.

    Args:
      parser_mediator (ParserMediator): mediates interactions between parsers
          and other components, such as storage and dfvfs.
      file_object (dfvfs.FileIO): a file-like object.

    Raises:
      UnableToParseFile: when the file cannot be parsed.
    """
        filename = parser_mediator.GetFilename()
        file_size = file_object.get_size()

        if file_size <= 0:
            raise errors.UnableToParseFile(
                'File size: {0:d} bytes is less equal 0.'.format(file_size))

        if file_size > self._MAXIMUM_PLIST_FILE_SIZE:
            raise errors.UnableToParseFile(
                'File size: {0:d} bytes is larger than 50 MB.'.format(
                    file_size))

        plist_data = file_object.read()

        has_leading_whitespace = False

        is_binary_plist = plist_data.startswith(b'bplist0')
        if not is_binary_plist:
            byte_order_mark_size, encoding = self._CheckByteOrderMark(
                plist_data)

            xml_signature = '<?xml '.encode(encoding)
            is_xml = plist_data[byte_order_mark_size:].startswith(
                xml_signature)
            if not is_xml:
                # Preserve the byte-order-mark for plistlib.
                plist_data = b''.join([
                    plist_data[:byte_order_mark_size],
                    plist_data[byte_order_mark_size:].lstrip()
                ])
                is_xml = plist_data[byte_order_mark_size:].startswith(
                    xml_signature)
                has_leading_whitespace = is_xml

            if is_xml:
                plist_footer = '</plist>'.encode(encoding)
                plist_data = plist_data.rstrip()

                if not plist_data.endswith(plist_footer):
                    raise errors.UnableToParseFile(
                        'Unable to parse XML plist with error: missing plist XML root '
                        'element.')

        try:
            top_level_object = plistlib.loads(plist_data)

        except (AttributeError, binascii.Error, expat.ExpatError,
                plistlib.InvalidFileException) as exception:
            raise errors.UnableToParseFile(
                'Unable to parse plist with error: {0!s}'.format(exception))

        except (LookupError, ValueError) as exception:
            # LookupError will be raised in cases where the plist is an XML file
            # that contains an unsupported encoding.
            # ValueError will be raised in cases where the plist is an XML file
            # that contains an unsupported date and time value.
            parser_mediator.ProduceExtractionWarning(
                'unable to parse XML plist with error: {0!s}'.format(
                    exception))
            return

        if not top_level_object:
            # Do not produce an extraction warning for a binary plist without a top
            # level object.
            if not is_binary_plist:
                parser_mediator.ProduceExtractionWarning((
                    'unable to parse XML plist file with error: missing top level '
                    'object'))
            return

        if has_leading_whitespace:
            parser_mediator.ProduceExtractionWarning(
                'XML plist file with leading whitespace')

        filename_lower_case = filename.lower()

        try:
            top_level_keys = set(top_level_object.keys())
        except AttributeError as exception:
            raise errors.UnableToParseFile(
                'Unable to parse top level keys of: {0:s} with error: {1!s}.'.
                format(filename, exception))

        found_matching_plugin = False
        for plugin in self._plugins:
            if parser_mediator.abort:
                break

            if not plugin.PLIST_PATH_FILTERS:
                path_filter_match = True
            else:
                path_filter_match = False
                for path_filter in plugin.PLIST_PATH_FILTERS:
                    if path_filter.Match(filename_lower_case):
                        path_filter_match = True

            file_entry = parser_mediator.GetFileEntry()
            display_name = parser_mediator.GetDisplayName(file_entry)

            if (not path_filter_match
                    or not top_level_keys.issuperset(plugin.PLIST_KEYS)):
                logger.debug(
                    'Skipped parsing file: {0:s} with plugin: {1:s}'.format(
                        display_name, plugin.NAME))
                continue

            logger.debug('Parsing file: {0:s} with plugin: {1:s}'.format(
                display_name, plugin.NAME))

            try:
                plugin.UpdateChainAndProcess(parser_mediator,
                                             top_level=top_level_object)
                found_matching_plugin = True

            except Exception as exception:  # pylint: disable=broad-except
                parser_mediator.ProduceExtractionWarning(
                    ('plugin: {0:s} unable to parse plist file with error: '
                     '{1!s}').format(plugin.NAME, exception))

        if not found_matching_plugin and self._default_plugin:
            self._default_plugin.UpdateChainAndProcess(
                parser_mediator, top_level=top_level_object)
Example #48
0
    def post(self, request, *args, **kwargs):
        # Verify payload signature, extract signed payload
        try:
            certificates, payload = verify_signed_payload(request.read())
        except ValueError:
            self.abort("posted data is not signed")

        # find out which CA signed the certificate used to sign the payload
        # if iPhone CA: phase 2
        # if SCEP CA: phase 3
        # if unknown: phase 2  # TODO: verify. seen with self signed cert in 10.13 beta in VMWare.
        for certificate_i_cn, certificate_bytes, signing_certificate in certificates:
            if verify_apple_iphone_device_ca_issuer_openssl(certificate_bytes):
                phase = 2
                break
            elif verify_zentral_scep_ca_issuer_openssl(certificate_bytes):
                phase = 3
                break
            else:
                self.post_event(
                    "warning",
                    reason="unknown signing certificate issuer '{}'".format(
                        certificate_i_cn))
                phase = 2

        payload = plistlib.loads(payload)
        self.serial_number = payload["SERIAL"]
        self.udid = payload["UDID"]

        if phase == 2:
            # Verify the challenge
            challenge = payload.get("CHALLENGE")
            if not challenge:
                self.abort("missing challenge", phase=phase)
            try:
                es_request = verify_enrollment_secret("ota_enrollment",
                                                      challenge,
                                                      self.user_agent, self.ip,
                                                      self.serial_number,
                                                      self.udid)
            except EnrollmentSecretVerificationFailed as e:
                self.abort("secret verification failed: '{}'".format(
                    e.err_msg),
                           phase=phase)

            # Start an OTA enrollment session
            ota_enrollment_session = OTAEnrollmentSession.objects.create_from_ota_enrollment(
                es_request.enrollment_secret.ota_enrollment,
                self.serial_number, self.udid)

            payload = build_ota_scep_payload(ota_enrollment_session)
            filename = "zentral_ota_scep"

        elif phase == 3:
            # get the serial number from the DN of the payload signing certificate
            serial_number = signing_certificate.subject.get_attributes_for_oid(
                NameOID.SERIAL_NUMBER)[0].value
            if self.serial_number != serial_number:
                self.abort(
                    "signing certificate DN serial number != payload serial number",
                    phase=phase)

            # get the ota enrollment session from the DN of the payload signing certificate
            cn = signing_certificate.subject.get_attributes_for_oid(
                NameOID.COMMON_NAME)[0].value
            _, ota_enrollment_session_secret = cn.split("$")
            try:
                ota_enrollment_session = (
                    OTAEnrollmentSession.objects.select_for_update(
                    ).select_related("ota_enrollment",
                                     "enrollment_secret__meta_business_unit").
                    get(enrollment_secret__secret=ota_enrollment_session_secret
                        ))
            except OTAEnrollmentSession.DoesNotExist:
                self.abort(
                    "could not find ota enrollment session from payload signing certificate",
                    phase=phase)

            # verify and update ota enrollment session status
            try:
                ota_enrollment_session.set_phase3_status()
            except OTAEnrollmentSessionStatusError:
                self.abort("ota enrollment session has wrong status",
                           phase=phase)

            # verify DN mbu
            ota_enrollment_session_mbu = ota_enrollment_session.enrollment_secret.meta_business_unit
            o = signing_certificate.subject.get_attributes_for_oid(
                NameOID.ORGANIZATION_NAME)[0]
            if int(o.value.split("$")[-1]) != ota_enrollment_session_mbu.pk:
                self.abort("DN mbu doesn't match ota enrollment session mbu",
                           phase=phase)

            # Get the MDM push certificate
            push_certificate = ota_enrollment_session_mbu.metabusinessunitpushcertificate.push_certificate

            payload = build_mdm_payload(ota_enrollment_session,
                                        push_certificate)
            filename = "zentral_mdm"

        self.post_event("success", phase=phase)

        return build_payload_response(sign_payload_openssl(payload), filename)
        return HttpResponse()
Example #49
0
 def getpacket(self):
     resp, tag, payload = BinaryProtocol.getpacket(self)
     if resp != self.TYPE_PLIST:
         raise MuxError("Received non-plist type %d" % resp)
     payload = plistlib.loads(payload)
     return payload['MessageType'], tag, payload
Example #50
0
 def readPlistFromString(s):
     return loads(s, fmt=FMT_XML)
Example #51
0
def plist_from_bytes(byte_content):
    try:
        return plistlib.loads(byte_content)
    except AttributeError:
        return plistlib.readPlistFromString(byte_content)
Example #52
0
    async def __ipa_parse(file_path: str):
        """
        解析ipa包
        :param file_path: ipa路径
        :return: PackageParse
        """
        ipa_file = ZipFile(file_path)

        # 解析info.plist路径
        ns = [
            n for n in ipa_file.namelist() if Regex.IPAInfoPlistPath.match(n)
        ]
        if not ns:
            log.warning('parse info.plist failure: {}'.format(file_path))
            return
        plist_path = ns[-1]

        # 解析plist
        plist_data = ipa_file.read(plist_path)
        plist_file = plistlib.loads(plist_data)

        # 解析icon'CFBundleIconFiles' (4400546488)
        if plist_file.get('CFBundleIconFiles'):
            icon_name = plist_file['CFBundleIconFiles'][-1]
        else:
            if plist_file.get('CFBundleIcons'):
                icon_dict = plist_file['CFBundleIcons']
            elif plist_file.get('CFBundleIcons'):
                icon_dict = plist_file['CFBundleIcons~ipad']
            else:
                log.warning('parse icon failure: {}'.format(file_path))
                return
            icon_name = icon_dict['CFBundlePrimaryIcon']['CFBundleIconFiles'][
                -1]

        log.debug('parse icon name: {}'.format(icon_name))

        # 获取icon路径
        re_icon_name_end = '(@\dx)\.png' if not icon_name.endswith(
            '.png') else ''
        re_icon_name = re.compile('([^/]+/){{2}}{}{}'.format(
            icon_name, re_icon_name_end))
        ns = [n for n in ipa_file.namelist() if re_icon_name.match(n)]
        if not ns:
            log.warning('read icon failure: {}'.format(file_path))
            return
        icon_path = ns[-1]
        log.debug('parse icon path: {}'.format(icon_path))

        # 版本号
        version_number = plist_file['CFBundleShortVersionString']
        # build号
        build_number = plist_file['CFBundleVersion']
        # 包名
        package_name = plist_file['CFBundleIdentifier']
        # app名称
        app_name = plist_file['CFBundleDisplayName'] if plist_file.get(
            'CFBundleDisplayName') else plist_file['CFBundleName']
        log.debug('app: {}, V{} build {}, package: {}'.format(
            app_name, version_number, build_number, package_name))
        return PackageParse(ipa_file, AppType.iOS, package_name, app_name,
                            icon_path, version_number, build_number)
Example #53
0
def read_plist(s):
    if sys.version_info.major == 3:
        return plistlib.loads(s)
    else:
        return plistlib.readPlistFromString(s)
Example #54
0
    for plist in plist_files:
        # For each file, decode the plist and get data inside the <hash data> xml key
        #print("Parsing file {}".format(plist))
        with open(os.path.join(path, plist), 'rb') as f:
            parsed_data = plistlib.load(f)

        if not parsed_data:
            print("[-]Parsed data seems to be empty for file {}".format(
                os.path.join(path, plist)))
            continue

        if 'ShadowHashData' in parsed_data:
            account = plist.split('.plist')[0]
            print("Found ShadowHashData for account: {}".format(account))
            shadow_data = plistlib.loads(parsed_data['ShadowHashData'][0])
            #print(shadow_data)
            # Extract data related to keys: entropy, iterations and salt
            if 'SALTED-SHA512-PBKDF2' in shadow_data:
                iterations = shadow_data['SALTED-SHA512-PBKDF2']['iterations']
                salt = shadow_data['SALTED-SHA512-PBKDF2']['salt']
                entropy = shadow_data['SALTED-SHA512-PBKDF2']['entropy']
                if not (iterations and salt and entropy):
                    print("[-]Something is wrong, checkout logs")
                    continue
                salt = salt.hex()
                entropy = entropy.hex()

                res[account] = [iterations, salt, entropy]
            else:
                print(
Example #55
0
 def test_parse_file_reads_plist(self, _mock_file):
     """Parsing a PList file should produce a dictionary."""
     fake_prefs = Preferences()
     value = fake_prefs._parse_json_or_plist_file("fake_filepath")
     self.assertEqual(value, plistlib.loads(TEST_PLIST_PREFS))
    def make_mobileconfig_from_payload(
        self,
        payload_path,
        payload_identifier,
        mobileconfig_name,
        organization,
        description,
        mobileconfig_uuid,
    ):
        """create a mobileconfig file using a payload file"""
        # import plist as text and replace any substitutable keys
        with open(payload_path, "rb") as file:
            payload_text = file.read()
        # substitute user-assignable keys (requires decode to string)
        payload_text = self.substitute_assignable_keys((payload_text.decode()),
                                                       xml_escape=True)
        # now convert to data (requires encode back to bytes...)
        mcx_preferences = plistlib.loads(str.encode(payload_text))

        self.output("Preferences contents:", verbose_level=2)
        self.output(mcx_preferences, verbose_level=2)

        # generate a random UUID for the payload
        payload_uuid = str(uuid.uuid4())

        # add the other keys required in the payload
        payload_contents = {
            "PayloadDisplayName": "Custom Settings",
            "PayloadIdentifier": payload_uuid,
            "PayloadOrganization": "JAMF Software",
            "PayloadType": "com.apple.ManagedClient.preferences",
            "PayloadUUID": payload_uuid,
            "PayloadVersion": 1,
            "PayloadContent": {
                payload_identifier: {
                    "Forced": [{
                        "mcx_preference_settings": mcx_preferences
                    }]
                }
            },
        }

        self.output("Payload contents:", verbose_level=2)
        self.output(payload_contents, verbose_level=2)

        # now write the mobileconfig file
        mobileconfig_data = {
            "PayloadDescription": description,
            "PayloadDisplayName": mobileconfig_name,
            "PayloadOrganization": organization,
            "PayloadRemovalDisallowed": True,
            "PayloadScope": "System",
            "PayloadType": "Configuration",
            "PayloadVersion": 1,
            "PayloadIdentifier": mobileconfig_uuid,
            "PayloadUUID": mobileconfig_uuid,
            "PayloadContent": [payload_contents],
        }

        self.output("Converting config data to plist")
        mobileconfig_plist = plistlib.dumps(mobileconfig_data)

        self.output("Mobileconfig contents:", verbose_level=2)
        self.output(mobileconfig_plist.decode("UTF-8"), verbose_level=2)

        return mobileconfig_plist
Example #57
0
 def test_non_bmp_characters(self):
     pl = {'python': '\U0001f40d'}
     for fmt in ALL_FORMATS:
         with self.subTest(fmt=fmt):
             data = plistlib.dumps(pl, fmt=fmt)
             self.assertEqual(plistlib.loads(data), pl)
def plist_from_bytes(byte_content):
  if _PY3:
    return plistlib.loads(byte_content)
  else:
    return plistlib.readPlistFromString(byte_content)
Example #59
0
 def test_xml_plist_with_entity_decl(self):
     with self.assertRaisesRegex(
             plistlib.InvalidFileException,
             "XML entity declarations are not supported"):
         plistlib.loads(XML_PLIST_WITH_ENTITY, fmt=plistlib.FMT_XML)
Example #60
0
    def build_kext(self):
        empty_controllers = [c for c in self.controllers_historical if not any(p["selected"] for p in c["ports"])]
        response = None
        if empty_controllers:
            empty_menu = utils.TUIMenu(
                "Selection Validation",
                "Select an option: ",
                in_between=["The following controllers have no enabled ports:", ""]
                + [controller["name"] for controller in empty_controllers]
                + ["Select whether to ignore these controllers and exclude them from the map, or disable all ports on these controllers."],
                add_quit=False,
                return_number=True,
            )
            empty_menu.add_menu_option("Ignore", key="I")
            empty_menu.add_menu_option("Disable", key="D")
            response = empty_menu.start()

        model_identifier = None
        if self.settings["use_native"]:
            if platform.system() == "Darwin":
                model_identifier = plistlib.loads(subprocess.run("system_profiler -detailLevel mini -xml SPHardwareDataType".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.strip())[
                    0
                ]["_items"][0]["machine_model"]
            else:
                model_menu = utils.TUIOnlyPrint(
                    "Enter Model Identifier",
                    "Enter the model identifier: ",
                    [
                        "You are seeing this as you have selected to use AppleUSBHostController. Model identifier autodetection is unavailable as you are not on macOS.",
                        "Please enter the model identifier of the target system below. You can find it in System Information or with 'system_profiler -detailLevel mini SPHardwareDataType'.",
                    ],
                ).start()
                model_identifier = model_menu.strip()

        ignore = response == "I"

        template = plistlib.load((shared.resource_dir / Path("Info.plist")).open("rb"))

        menu = utils.TUIMenu("Building USBMap", "Select an option: ")
        menu.head()
        print("Generating Info.plist...")
        for controller in self.controllers_historical:
            if not any(i["selected"] for i in controller["ports"]) and ignore:
                continue

            # FIXME: ensure unique
            if controller["identifiers"].get("acpi_path"):
                if self.check_unique(lambda c: c["identifiers"]["acpi_path"].rpartition(".")[2], lambda c: "acpi_path" in c["identifiers"], controller):
                    personality_name: str = controller["identifiers"]["acpi_path"].rpartition(".")[2]
                else:
                    personality_name: str = controller["identifiers"]["acpi_path"][1:]  # Strip leading \
            elif controller["identifiers"].get("bdf"):
                personality_name: str = ":".join([str(i) for i in controller["identifiers"]["bdf"]])
            else:
                personality_name: str = controller["name"]

            if self.settings["use_native"]:
                personality = {
                    "CFBundleIdentifier": "com.apple.driver.AppleUSBHostMergeProperties",
                    "IOClass": "AppleUSBHostMergeProperties",
                    "IOProviderClass": "AppleUSBHostController",
                    "IOParentMatch": self.choose_matching_key(controller),
                    "model": model_identifier,
                }

            else:
                personality = {
                    "CFBundleIdentifier": "com.dhinakg.USBToolBox.kext",
                    "IOClass": "USBToolBox",
                    "IOProviderClass": "IOPCIDevice",
                    "IOMatchCategory": "USBToolBox",
                } | self.choose_matching_key(
                    controller
                )  # type: ignore

            personality["IOProviderMergeProperties"] = {"ports": {}, "port-count": None}

            port_name_index = {}
            highest_index = 0

            for port in controller["ports"]:
                if not port["selected"]:
                    continue

                if port["index"] > highest_index:
                    highest_index = port["index"]

                if controller["class"] == shared.USBControllerTypes.XHCI and port["class"] == shared.USBDeviceSpeeds.SuperSpeed:
                    prefix = "SS"
                elif controller["class"] == shared.USBControllerTypes.XHCI and port["class"] == shared.USBDeviceSpeeds.HighSpeed:
                    prefix = "HS"
                else:
                    prefix = "PRT"

                port_index = port_name_index.setdefault(prefix, 1)
                port_name = prefix + str(port_index).zfill(4 - len(prefix))
                port_name_index[prefix] += 1

                personality["IOProviderMergeProperties"]["ports"][port_name] = {
                    "port": binascii.a2b_hex(hexswap(hex(port["index"])[2:].zfill(8))),
                    "UsbConnector": port["type"] or port["guessed"],
                }

                if self.settings["add_comments_to_map"] and port["comment"]:
                    personality["IOProviderMergeProperties"]["ports"][port_name]["#comment"] = port["comment"]

            personality["IOProviderMergeProperties"]["port-count"] = binascii.a2b_hex(hexswap(hex(highest_index)[2:].zfill(8)))

            template["IOKitPersonalities"][personality_name] = personality

        if not self.settings["use_native"]:
            template["OSBundleLibraries"] = {"com.dhinakg.USBToolBox.kext": "1.0.0"}

        write_path = shared.current_dir / (Path("USBMap.kext") if self.settings["use_native"] else Path("UTBMap.kext"))

        if write_path.exists():
            print("Removing existing kext...")
            shutil.rmtree(write_path)

        print("Writing kext and Info.plist...")
        (write_path / Path("Contents")).mkdir(parents=True)
        plistlib.dump(template, (write_path / Path("Contents/Info.plist")).open("wb"), sort_keys=True)
        print(f"Done. Saved to {write_path.resolve()}.\n")
        menu.print_options()

        menu.select()
        return True