started on install/uninstall logic (as root, etc)

TODOs/code cleanup
This commit is contained in:
Patrick Wardle 2016-09-14 22:15:30 -10:00
parent 5173869913
commit d14d33fbd1
11 changed files with 287 additions and 87 deletions

View File

@ -54,6 +54,7 @@
7D17C5031D658DEC0066232A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Installer/Base.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
7D24C8651D2CDEA7009932EE /* Installer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Installer.app; sourceTree = BUILT_PRODUCTS_DIR; };
7D6245821D87C3D700870565 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Images/Images.xcassets; sourceTree = "<group>"; };
7D9A7DE91D8A8BDA0091C1AF /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = main.h; path = Installer/main.h; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -117,6 +118,7 @@
children = (
7D17C5021D658DEC0066232A /* MainMenu.xib */,
7D17C4EC1D658DB90066232A /* Configure.m */,
7D17C4F61D658DB90066232A /* AppDelegate.h */,
7D17C4ED1D658DB90066232A /* AppDelegate.m */,
7D17C4EE1D658DB90066232A /* ConfigureWindowController.m */,
7D17C4EF1D658DB90066232A /* ConfigureWindowController.xib */,
@ -124,7 +126,6 @@
7D17C4F11D658DB90066232A /* ConfigureWindowController.h */,
7D17C4F21D658DB90066232A /* ErrorWindowController.h */,
7D17C4F31D658DB90066232A /* ErrorWindowController.m */,
7D17C4F61D658DB90066232A /* AppDelegate.h */,
7D17C4F81D658DB90066232A /* ErrorWindowController.xib */,
7D24C86B1D2CDEA7009932EE /* Supporting Files */,
);
@ -137,6 +138,7 @@
children = (
7D17C4F51D658DB90066232A /* Info.plist */,
7D17C4F41D658DB90066232A /* main.m */,
7D9A7DE91D8A8BDA0091C1AF /* main.h */,
);
name = "Supporting Files";
sourceTree = "<group>";

View File

@ -87,14 +87,13 @@ bail:
-(BOOL)isInstalled
{
//check if extension exists
return [[NSFileManager defaultManager] fileExistsAtPath:[[EXTENSION_FOLDER stringByExpandingTildeInPath] stringByAppendingPathComponent:EXTENSION_NAME]];
return [[NSFileManager defaultManager] fileExistsAtPath:[APPS_FOLDER stringByAppendingPathComponent:APP_NAME]];
}
//install
// a) create and copy extension to ~/Library/WhatsYourSign
// b) add extension: 'pluginkit -a /path/2/WhatsYourSign.appex'
// c) enable extension: 'pluginkit -e use -i com.objective-see.WhatsYourSignExt.FinderSync'
// a) copy to /Applications
// b) chown/chmod XPC component
-(BOOL)install
{
//return/status var
@ -103,76 +102,35 @@ bail:
//error
NSError* error = nil;
//path to finder sync (src)
NSString* extensionPathSrc = nil;
//path to app (src)
NSString* appPathSrc = nil;
//path to finder sync (dest)
NSString* extensionPathDest = nil;
//path to app (dest)
NSString* appPathDest = nil;
//results from 'pluginkit' cmd
NSData* results = nil;
//set src path
// ->orginally stored in installer app's /Resource bundle
extensionPathSrc = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:EXTENSION_NAME];
appPathSrc = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:APP_NAME];
//set dest path
extensionPathDest = [[EXTENSION_FOLDER stringByExpandingTildeInPath] stringByAppendingPathComponent:EXTENSION_NAME];
appPathDest = [APPS_FOLDER stringByAppendingPathComponent:APP_NAME];
//check if extension folder needs to be created
if(YES != [[NSFileManager defaultManager] fileExistsAtPath:[EXTENSION_FOLDER stringByExpandingTildeInPath]])
{
//create it
if(YES != [[NSFileManager defaultManager] createDirectoryAtPath:[EXTENSION_FOLDER stringByExpandingTildeInPath] withIntermediateDirectories:YES attributes:nil error:&error])
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to create extension's directory %@ (%@)", EXTENSION_FOLDER, error]);
//bail
goto bail;
}
}
//move extension into persistent location
// ->'/Library/WhatsYourSign/' + extension name
if(YES != [[NSFileManager defaultManager] copyItemAtPath:extensionPathSrc toPath:extensionPathDest error:&error])
//move app into /Applications
if(YES != [[NSFileManager defaultManager] copyItemAtPath:appPathSrc toPath:appPathDest error:&error])
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to copy %@ -> %@ (%@)", extensionPathSrc, extensionPathDest, error]);
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to copy %@ -> %@ (%@)", appPathSrc, appPathDest, error]);
//bail
goto bail;
}
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"copied %@ -> %@", extensionPathSrc, extensionPathDest]);
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"copied %@ -> %@", appPathSrc, appPathDest]);
//always set group/owner to root/wheel
setFileOwner(appPathDest, @0, @0, YES);
//install extension via 'pluginkit -a <path 2 ext>
results = execTask(PLUGIN_KIT, @[@"-a", extensionPathDest]);
if(0 != results.length)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"pluginkit failed to install extension (%@)", [[NSString alloc] initWithData:results encoding:NSUTF8StringEncoding]]);
//bail
goto bail;
}
//nap
// ->VM sometimes didn't enable
[NSThread sleepForTimeInterval:0.5];
//enable extension via 'pluginkit -e use -i <ext bundle id>
results = execTask(PLUGIN_KIT, @[@"-e", @"use", @"-i", EXTENSION_BUNDLE_ID]);
if(0 != results.length)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"pluginkit failed to enable extension (%@)", [[NSString alloc] initWithData:results encoding:NSUTF8StringEncoding]]);
//bail
goto bail;
}
//no error
wasInstalled = YES;
@ -195,23 +153,19 @@ bail:
BOOL bAnyErrors = NO;
//path to finder sync
NSString* extensionPath = nil;
NSString* appPath = nil;
//error
NSError* error = nil;
//init path
extensionPath = [[EXTENSION_FOLDER stringByExpandingTildeInPath] stringByAppendingPathComponent:EXTENSION_NAME];
appPath = [APPS_FOLDER stringByAppendingPathComponent:APP_NAME];
//this always seem to 'fail' with 'remove: no plugin at <path/2/FinderSync.appex>'
// ->but yet works, so just ignore any return from this invocation of execTask()
execTask(PLUGIN_KIT, @[@"-r", extensionPath]);
//delete folder
if(YES != [[NSFileManager defaultManager] removeItemAtPath:[EXTENSION_FOLDER stringByExpandingTildeInPath] error:&error])
if(YES != [[NSFileManager defaultManager] removeItemAtPath:appPath error:&error])
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to delete extension directory %@ (%@)", EXTENSION_FOLDER, error]);
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to delete app %@ (%@)", appPath, error]);
//set flag
bAnyErrors = YES;

24
Installer/main.h Normal file
View File

@ -0,0 +1,24 @@
//
// main.h
// Installer
//
// Created by Patrick Wardle on 9/14/16.
// Copyright © 2016 Objective-See. All rights reserved.
//
#ifndef main_h
#define main_h
#import "Consts.h"
#import "Logging.h"
#import "Configure.h"
#import <syslog.h>
#import <Cocoa/Cocoa.h>
/* FUNCTION DECLARATIONS */
//spawn self as root
BOOL spawnAsRoot(const char* path2Self);
#endif /* main_h */

View File

@ -6,8 +6,116 @@
// Copyright (c) 2016 Objective-See. All rights reserved.
//
#import "main.h"
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[]) {
return NSApplicationMain(argc, argv);
int main(int argc, const char * argv[])
{
//return var
int retVar = -1;
@autoreleasepool
{
//check for r00t
// ->then spawn self via auth exec
if(0 != geteuid())
{
//dbg msg
logMsg(LOG_DEBUG, @"non-root installer instance");
//spawn as root
if(YES != spawnAsRoot(argv[0]))
{
//err msg
logMsg(LOG_ERR, @"failed to spawn self as r00t");
//bail
goto bail;
}
//happy
retVar = 0;
}
//otherwise
// ->just kick off app, as we're root now
else
{
//dbg msg
logMsg(LOG_DEBUG, @"root installer instance");
//app away
retVar = NSApplicationMain(argc, (const char **)argv);
}
}//pool
//bail
bail:
return retVar;
}
//spawn self as root
BOOL spawnAsRoot(const char* path2Self)
{
//return/status var
BOOL bRet = NO;
//authorization ref
AuthorizationRef authorizatioRef = {0};
//args
char *args[] = {NULL};
//flag creation of ref
BOOL authRefCreated = NO;
//status code
OSStatus osStatus = -1;
//create authorization ref
// ->and check
osStatus = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizatioRef);
if(errAuthorizationSuccess != osStatus)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"AuthorizationCreate() failed with %d", osStatus]);
//bail
goto bail;
}
//set flag indicating auth ref was created
authRefCreated = YES;
//spawn self as r00t w/ install flag (will ask user for password)
// ->and check
osStatus = AuthorizationExecuteWithPrivileges(authorizatioRef, path2Self, 0, args, NULL);
//check
if(errAuthorizationSuccess != osStatus)
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"AuthorizationExecuteWithPrivileges() failed with %d", osStatus]);
//bail
goto bail;
}
//no errors
bRet = YES;
//bail
bail:
//free auth ref
if(YES == authRefCreated)
{
//free
AuthorizationFree(authorizatioRef, kAuthorizationFlagDefaults);
}
return bRet;
}

View File

@ -6,8 +6,6 @@
// Copyright (c) 2015 Objective-See. All rights reserved.
//
//TODO: NSLOg -> logmSg
#import "Consts.h"
#import "Logging.h"
#import "Utilities.h"

View File

@ -39,20 +39,17 @@
//check for updates
// ->but only when user has not disabled that feature
// TODO: change to YES
if(NO == [[NSUserDefaults standardUserDefaults] boolForKey:CHECK_4_UPDATES])
if(YES == [[NSUserDefaults standardUserDefaults] boolForKey:CHECK_4_UPDATES])
{
//TODO: make a min!
//after a minute
//->check for updates in background
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 60 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
//dbg msg
logMsg(LOG_DEBUG, @"checking for update");
//check
[self isThereAndUpdate];
});
}

View File

@ -262,9 +262,6 @@ bail:
//TODO: ignore self!!
//Sample analysis of process 18340 written to file /tmp/OverSight_Helper_2016-09-12_211234_StAd.sample.txt
//save to baseline
// TODO: test that this works, esp if cnt goes down!! (facetime battery mode)
//[self.machSenders addEntriesFromDictionary:currentSenders];
//update
self.machSenders = currentSenders;

View File

@ -9,16 +9,10 @@
#import "Logging.h"
#import "Enumerator.h"
#import "OverSightXPC.h"
#import "../Shared/Utilities.h"
@implementation OverSightXPC
//TODO: method to set flag, that's sync'd~!?
@synthesize machSenders;
@synthesize videoActive;

View File

@ -12,12 +12,18 @@
//success
#define STATUS_SUCCESS 0
//apps folder
#define APPS_FOLDER @"/Applications"
//app name
#define APP_NAME @"OverSight.app"
//product url
#define PRODUCT_URL @"https://objective-see.com/products/oversight.html"
//product version url
//TODO: change back!
#define PRODUCT_VERSION_URL @"https://objective-see.com/products/versions/ransomwhere.json"
//TODO: test final/with page
#define PRODUCT_VERSION_URL @"https://objective-see.com/products/versions/oversight.json"
//frame shift
// ->for status msg to avoid activity indicator

View File

@ -20,6 +20,12 @@
// ->extracted from Info.plist
NSString* getAppVersion();
//set dir's|file's group/owner
BOOL setFileOwner(NSString* path, NSNumber* groupID, NSNumber* ownerID, BOOL recursive);
//set permissions for file
void setFilePermissions(NSString* file, int permissions);
//exec a process and grab it's output
NSData* execTask(NSString* binaryPath, NSArray* arguments);

View File

@ -7,11 +7,13 @@
//
#import "Consts.h"
#import "Logging.h"
#import "Utilities.h"
#import <signal.h>
#import <unistd.h>
#import <libproc.h>
#import <sys/stat.h>
#import <sys/sysctl.h>
#import <Security/Security.h>
#import <Foundation/Foundation.h>
@ -71,6 +73,116 @@ NSBundle* findAppBundle(NSString* binaryPath)
return appBundle;
}
//set dir's|file's group/owner
BOOL setFileOwner(NSString* path, NSNumber* groupID, NSNumber* ownerID, BOOL recursive)
{
//ret var
BOOL bRet = NO;
//owner dictionary
NSDictionary* fileOwner = nil;
//sub paths
NSArray *subPaths = nil;
//full path
// ->for recursive
NSString* fullPath = nil;
//init permissions dictionary
fileOwner = @{NSFileGroupOwnerAccountID:groupID, NSFileOwnerAccountID:ownerID};
//set group/owner
if(YES != [[NSFileManager defaultManager] setAttributes:fileOwner ofItemAtPath:path error:NULL])
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to set ownership for %@ (%@)", path, fileOwner]);
//bail
goto bail;
}
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"set ownership for %@ (%@)", path, fileOwner]);
//do it recursively
if(YES == recursive)
{
//sanity check
// ->make sure root starts with '/'
if(YES != [path hasSuffix:@"/"])
{
//add '/'
path = [NSString stringWithFormat:@"%@/", path];
}
//get all subpaths
subPaths = [[NSFileManager defaultManager] subpathsAtPath:path];
for(NSString *subPath in subPaths)
{
//init full path
fullPath = [path stringByAppendingString:subPath];
//set group/owner
if(YES != [[NSFileManager defaultManager] setAttributes:fileOwner ofItemAtPath:fullPath error:NULL])
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to set ownership for %@ (%@)", fullPath, fileOwner]);
//bail
goto bail;
}
}
}
//no errors
bRet = YES;
//bail
bail:
return bRet;
}
//set permissions for file
void setFilePermissions(NSString* file, int permissions)
{
//file permissions
NSDictionary* filePermissions = nil;
//new permissions
//newPermissions =
//get current file attributes
filePermissions = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:NULL];
//int currentPermissions = [[filePermissions objectForKey:@"NSFilePosixPermissions"] intValue];
//permissions |= (S_IRSUR | S_IRGRP | S_IROTH);
// NSDictionary *newattribs = [NSDict dictionaryWithObject:[NSNumber numberWithInt:permissions]
// forKey:NSFilePosixPermissions];
//[fm setAttributes:dict ofItemAtPath:[file path] error:&error];
//init dictionary
filePermissions = @{NSFilePosixPermissions: [NSNumber numberWithInt:permissions]};
//set permissions
if(YES != [[NSFileManager defaultManager] setAttributes:filePermissions ofItemAtPath:file error:NULL])
{
//err msg
logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to set permissions for %@ (%@)", file, filePermissions]);
}
else
{
//dbg msg
logMsg(LOG_DEBUG, [NSString stringWithFormat:@"set permissions for %@ (%@)", file, filePermissions]);
}
return;
}
//exec a process and grab it's output
NSData* execTask(NSString* binaryPath, NSArray* arguments)
{
@ -385,3 +497,5 @@ void makeModal(NSWindowController* windowController)
return;
}