def testOk(self): mock_passphrase = 'random keychain passphrase' mock_full_keychain = self.mox.CreateMockAnything() mock_full_keychain_file = self.mox.CreateMockAnything() mock_pub_keychain = self.mox.CreateMockAnything() mock_pub_keychain_file = self.mox.CreateMockAnything() open_ = self.mox.CreateMockAnything() self.mox.StubOutWithMock(base64, 'b32encode') self.mox.StubOutWithMock(util, 'Exec') self.mox.StubOutWithMock(keychain, 'Remove') base64.b32encode(mox.IsA(basestring)).AndReturn(mock_passphrase) util.Exec(mox.In('/usr/bin/certtool'), mox.IsA(basestring)).AndReturn( (0, '', '')) open_(mox.IsA(basestring), 'r').AndReturn(mock_full_keychain_file) mock_full_keychain_file.read().AndReturn(mock_full_keychain) keychain.Remove() util.Exec(mox.In('/usr/bin/security')).AndReturn((0, '', '')) util.Exec(mox.In('/usr/bin/certtool')).AndReturn((0, '', '')) open_(mox.IsA(basestring), 'r').AndReturn(mock_pub_keychain_file) mock_pub_keychain_file.read().AndReturn(mock_pub_keychain) mox.Replay(open_) self.mox.ReplayAll() self.assertEquals( (mock_pub_keychain, mock_full_keychain, mock_passphrase), keychain.Create(open_=open_)) self.mox.VerifyAll() mox.Verify(open_)
def __init__(self, server_url): self.server_url = server_url # This is the top-level container that is destroyed and recreated to # "switch pages". See _PrepTop(). self.top_frame = None self.username = pwd.getpwuid(os.getuid()).pw_name # current user name self.password = None self.root = Tkinter.Tk() self.root.title('CauliflowerVest') # Set our fixed size, and center on the screen. self.root.geometry('%dx%d+%d+%d' % ( self.WIDTH, self.HEIGHT, self.root.winfo_screenwidth() / 2 - self.WIDTH / 2, self.root.winfo_screenheight() / 2 - self.HEIGHT / 2, )) # Override Tk's default error handling. self.root.report_callback_exception = ( lambda _1, exc, *_2, **_3: self.ShowFatalError(exc)) # Lame hack around OSX focus issue. http://goo.gl/9U0Vg util.Exec( ('/usr/bin/osascript', '-e', 'tell app "Finder" to set frontmost of process "Python" to true')) self.top_frame = None
def testOutOfOrder(self): self.mox.StubOutWithMock(util, 'Exec') util.Exec(('/sbin/mount')).AndReturn( (0, MOUNT_OUTPUT_OUT_OF_ORDER, '')) self.mox.ReplayAll() self.assertEquals('/dev/disk0s2', util.GetRootDisk()) self.mox.VerifyAll()
def testTrailingBlank(self): self.mox.StubOutWithMock(util, 'Exec') util.Exec(('/sbin/mount')).AndReturn( (0, MOUNT_OUTPUT_TRAILING_BLANK, '')) self.mox.ReplayAll() self.assertRaises(util.Error, util.GetRootDisk) self.mox.VerifyAll()
def testGetPlistFromExecNonZeroReturncode(self): self.mox.StubOutWithMock(util, 'Exec') util.Exec('cmd', stdin=None).AndReturn((1, 'stdout', 'stderr')) self.mox.ReplayAll() self.assertRaises(util.ExecError, util.GetPlistFromExec, 'cmd') self.mox.VerifyAll()
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()
def testGetPlistFromExecPlistParseError(self): self.mox.StubOutWithMock(util, 'Exec') self.mox.StubOutWithMock(util.plistlib, 'readPlistFromString') util.Exec('cmd', stdin=None).AndReturn((0, 'stdout', 'stderr')) util.plistlib.readPlistFromString('stdout').AndRaise( util.expat.ExpatError) self.mox.ReplayAll() self.assertRaises(util.ExecError, util.GetPlistFromExec, 'cmd') self.mox.VerifyAll()
def testRetrieveEntropyWhenNoOutputResult(self): self.mox.StubOutWithMock(util, 'Exec') rc = 0 stdout = 'CrapThatWontMatchTheRegex\n' stderr = '' util.Exec(['/usr/sbin/ioreg', '-l']).AndReturn((rc, stdout, stderr)) self.mox.ReplayAll() self.assertRaises(util.RetrieveEntropyError, util.RetrieveEntropy) self.mox.VerifyAll()
def testRetrieveEntropyWhenErrorIoRegExec(self): self.mox.StubOutWithMock(util, 'Exec') rc = 1 stdout = '' stderr = '' util.Exec(['/usr/sbin/ioreg', '-l']).AndRaise(util.ExecError) self.mox.ReplayAll() self.assertRaises(util.RetrieveEntropyError, util.RetrieveEntropy) self.mox.VerifyAll()
def Remove(): """Ensure that no pre-existing keychain is used, by removing it. Raises: AssertionError: For all exception cases. """ # TODO(user): Ensure that this "securely" deletes the sensitive data. returncode, unused_stdout, unused_stderr = util.Exec( ('/usr/bin/security', 'delete-keychain', KEYCHAIN_PATH)) # Error code 50 is file did not exist. assert returncode in (0, 50), ('Could not remove old keychain (%s).' % returncode)
def Create(open_=open): """Create a keychain that FileVault will use for disk encryption. Args: open_: Callable, dependency injection for "open" builtin. Returns: Tuple of blobs, (pub_only_keychain, full_keychain, passphrase). Raises: AssertionError: For all exception cases. """ # Input to send to create a compliant keychain. script = '\n'.join( ('FileVault Recovery Key', 'r', '1024', 'y', 'b', 's', 'y', 'FileVault Recovery Key', '', '', '', '', '', 'y', '')) # 160 cryptographically random bits, encoded with 32 printable characters. passphrase = base64.b32encode(os.urandom(20)) # Create the full keychain (pub + priv), and (pub) cert file. returncode, unused_stdout, unused_stderr = util.Exec( ('/usr/bin/certtool', 'c', 'c', 'k=' + KEYCHAIN_PATH, 'o=%s.pem' % KEYCHAIN_PATH, 'a', 'p=' + passphrase), script) assert returncode == 0, 'Could not create full keychain (%s).' % returncode # Get that data, and remove the keychain, to ... full_keychain = open_(KEYCHAIN_PATH, 'r').read() Remove() # ... replace it with the public-key-only version. returncode, unused_stdout, unused_stderr = util.Exec( ('/usr/bin/security', 'create-keychain', '-p', passphrase, KEYCHAIN_PATH)) assert returncode == 0, 'Could not create pub keychain (%s).' % returncode returncode, unused_stdout, unused_stderr = util.Exec( ('/usr/bin/certtool', 'i', KEYCHAIN_PATH + '.pem', 'k=' + KEYCHAIN_PATH)) assert returncode == 0, 'Could not import pub keychain (%s).' % returncode pub_only_keychain = open_(KEYCHAIN_PATH, 'r').read() return pub_only_keychain, full_keychain, passphrase
def testRetrieveEntropy(self): self.mox.StubOutWithMock(util, 'Exec') rc = 0 stdout = 'HIDIdleTime=100\nWhateverOtherCrap\n' stderr = '' expected_entropy = 'HIDIdleTime=100' util.Exec(['/usr/sbin/ioreg', '-l']).AndReturn((rc, stdout, stderr)) self.mox.ReplayAll() self.assertEqual(expected_entropy, util.RetrieveEntropy()) self.mox.VerifyAll()
def UnlockVolume(uuid, passphrase): """Unlock a core storage encrypted volume. Args: uuid: str, uuid of the volume to unlock. passphrase: str, passphrase to unlock the volume. Raises: CouldNotUnlockError: the volume cannot be unlocked. ValueError: The UUID is formatted incorrectly. """ if not util.UuidIsValid(uuid): raise ValueError('Invalid UUID: ' + uuid) returncode, _, stderr = util.Exec( (DISKUTIL, 'corestorage', 'unlockVolume', uuid, '-stdinpassphrase'), stdin=passphrase) if returncode != 0 and not 'volume is not locked' in stderr: raise CouldNotUnlockError('Could not unlock volume (%s).' % returncode)
def RevertVolume(uuid, passphrase): """Revert a core storage encrypted volume (to unencrypted state). Args: uuid: str, uuid of the volume to revert. passphrase: str, passphrase to unlock the volume. Raises: CouldNotRevertError: the volume was unlocked, but cannot be reverted. CouldNotUnlockError: the volume cannot be unlocked. ValueError: The UUID is formatted incorrectly. """ if not util.UuidIsValid(uuid): raise ValueError('Invalid UUID: ' + uuid) UnlockVolume(uuid, passphrase) returncode, _, _ = util.Exec( (DISKUTIL, 'corestorage', 'revert', uuid, '-stdinpassphrase'), stdin=passphrase) if returncode != 0: raise CouldNotRevertError('Could not revert volume (%s).' % returncode)
def UnlockVolume(self, uuid, passphrase): """Unlock an APFS encrypted volume. Args: uuid: str, uuid of the volume to unlock. passphrase: str, passphrase to unlock the volume. Raises: CouldNotUnlockError: the volume cannot be unlocked. InvalidUUIDError: The UUID is formatted incorrectly. """ if not util.UuidIsValid(uuid): raise storage.InvalidUUIDError('Invalid UUID: ' + uuid) returncode, _, stderr = util.Exec( (DISKUTIL, 'apfs', 'unlockVolume', uuid, '-stdinpassphrase'), stdin=passphrase) if (returncode != 0 and 'volume is not locked' not in stderr and 'is already unlocked' not in stderr): raise storage.CouldNotUnlockError('Could not unlock volume (%s).' % returncode)
def RevertVolume(self, uuid, passphrase, passwd=''): """Disable encryption on an APFS system. Args: uuid: str, uuid of the volume to revert. passphrase: str, passphrase to unlock the volume. passwd: str, password for sudo Raises: CouldNotRevertError: the volume was unlocked, but cannot be reverted. CouldNotUnlockError: the volume cannot be unlocked. InvalidUUIDError: The UUID is formatted incorrectly. """ if not util.UuidIsValid(uuid): raise storage.InvalidUUIDError('Invalid UUID: ' + uuid) self.UnlockVolume(uuid, passphrase) returncode, _, _ = util.Exec(('sudo', '-k', '-S', FDESETUP, 'disable'), stdin=passwd + '\n') if returncode != 0: raise storage.CouldNotRevertError( 'Could not disable encryption (%s).' % (returncode))
def testException(self): self.mox.StubOutWithMock(util, 'Exec') util.Exec(('/sbin/mount')).AndRaise(util.ExecError) self.mox.ReplayAll() self.assertRaises(util.Error, util.GetRootDisk) self.mox.VerifyAll()
def testEnumerationFailure(self): self.mox.StubOutWithMock(util, 'Exec') util.Exec(('/sbin/mount')).AndReturn((1, '', '')) self.mox.ReplayAll() self.assertRaises(util.Error, util.GetRootDisk) self.mox.VerifyAll()
def testOk(self): self.mox.StubOutWithMock(util, 'Exec') util.Exec(mox.In('/usr/bin/security')).AndReturn((0, '', '')) self.mox.ReplayAll() keychain.Remove() self.mox.VerifyAll()
def testPermissionDenied(self): self.mox.StubOutWithMock(util, 'Exec') util.Exec(mox.In('/usr/bin/security')).AndReturn((173, '', '')) self.mox.ReplayAll() self.assertRaises(AssertionError, keychain.Remove) self.mox.VerifyAll()