Beispiel #1
0
 def testGetCoreStorageStateEnabled(self):
     self.mox.StubOutWithMock(util, 'GetPlistFromExec')
     pl = plistlib.readPlistFromString(CORE_STORAGE_PLIST_LIST_ENABLED)
     pl2 = plistlib.readPlistFromString(CORE_STORAGE_PLIST_LVF_INFO_ENABLED)
     util.GetPlistFromExec(mox.In(DISKUTIL)).AndReturn(pl)
     util.GetPlistFromExec(mox.In(DISKUTIL)).AndReturn(pl2)
     self.mox.ReplayAll()
     self.assertEquals(corestorage.GetState(), corestorage.State.enabled)
     self.mox.VerifyAll()
Beispiel #2
0
def GetStateAndVolumeIds():
    """Determine the state of core storage and the volume IDs (if any).

  In the case that core storage is enabled, it is required that every present
  volume is encrypted, to return "encrypted" status (i.e. the entire drive is
  encrypted, for all present drives).  Otherwise only "enabled" status is
  returned.

  Returns:
    tuple: (State, [list; str encrypted UUIDs], [list; str unencrypted UUIDs])
  Raises:
    Error: there was a problem getting the corestorage list, or family info.
  """
    try:
        cs_plist = util.GetPlistFromExec(
            (DISKUTIL, 'corestorage', 'list', '-plist'))
    except util.ExecError:
        logging.exception(
            'GetStateAndVolumeIds() failed to get corestorage list.')
        raise Error

    state = State.none
    volume_ids = []
    encrypted_volume_ids = []

    groups = cs_plist.get('CoreStorageLogicalVolumeGroups', [])
    if groups:
        state = State.enabled
    for group in groups:
        for family in group.get('CoreStorageLogicalVolumeFamilies', []):
            family_id = family['CoreStorageUUID']
            if not util.UuidIsValid(family_id):
                continue
            try:
                info_plist = util.GetPlistFromExec(
                    (DISKUTIL, 'corestorage', 'info', '-plist', family_id))
            except util.ExecError:
                logging.exception(
                    'GetStateAndVolumeIds() failed to get corestorage family info: %s',
                    family_id)
                raise Error
            enc = info_plist.get(
                'CoreStorageLogicalVolumeFamilyEncryptionType', '')

            for volume in family['CoreStorageLogicalVolumes']:
                volume_id = volume['CoreStorageUUID']
                if enc == 'AES-XTS':
                    encrypted_volume_ids.append(volume_id)
                else:
                    volume_ids.append(volume_id)
    if encrypted_volume_ids and not volume_ids:
        state = State.encrypted
    return state, encrypted_volume_ids, volume_ids
Beispiel #3
0
 def testGetCoreStorageStateFailed(self):
     self.mox.StubOutWithMock(util, 'GetPlistFromExec')
     pl = plistlib.readPlistFromString(CORE_STORAGE_PLIST_LIST_ENABLED)
     pl2 = plistlib.readPlistFromString(CORE_STORAGE_PLIST_LVF_INFO_ENABLED)
     pl3 = plistlib.readPlistFromString(CORE_STORAGE_PLIST_LV_INFO)
     pl3['CoreStorageLogicalVolumeConversionState'] = 'Failed'
     util.GetPlistFromExec(mox.In(DISKUTIL)).AndReturn(pl)
     util.GetPlistFromExec(mox.In(DISKUTIL)).AndReturn(pl2)
     util.GetPlistFromExec(mox.In(DISKUTIL)).AndReturn(pl3)
     self.mox.ReplayAll()
     self.assertEquals(corestorage.GetState(), corestorage.State.FAILED)
     self.mox.VerifyAll()
Beispiel #4
0
 def testGetRecoveryPartition(self):
     self.mox.StubOutWithMock(util, 'GetPlistFromExec')
     pl = plistlib.readPlistFromString(DISKUTIL_LIST_PLIST)
     util.GetPlistFromExec(mox.In(DISKUTIL)).AndReturn(pl)
     self.mox.ReplayAll()
     self.assertEquals(corestorage.GetRecoveryPartition(), '/dev/disk0s3')
     self.mox.VerifyAll()
Beispiel #5
0
 def testGetRecoveryPartitionWhenDiskutilFail(self):
     self.mox.StubOutWithMock(util, 'GetPlistFromExec')
     util.GetPlistFromExec(mox.In(DISKUTIL)).AndRaise(
         corestorage.util.ExecError)
     self.mox.ReplayAll()
     self.assertEquals(corestorage.GetRecoveryPartition(), None)
     self.mox.VerifyAll()
Beispiel #6
0
 def testGetCoreStorageStateNone(self):
     self.mox.StubOutWithMock(util, 'GetPlistFromExec')
     pl = plistlib.readPlistFromString(CORE_STORAGE_PLIST_LIST_EMPTY)
     util.GetPlistFromExec(mox.In(DISKUTIL)).AndReturn(pl)
     self.mox.ReplayAll()
     self.assertEquals(corestorage.GetState(), corestorage.State.NONE)
     self.mox.VerifyAll()
Beispiel #7
0
def UpdateEscrowPassphrase(password):
    """Change the FileVault2 recovery key.

  Under CoreStorage, the current recovery key could be used as the password to
  fdesetup, but this does not work with APFS.  Since the user password works in
  both cases and we already require it for sudo, we simply default to that.

  Args:
    password: the user password.
  Returns:
    The new recovery key.
  """
    command = ('sudo', '-k', '-S', FDESETUP_PATH, 'changerecovery',
               '-personal', '-outputplist', '-inputplist')

    stdin = plistlib.writePlistToString({'Password': password})
    if os.getuid() != 0:
        stdin = '%s\n%s' % (password, stdin)

    try:
        result_plist = util.GetPlistFromExec(command, stdin=stdin)
    except util.ExecError as e:
        logging.error(e.stderr)
        raise Error(e.message)

    recovery_key = result_plist.get('RecoveryKey')
    return recovery_key
Beispiel #8
0
def GetVolumeSize(uuid, readable=True):
    """Return the size of the volume with the given UUID.

  Args:
    uuid: str, ID of the volume in question
    readable: Optional boolean, default true: return a human-readable string
      when true, otherwise int number of bytes.

  Returns:
    str or int, see "readable" arg.
  Raises:
    Error: there was a problem getting volume info.
    ValueError: The UUID is formatted incorrectly.
  """
    if not util.UuidIsValid(uuid):
        raise ValueError('Invalid UUID: ' + uuid)
    try:
        plist = util.GetPlistFromExec(
            (DISKUTIL, 'corestorage', 'info', '-plist', uuid))
    except util.ExecError:
        logging.exception('GetVolumeSize() failed to get volume info: %s',
                          uuid)
        raise Error

    num_bytes = plist['CoreStorageLogicalVolumeSize']
    if readable:
        return '%.2f GiB' % (num_bytes / (1 << 30))
    else:
        return num_bytes
Beispiel #9
0
def GetFilesystemType():
    try:
        plist = util.GetPlistFromExec((DISKUTIL, 'info', '-plist', '/'))
    except util.ExecError:
        logging.error('FilesystemType lookup failed.  Defaulting to hfs')
        return 'hfs'
    fstype = plist.get('FilesystemType', None)
    return fstype
Beispiel #10
0
 def GetPrimaryVolumeUUID(self):
     """Returns string UUID of the boot volume (/), or None if error."""
     cmd = [DISKUTIL, 'info', '-plist', '/']
     try:
         plist = util.GetPlistFromExec(cmd)
     except util.ExecError:
         return None
     return plist.get('VolumeUUID')
Beispiel #11
0
def IsBootVolumeEncrypted():
    """Returns True if the boot volume (/) is encrypted, False otherwise."""
    try:
        csinfo_plist = util.GetPlistFromExec(
            (DISKUTIL, 'cs', 'info', '-plist', '/'))
    except util.ExecError:
        return False  # Non-zero return means / volume isn't a CoreStorage volume.

    lvf_uuid = csinfo_plist.get('MemberOfCoreStorageLogicalVolumeFamily')
    if lvf_uuid:
        try:
            lvf_info_plist = util.GetPlistFromExec(
                (DISKUTIL, 'cs', 'info', '-plist', lvf_uuid))
        except util.ExecError:
            return False  # Couldn't get info on Logical Volume Family UUID.
        return lvf_info_plist.get(
            'CoreStorageLogicalVolumeFamilyEncryptionType') == 'AES-XTS'

    return False
Beispiel #12
0
    def testGetPlistFromExec(self):
        self.mox.StubOutWithMock(util, 'Exec')
        self.mox.StubOutWithMock(util.plistlib, 'readPlistFromString')

        util.Exec('cmd', stdin='stdin').AndReturn((0, 'stdout', 'stderr'))
        util.plistlib.readPlistFromString('stdout').AndReturn('plist')

        self.mox.ReplayAll()
        self.assertEqual('plist', util.GetPlistFromExec('cmd', stdin='stdin'))
        self.mox.VerifyAll()
Beispiel #13
0
    def EnableEncryption(self):
        """Enable full disk encryption.

    Returns:
      A 2-tuple containing the encrypted volume's UUID, and the recovery token.
    """
        try:
            result_plist = util.GetPlistFromExec(self._GetCommand(),
                                                 stdin=self._GetStdin())
        except util.ExecError as e:
            self._HandleFailure(e)
        return self._HandleResult(result_plist)
Beispiel #14
0
def UpdateEscrowPassphrase(password, passphrase):
    """Change recovery passphrase."""
    command = ('sudo', '-k', '-S', FDESETUP_PATH, 'changerecovery',
               '-personal', '-outputplist', '-inputplist')

    stdin = plistlib.writePlistToString({'Password': passphrase})
    if os.getuid() != 0:
        stdin = '%s\n%s' % (password, stdin)

    try:
        result_plist = util.GetPlistFromExec(command, stdin=stdin)
    except util.ExecError as e:
        logging.error(e.stderr)
        raise Error(e.message)

    recovery_key = result_plist.get('RecoveryKey')
    return recovery_key
Beispiel #15
0
    def _GetAPFSVolumesAndContainers(self, uuid=None, disk=None):
        """Returns a tuple of volumes and containers from apfs list -plist.

    Args:
      uuid: str, optional, APFSVolume uuid. If no uuid is provided, this
            function returns a diskutil apfs list plist..
      disk: str, optional, name of the disk to look at.
    Returns:
      A dict of diskutil cs info/list -plist output.
    Raises:
      Error: The given uuid was invalid or there was a diskutil error.
    """
        if uuid:
            if not util.UuidIsValid(uuid):
                raise storage.Error

        if disk or not self._containers:
            cmd = [DISKUTIL, 'apfs', 'list', '-plist']
            if disk:
                cmd.append(disk)
            try:
                plist = util.GetPlistFromExec(cmd)
            except util.ExecError:
                return ([], [])
            containers = plist.get('Containers', [])
            if containers:
                volumes = containers[0].get('Volumes', [])
            else:
                volumes = []

            if not disk:  # save the full list for future lookups
                self._containers = containers
                self._volumes = volumes
        else:
            containers = self._containers
            volumes = self._volumes

        if uuid:
            uuid_volumes = []
            for volume in volumes:
                if volume.get('APFSVolumeUUID') == uuid:
                    uuid_volumes.append(volume)
            return (uuid_volumes, containers)
        else:
            return (volumes, containers)
def GetRecoveryPartition():
    """Determine the location of the recovery partition.

  Returns:
    str, like "/dev/disk0s3" where the recovery partition is, OR
    None, if no recovery partition exists or cannot be detected.
  """
    try:
        disklist_plist = util.GetPlistFromExec((DISKUTIL, 'list', '-plist'))
    except util.ExecError:
        logging.exception(
            'GetRecoveryPartition() failed to get partition list.')
        return

    alldisks = disklist_plist.get('AllDisksAndPartitions', [])
    for disk in alldisks:
        partitions = disk.get('Partitions', [])
        for partition in partitions:
            if partition.get('VolumeName') == 'Recovery HD':
                return '/dev/%s' % partition['DeviceIdentifier']
def GetCoreStoragePlist(uuid=None):
    """Returns a dict of diskutil cs info plist for a given str CoreStorage uuid.

  Args:
    uuid: str, optional, CoreStorage uuid. If no uuid is provided, this function
          returns a diskutil cs list plist..
  Returns:
    A dict of diskutil cs info/list -plist output.
  Raises:
    Error: The given uuid was invalid or there was a diskutil error.
  """
    if uuid:
        if not util.UuidIsValid(uuid):
            raise Error
        cmd = [DISKUTIL, 'corestorage', 'info', '-plist', uuid]
    else:
        cmd = [DISKUTIL, 'corestorage', 'list', '-plist']
    try:
        return util.GetPlistFromExec(cmd)
    except util.ExecError:
        raise Error
Beispiel #18
0
    """Base class for all errors raised by options."""


def ApplyEncryption(fvclient, username, password):
    """Turn encryption on."""

    # Supply entropy to the system before csfde uses /dev/random.
    try:
        entropy = util.RetrieveEntropy()
        util.SupplyEntropy(entropy)
    except util.EntropyError, e:
        raise Error('Entropy operations failed: %s' % str(e))

    root_disk = util.GetRootDisk()
    try:
        csfde_plist = util.GetPlistFromExec(
            (CSFDE_PATH, root_disk, username, '-'), stdin=password)
    except util.ExecError, e:
        if e.returncode == CSFDE_RETURN_AUTH_FAIL:
            raise InputError(
                'Authentication problem with local account.  Drive NOT encrypted.'
            )
        elif e.returncode != 0:
            logging.error('csfde failed with stderr:\n%s', e.stderr)
            raise Error('Problem running csfde (exit status = %d)' %
                        e.returncode)
        else:
            logging.exception('Problem running csfde.')
            raise Error('Problem running csfde', e)
    fvclient.SetOwner(username)

    return GetEncryptionResults(csfde_plist)
Beispiel #19
0
    def testGetPlistFromExec(self, exec_mock, read_plist_mock):
        self.assertEqual('plist', util.GetPlistFromExec('cmd', stdin='stdin'))

        exec_mock.assert_called_once_with('cmd', stdin='stdin')
        read_plist_mock.assert_called_once_with('stdout')