2016-09-12 01:21:14 +01:00
//
// Configure . m
// OverSight
//
// Created by Patrick Wardle on 9 / 01 / 16.
// Copyright ( c ) 2016 Objective - See . All rights reserved .
//
# import < Foundation / Foundation . h >
2016-10-09 06:34:31 +01:00
# import < ServiceManagement / ServiceManagement . h >
2016-09-12 01:21:14 +01:00
# import "Consts.h"
# import "Logging.h"
# import "Utilities.h"
# import "Configure.h"
@ implementation Configure
// invokes appropriate install || uninstall logic
- ( BOOL ) configure : ( NSUInteger ) parameter
{
// return var
BOOL wasConfigured = NO ;
2016-11-14 19:12:19 +00:00
2016-09-16 09:13:06 +01:00
// install
// -> starts on success
2016-09-12 01:21:14 +01:00
if ( ACTION_INSTALL _FLAG = = parameter )
{
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-09-12 01:21:14 +01:00
logMsg ( LOG_DEBUG , @ "installing..." ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-09-12 01:21:14 +01:00
// if already installed though
// -> uninstall everything first
if ( YES = = [ self isInstalled ] )
{
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-09-18 22:10:44 +01:00
logMsg ( LOG_DEBUG , @ "already installed, so stopping/uninstalling..." ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-09-18 22:10:44 +01:00
// stop
// -> kill login item / XPC service
[ self stop ] ;
2016-09-12 01:21:14 +01:00
// uninstall
2017-03-28 09:00:11 +01:00
// -> but do partial ( leave whitelist )
if ( YES ! = [ self uninstall : UNINSTALL_PARIAL ] )
2016-09-12 01:21:14 +01:00
{
// bail
goto bail ;
}
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-09-12 01:21:14 +01:00
logMsg ( LOG_DEBUG , @ "uninstalled" ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-09-12 01:21:14 +01:00
}
// install
if ( YES ! = [ self install ] )
{
2016-09-16 09:13:06 +01:00
// err msg
logMsg ( LOG_ERR , @ "installation failed" ) ;
2016-09-12 01:21:14 +01:00
// bail
goto bail ;
}
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-09-16 09:13:06 +01:00
logMsg ( LOG_DEBUG , @ "installed, now will start" ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-09-16 09:13:06 +01:00
// start login item
if ( YES ! = [ self start ] )
{
// err msg
logMsg ( LOG_ERR , @ "starting failed" ) ;
// bail
goto bail ;
}
2016-09-12 01:21:14 +01:00
}
2016-09-16 09:13:06 +01:00
// uninstall
// -> stops login item ( also w / stop XPC service )
2016-09-12 01:21:14 +01:00
else if ( ACTION_UNINSTALL _FLAG = = parameter )
{
2016-09-16 09:13:06 +01:00
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-09-16 09:13:06 +01:00
logMsg ( LOG_DEBUG , @ "stopping login item" ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-09-16 09:13:06 +01:00
2016-09-18 22:10:44 +01:00
// stop
// -> kill login item / XPC service
[ self stop ] ;
2016-09-16 09:13:06 +01:00
2016-09-12 01:21:14 +01:00
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-09-12 01:21:14 +01:00
logMsg ( LOG_DEBUG , @ "uninstalling..." ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-09-12 01:21:14 +01:00
// uninstall
2017-03-28 09:00:11 +01:00
if ( YES ! = [ self uninstall : UNINSTALL_FULL ] )
2016-09-12 01:21:14 +01:00
{
// bail
goto bail ;
}
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-09-12 01:21:14 +01:00
logMsg ( LOG_DEBUG , @ "uninstalled!" ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-09-12 01:21:14 +01:00
}
// no errors
wasConfigured = YES ;
// bail
bail :
return wasConfigured ;
}
// determine if installed
2016-09-16 09:13:06 +01:00
// -> simply checks if application exists in / Applications
2016-09-12 01:21:14 +01:00
- ( BOOL ) isInstalled
{
// check if extension exists
2016-09-15 09:15:30 +01:00
return [ [ NSFileManager defaultManager ] fileExistsAtPath : [ APPS_FOLDER stringByAppendingPathComponent : APP_NAME ] ] ;
2016-09-12 01:21:14 +01:00
}
// install
2016-09-15 09:15:30 +01:00
// a ) copy to / Applications
// b ) chown / chmod XPC component
2016-09-12 01:21:14 +01:00
- ( BOOL ) install
{
// return / status var
BOOL wasInstalled = NO ;
// error
NSError * error = nil ;
2016-09-15 09:15:30 +01:00
// path to app ( src )
NSString * appPathSrc = nil ;
2016-09-12 01:21:14 +01:00
2016-09-15 09:15:30 +01:00
// path to app ( dest )
NSString * appPathDest = nil ;
2016-09-12 01:21:14 +01:00
2016-09-16 09:13:06 +01:00
// path to XPC service
NSString * xpcServicePath = nil ;
2016-10-09 06:34:31 +01:00
// path to login item
NSString * loginItem = nil ;
2016-11-14 19:12:19 +00:00
// logged in user
NSString * user = nil ;
2016-09-12 01:21:14 +01:00
// set src path
// -> orginally stored in installer app ' s / Resource bundle
2016-09-15 09:15:30 +01:00
appPathSrc = [ [ [ NSBundle mainBundle ] resourcePath ] stringByAppendingPathComponent : APP_NAME ] ;
2016-09-12 01:21:14 +01:00
// set dest path
2016-09-15 09:15:30 +01:00
appPathDest = [ APPS_FOLDER stringByAppendingPathComponent : APP_NAME ] ;
2016-09-12 01:21:14 +01:00
2016-09-15 09:15:30 +01:00
// move app into / Applications
if ( YES ! = [ [ NSFileManager defaultManager ] copyItemAtPath : appPathSrc toPath : appPathDest error : & error ] )
2016-09-12 01:21:14 +01:00
{
// err msg
2016-09-15 09:15:30 +01:00
logMsg ( LOG_ERR , [ NSString stringWithFormat : @ "failed to copy %@ -> %@ (%@)" , appPathSrc , appPathDest , error ] ) ;
2016-09-12 01:21:14 +01:00
// bail
goto bail ;
}
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-09-15 09:15:30 +01:00
logMsg ( LOG_DEBUG , [ NSString stringWithFormat : @ "copied %@ -> %@" , appPathSrc , appPathDest ] ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-09-16 09:13:06 +01:00
2016-10-05 05:03:41 +01:00
// remove xattrs
// -> otherwise app translocation causes issues
execTask ( XATTR , @ [ @ "-cr" , appPathDest ] ) ;
2016-10-09 06:34:31 +01:00
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
logMsg ( LOG_DEBUG , @ "removed xattr" ) ;
# endif
2016-11-08 07:36:03 +00:00
2016-10-09 06:34:31 +01:00
// init path to login item
loginItem = [ appPathDest stringByAppendingPathComponent : @ "Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper" ] ;
2016-11-14 19:12:19 +00:00
// get user
user = loggedinUser ( ) ;
if ( nil = = user )
{
// err msg
logMsg ( LOG_ERR , @ "failed to determine logged-in user" ) ;
// bail
goto bail ;
}
2016-10-09 06:34:31 +01:00
// call into login item to install itself
2016-11-14 19:12:19 +00:00
// -> runs as logged in user , so can access user ' s login items , etc
2017-03-28 09:00:11 +01:00
execTask ( SUDO , @ [ @ "-u" , user , loginItem , [ NSString stringWithUTF8String : CMD_INSTALL ] ] ) ;
2016-10-09 06:34:31 +01:00
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-10-09 06:34:31 +01:00
logMsg ( LOG_DEBUG , [ NSString stringWithFormat : @ "persisted %@" , loginItem ] ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-10-09 06:34:31 +01:00
2016-09-16 09:13:06 +01:00
// init path to XPC service
xpcServicePath = [ appPathDest stringByAppendingPathComponent : @ "Contents/Library/LoginItems/OverSight Helper.app/Contents/XPCServices/OverSightXPC.xpc" ] ;
2016-09-12 01:21:14 +01:00
2016-09-16 09:13:06 +01:00
// set XPC service to be owned ; root : wheel
if ( YES ! = setFileOwner ( xpcServicePath , @ 0 , @ 0 , YES ) )
{
// err msg
logMsg ( LOG_ERR , [ NSString stringWithFormat : @ "failed to set file owner to root:wheel on %@" , xpcServicePath ] ) ;
// bail
goto bail ;
}
// set XPC service binary to setuid
if ( YES ! = setFilePermissions ( xpcServicePath , 06755 , YES ) )
{
// err msg
logMsg ( LOG_ERR , [ NSString stringWithFormat : @ "failed to set file permissions to 06755 on %@" , xpcServicePath ] ) ;
// bail
goto bail ;
}
2016-09-15 09:15:30 +01:00
2016-09-12 01:21:14 +01:00
// no error
wasInstalled = YES ;
// bail
bail :
return wasInstalled ;
}
2016-09-16 09:13:06 +01:00
// start
// -> just the login item
- ( BOOL ) start
{
// flag
BOOL bStarted = NO ;
// path to login item
NSString * loginItem = nil ;
2016-09-25 04:08:38 +01:00
// task
NSTask * task = nil ;
2016-09-16 09:13:06 +01:00
// init path
2016-09-25 04:08:38 +01:00
loginItem = [ [ APPS_FOLDER stringByAppendingPathComponent : APP_NAME ] stringByAppendingPathComponent : @ "Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper" ] ;
// alloc task
task = [ [ NSTask alloc ] init ] ;
// set path
[ task setLaunchPath : loginItem ] ;
// wrap task launch
@ try
{
// launch
[ task launch ] ;
}
@ catch ( NSException * exception )
2016-09-16 09:13:06 +01:00
{
// bail
goto bail ;
}
2016-09-25 04:08:38 +01:00
2016-09-16 09:13:06 +01:00
// happy
bStarted = YES ;
// bail
bail :
return bStarted ;
}
// stop
2016-09-18 22:10:44 +01:00
- ( void ) stop
2016-09-16 09:13:06 +01:00
{
// kill it
// pkill doesn ' t provide error info , so . . .
execTask ( PKILL , @ [ APP_HELPER _NAME ] ) ;
2016-09-18 22:10:44 +01:00
return ;
2016-09-16 09:13:06 +01:00
}
2016-09-12 01:21:14 +01:00
// uninstall
2016-09-16 09:13:06 +01:00
// -> delete app
2017-03-28 09:00:11 +01:00
- ( BOOL ) uninstall : ( NSUInteger ) type
2016-09-12 01:21:14 +01:00
{
// return / status var
BOOL wasUninstalled = NO ;
// status var
// -> since want to try all uninstall steps , but record if any fail
BOOL bAnyErrors = NO ;
2017-03-28 09:00:11 +01:00
// path to login item
NSString * loginItem = nil ;
// path to installed app
NSString * installedAppPath = nil ;
2016-09-12 01:21:14 +01:00
// error
NSError * error = nil ;
2016-10-09 06:34:31 +01:00
2016-11-14 19:12:19 +00:00
// logged in user
NSString * user = nil ;
2016-10-09 06:34:31 +01:00
// init path to login item
2017-03-28 09:00:11 +01:00
loginItem = [ [ [ [ NSBundle mainBundle ] resourcePath ] stringByAppendingPathComponent : APP_NAME ] stringByAppendingPathComponent : @ "Contents/Library/LoginItems/OverSight Helper.app/Contents/MacOS/OverSight Helper" ] ;
// init path to installed app
installedAppPath = [ APPS_FOLDER stringByAppendingPathComponent : APP_NAME ] ;
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2017-03-28 09:00:11 +01:00
logMsg ( LOG_DEBUG , @ "uninstalling login item" ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-10-09 06:34:31 +01:00
2016-11-14 19:12:19 +00:00
// get user
user = loggedinUser ( ) ;
if ( nil = = user )
{
// err msg
logMsg ( LOG_ERR , @ "failed to determine logged-in user" ) ;
// set flag
bAnyErrors = YES ;
// keep uninstalling . . .
}
2016-10-09 06:34:31 +01:00
2016-11-14 19:12:19 +00:00
// unistall login item
else
{
2017-03-28 09:00:11 +01:00
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2017-03-28 09:00:11 +01:00
logMsg ( LOG_DEBUG , [ NSString stringWithFormat : @ "telling login item %@, to uninstall itself" , loginItem ] ) ;
2017-04-03 00:12:42 +01:00
# endif
2017-03-28 09:00:11 +01:00
2016-11-14 19:12:19 +00:00
// call into login item to uninstall itself
// -> runs as logged in user , so can access user ' s login items , etc
2017-03-28 09:00:11 +01:00
execTask ( SUDO , @ [ @ "-u" , user , loginItem , [ NSString stringWithUTF8String : CMD_UNINSTALL ] ] ) ;
2016-11-14 19:12:19 +00:00
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2016-11-14 19:12:19 +00:00
logMsg ( LOG_DEBUG , [ NSString stringWithFormat : @ "unpersisted %@" , loginItem ] ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-11-14 19:12:19 +00:00
}
2017-03-28 09:00:11 +01:00
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
2017-03-28 09:00:11 +01:00
logMsg ( LOG_DEBUG , @ "deleting app" ) ;
2017-04-03 00:12:42 +01:00
# endif
2016-11-14 19:12:19 +00:00
2016-09-12 01:21:14 +01:00
// delete folder
2017-03-28 09:00:11 +01:00
if ( YES ! = [ [ NSFileManager defaultManager ] removeItemAtPath : installedAppPath error : & error ] )
2016-09-12 01:21:14 +01:00
{
// err msg
2017-03-28 09:00:11 +01:00
logMsg ( LOG_ERR , [ NSString stringWithFormat : @ "failed to delete app %@ (%@)" , installedAppPath , error ] ) ;
2016-09-12 01:21:14 +01:00
// set flag
bAnyErrors = YES ;
// keep uninstalling . . .
}
2017-03-28 09:00:11 +01:00
// full uninstall ?
// -> remove app support directory too
if ( UNINSTALL_FULL = = type )
{
// dbg msg
2017-04-03 00:12:42 +01:00
# ifdef DEBUG
logMsg ( LOG_DEBUG , @ "full uninstall, so also deleting app support directory" ) ;
# endif
2017-03-28 09:00:11 +01:00
// delete app support folder
if ( YES = = [ [ NSFileManager defaultManager ] fileExistsAtPath : [ APP_SUPPORT _DIRECTORY stringByExpandingTildeInPath ] ] )
{
// delete
if ( YES ! = [ self removeAppSupport ] )
{
// err msg
logMsg ( LOG_ERR , [ NSString stringWithFormat : @ "failed to delete app support directory %@" , APP_SUPPORT _DIRECTORY ] ) ;
// set flag
bAnyErrors = YES ;
// keep uninstalling . . .
}
}
}
2016-09-12 01:21:14 +01:00
// only success when there were no errors
if ( YES ! = bAnyErrors )
{
// happy
wasUninstalled = YES ;
}
return wasUninstalled ;
}
2017-03-28 09:00:11 +01:00
// remove ~ / Library / Application Support / Objective - See / OverSight
// and also ~ / Library / Application Support / Objective - See / if nothing else is in there ( no other products )
- ( BOOL ) removeAppSupport
{
// flag
BOOL removedDirectory = NO ;
// error
NSError * error = nil ;
// delete OverSight directory
if ( YES ! = [ [ NSFileManager defaultManager ] removeItemAtPath : [ APP_SUPPORT _DIRECTORY stringByExpandingTildeInPath ] error : & error ] )
{
// err msg
logMsg ( LOG_ERR , [ NSString stringWithFormat : @ "failed to delete OverSight's app support directory %@ (%@)" , APP_SUPPORT _DIRECTORY , error ] ) ;
// bail
goto bail ;
}
// anything left in ~ / Library / Application Support / Objective - See / ?
// -> nope : delete it
if ( 0 = = [ [ [ NSFileManager defaultManager ] contentsOfDirectoryAtPath : [ [ APP_SUPPORT _DIRECTORY stringByExpandingTildeInPath ] stringByDeletingLastPathComponent ] error : nil ] count ] )
{
if ( YES ! = [ [ NSFileManager defaultManager ] removeItemAtPath : [ [ APP_SUPPORT _DIRECTORY stringByExpandingTildeInPath ] stringByDeletingLastPathComponent ] error : & error ] )
{
// err msg
logMsg ( LOG_ERR , [ NSString stringWithFormat : @ "failed to delete Objective-See's app support directory %@ (%@)" , [ APP_SUPPORT _DIRECTORY stringByDeletingLastPathComponent ] , error ] ) ;
// bail
goto bail ;
}
}
// happy
removedDirectory = YES ;
// bail
bail :
return removedDirectory ;
}
2016-10-09 06:34:31 +01:00
2016-09-12 01:21:14 +01:00
@ end