diff --git a/Installer/Configure.m b/Installer/Configure.m
index 5e19586..63a9935 100644
--- a/Installer/Configure.m
+++ b/Installer/Configure.m
@@ -34,7 +34,11 @@
if(YES == [self isInstalled])
{
//dbg msg
- logMsg(LOG_DEBUG, @"already installed, so uninstalling...");
+ logMsg(LOG_DEBUG, @"already installed, so stopping/uninstalling...");
+
+ //stop
+ // ->kill login item/XPC service
+ [self stop];
//uninstall
if(YES != [self uninstall])
@@ -43,10 +47,6 @@
goto bail;
}
- //and stop
- //TODO: erorr checking
- [self stop];
-
//dbg msg
logMsg(LOG_DEBUG, @"uninstalled");
}
@@ -81,16 +81,9 @@
//dbg msg
logMsg(LOG_DEBUG, @"stopping login item");
- //stop login item/XPC service
- if(YES != [self stop])
- {
- //err msg
- logMsg(LOG_ERR, @"stopping failed");
-
- //bail
- goto bail;
- }
-
+ //stop
+ // ->kill login item/XPC service
+ [self stop];
//dbg msg
logMsg(LOG_DEBUG, @"uninstalling...");
@@ -228,22 +221,13 @@ bail:
}
//stop
--(BOOL)stop
+-(void)stop
{
- //flag
- BOOL bStopped = NO;
-
//kill it
// pkill doesn't provide error info, so...
execTask(PKILL, @[APP_HELPER_NAME]);
-
- //happy
- bStopped = YES;
-
-//bail
-bail:
-
- return bStopped;
+
+ return;
}
//uninstall
diff --git a/LoginItem/AVMonitor.m b/LoginItem/AVMonitor.m
index 82e593f..3ede48f 100644
--- a/LoginItem/AVMonitor.m
+++ b/LoginItem/AVMonitor.m
@@ -14,67 +14,6 @@
#import "../Shared/XPCProtocol.h"
-//TODO: make instance methods?!
-
-//grab first apple camera
-AVCaptureDevice* findAppleCamera()
-{
- //apple camera
- // ->likely FaceTime camera
- AVCaptureDevice* appleCamera = nil;
-
- //list of cameras
- NSArray *cameras = nil;
-
- //get cameras
- cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
- for(AVCaptureDevice* camera in cameras)
- {
- //check if apple
- if(YES == [camera.manufacturer isEqualToString:@"Apple Inc."])
- {
- //save
- appleCamera = camera;
-
- //exit loop
- break;
- }
- }
-
- return appleCamera;
-}
-
-//grab built-in mic
-AVCaptureDevice* findAppleMic()
-{
- //built-in mic
- AVCaptureDevice* appleMic = nil;
-
- //list of mics
- NSArray *mics = nil;
-
- //get mics
- mics = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
- for(AVCaptureDevice* mic in mics)
- {
- //check if apple
- // ->also check input source
- if( (YES == [mic.manufacturer isEqualToString:@"Apple Inc."]) &&
- (YES == [[[mic activeInputSource] inputSourceID] isEqualToString:@"imic"]) )
- {
- //save
- appleMic = mic;
-
- //exit loop
- break;
- }
-
- }
-
- return appleMic;
-}
-
-
@implementation AVMonitor
@synthesize mic;
@@ -96,6 +35,54 @@ AVCaptureDevice* findAppleMic()
return self;
}
+//grab first apple camera
+// ->saves into iVar 'camera'
+// note: could maybe use defaultDeviceWithDeviceType method() to default device...
+-(void)findAppleCamera
+{
+ //get cameras
+ // ->look for one that belongs to apple
+ for(AVCaptureDevice* currentCamera in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo])
+ {
+ //check if apple
+ if(YES == [currentCamera.manufacturer isEqualToString:@"Apple Inc."])
+ {
+ //save
+ self.camera = currentCamera;
+
+ //exit loop
+ break;
+ }
+ }
+
+ return;
+}
+
+//grab first apple mic
+// ->saves into iVar 'mic'
+-(void)findAppleMic
+{
+ //get mics
+ // ->loof for one that belongs to app
+ for(AVCaptureDevice* currentMic in [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio])
+ {
+ //check if apple
+ // ->also check input source
+ if( (YES == [currentMic.manufacturer isEqualToString:@"Apple Inc."]) &&
+ (YES == [[[currentMic activeInputSource] inputSourceID] isEqualToString:@"imic"]) )
+ {
+ //save
+ self.mic = currentMic;
+
+ //exit loop
+ break;
+ }
+
+ }
+
+ return;
+}
+
//initialiaze AV notifcations/callbacks
-(BOOL)monitor
{
@@ -155,13 +142,12 @@ AVCaptureDevice* findAppleMic()
methodSelector = NSSelectorFromString(@"connectionID");
//find (first) apple camera
- self.camera = findAppleCamera();
+ // ->saves camera into iVar, 'camera'
+ [self findAppleCamera];
- //find built in mic
- self.mic = findAppleMic();
-
- //dbg msg
- logMsg(LOG_DEBUG, [NSString stringWithFormat:@"found mic: %@", self.mic]);
+ //find (first) apple mic
+ // ->saves mic into iVar, 'mic'
+ [self findAppleMic];
//got camera
// ->grab connection ID and invoke helper functions
@@ -522,7 +508,7 @@ bail:
if(noErr != status)
{
//err msg
- //TODO: add
+ logMsg(LOG_ERR, [NSString stringWithFormat:@"CMIOObjectAddPropertyListenerBlock() failed with %d", status]);
//bail
goto bail;
@@ -737,23 +723,22 @@ bail:
// ->for activatated video; allow/block
else
{
+ //get process name
+ processName = getProcessName([event[EVENT_PROCESS_ID] intValue]);
+
//set other button title
notification.otherButtonTitle = @"allow";
//set action title
notification.actionButtonTitle = @"block";
- //get process name
- // TODO: see 'determineName' in BB (to get name from bundle, etc)
- processName = [getProcessPath([event[EVENT_PROCESS_ID] intValue]) lastPathComponent];
-
//set pid in user info
// ->allows code to try kill proc (later) if user clicks 'block'
notification.userInfo = @{EVENT_PROCESS_ID:event[EVENT_PROCESS_ID]};
//set details
// ->name of process using it / icon too?
- [notification setInformativeText:[NSString stringWithFormat:@"%@ (%@)", processName, event[EVENT_PROCESS_ID]]];
+ [notification setInformativeText:[NSString stringWithFormat:@"process: %@ (%@)", processName, event[EVENT_PROCESS_ID]]];
}
//log event?
@@ -772,11 +757,11 @@ bail:
}
//process
- // ->add title / details / process
+ // ->add title / details / process path
else
{
//add
- [logMsg appendFormat:@"%@ (%@, %@)", title, details, processName];
+ [logMsg appendFormat:@"%@ (process: %@, %@)", title, details, getProcessPath([event[EVENT_PROCESS_ID] intValue])];
}
//write it out to syslog
diff --git a/MainApp/Info.plist b/MainApp/Info.plist
index 79b6bf7..42e9bed 100644
--- a/MainApp/Info.plist
+++ b/MainApp/Info.plist
@@ -6,8 +6,6 @@
en
CFBundleExecutable
$(EXECUTABLE_NAME)
- CFBundleIconFile
-
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
@@ -24,12 +22,12 @@
1.0.0
LSMinimumSystemVersion
$(MACOSX_DEPLOYMENT_TARGET)
+ LSUIElement
+
NSHumanReadableCopyright
Copyright (c) 2016 Objective-See. All rights reserved.
NSMainNibFile
MainMenu
- LSUIElement
-
NSPrincipalClass
NSApplication
diff --git a/OverSight.xcodeproj/project.pbxproj b/OverSight.xcodeproj/project.pbxproj
index 6fe27c1..27dec0d 100644
--- a/OverSight.xcodeproj/project.pbxproj
+++ b/OverSight.xcodeproj/project.pbxproj
@@ -33,6 +33,7 @@
7D9A7DE81D893E4F0091C1AF /* InfoWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D62458C1D87D38400870565 /* InfoWindow.xib */; };
7D9A7DEC1D8BE1E00091C1AF /* Exception.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D17C5311D659E580066232A /* Exception.m */; };
7D9A7DEE1D8CACE30091C1AF /* libbsm.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D9A7DED1D8CACE30091C1AF /* libbsm.tbd */; };
+ 7D9A7DF21D8F2C900091C1AF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7D6245841D87C43900870565 /* Images.xcassets */; };
7DAF4B7F1D657192000DA31A /* StatusBarMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DAF4B7D1D656FD3000DA31A /* StatusBarMenu.m */; };
7DC9C8171D641A350017D143 /* OverSightXPC.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC9C8161D641A350017D143 /* OverSightXPC.m */; };
7DC9C8191D641A350017D143 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC9C8181D641A350017D143 /* main.m */; };
@@ -166,7 +167,7 @@
7D17C5131D658FE20066232A /* Images */ = {
isa = PBXGroup;
children = (
- 7D17CFE21D81121E0017B475 /* AVMonitor.h */,
+ 8B5755C819DA3F9300799E6B /* AppDelegate.h */,
7D17C5141D658FEB0066232A /* statusIcon.png */,
7D17C5151D658FEB0066232A /* statusIcon@2x.png */,
);
@@ -276,11 +277,11 @@
isa = PBXGroup;
children = (
7D17C5131D658FE20066232A /* Images */,
+ 8B5755C919DA3F9300799E6B /* AppDelegate.m */,
+ 7D17CFE21D81121E0017B475 /* AVMonitor.h */,
+ 7D17CFE11D81121E0017B475 /* AVMonitor.m */,
7DAF4B7C1D656FD3000DA31A /* StatusBarMenu.h */,
7DAF4B7D1D656FD3000DA31A /* StatusBarMenu.m */,
- 8B5755C819DA3F9300799E6B /* AppDelegate.h */,
- 8B5755C919DA3F9300799E6B /* AppDelegate.m */,
- 7D17CFE11D81121E0017B475 /* AVMonitor.m */,
8B5755CD19DA3F9300799E6B /* MainMenu.xib */,
8B5755C419DA3F9300799E6B /* Supporting Files */,
);
@@ -419,6 +420,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 7D9A7DF21D8F2C900091C1AF /* Images.xcassets in Resources */,
7D6245921D87D46800870565 /* InfoWindow.xib in Resources */,
7D17C53C1D659E580066232A /* icon.png in Resources */,
8B5755A919DA3E9500799E6B /* MainMenu.xib in Resources */,
@@ -629,6 +631,7 @@
8B5755B919DA3E9500799E6B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Developer ID Application";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
COMBINE_HIDPI_IMAGES = YES;
@@ -644,6 +647,7 @@
8B5755BA19DA3E9500799E6B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Developer ID Application";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Developer ID Application: Objective-See, LLC (VBG97UB4TA)";
COMBINE_HIDPI_IMAGES = YES;
diff --git a/OverSightXPC/Enumerator.m b/OverSightXPC/Enumerator.m
index b0d1189..a9e7f39 100644
--- a/OverSightXPC/Enumerator.m
+++ b/OverSightXPC/Enumerator.m
@@ -309,7 +309,6 @@ bail:
}
//parse on '()'
- // TODO: improve this!
subStrings = [line componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"()"]];
if(subStrings.count < 3)
{
@@ -371,10 +370,10 @@ bail:
videoProcs = [NSMutableArray array];
//invoke 'sample' on each
- // TODO: delete tmp file? 'Sample analysis of process 37370 written to file /tmp/FaceTime_2016-09-10_081703_TAwB.sample.txt' (written 2 std err?)
for(NSNumber* processID in currentSenders)
{
//exec 'sample' to get threads/dylibs
+ // ->uses 1.0 seconds for sampling time
results = [[NSString alloc] initWithData:execTask(SAMPLE, @[processID.stringValue, @"1"]) encoding:NSUTF8StringEncoding];
if( (nil == results) ||
(0 == results.length) )
@@ -382,7 +381,11 @@ bail:
//skip
continue;
}
-
+
+ //sampling a process creates a temp file
+ //->delete it!
+ [self deleteSampleFile:getProcessPath(processID.intValue)];
+
//for now, just check for 'CMIOGraph::DoWork'
// ->TODO: could look for dylibs, other calls, etc
if(YES != [results containsString:@"CMIOGraph::DoWork"])
@@ -398,6 +401,66 @@ bail:
return videoProcs;
}
+//'sample' binary creates a file
+// ->this looks for that file and deletes it
+-(void)deleteSampleFile:(NSString*)processPath
+{
+ //error
+ NSError* error = nil;
+
+ //files
+ NSArray* files = nil;
+
+ //grab all files in /tmp
+ files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/tmp/" error:&error];
+ if(nil != error)
+ {
+ //err msg
+ logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to enumerate files in /tmp, %@", error]);
+
+ //bail
+ goto bail;
+ }
+
+ //find/delete file
+ for(NSString* file in files)
+ {
+ //skip non-sample files
+ if(YES != [file hasSuffix:@".sample.txt"])
+ {
+ //skip
+ continue;
+ }
+
+ //ignore files that don't contain process name
+ if(YES != [file containsString:[processPath lastPathComponent]])
+ {
+ //skip
+ continue;
+ }
+
+ //dbg msg
+ logMsg(LOG_DEBUG, [NSString stringWithFormat:@"deleting sample file: %@", file]);
+
+ //delete
+ if(YES != [[NSFileManager defaultManager] removeItemAtPath:[@"/tmp" stringByAppendingPathComponent:file] error:&error])
+ {
+ //err msg
+ logMsg(LOG_ERR, [NSString stringWithFormat:@"failed to delete %@ (%@)", file, error]);
+
+ //bail
+ goto bail;
+ }
+
+ }//all files
+
+//bail
+bail:
+
+
+ return;
+}
+
//set status of video
-(void)updateVideoStatus:(BOOL)isEnabled
{
diff --git a/Shared/Exception.m b/Shared/Exception.m
index 140bcb1..7f7d035 100755
--- a/Shared/Exception.m
+++ b/Shared/Exception.m
@@ -11,12 +11,10 @@
#import "Exception.h"
#import "Utilities.h"
-//TODO: renenable
-/*
#ifdef IS_INSTALLER_APP
#import "AppDelegate.h"
#endif
-*/
+
//global
// ->only report an fatal exception once
@@ -98,9 +96,8 @@ void exceptionHandler(NSException *exception)
// ->agent should exit
errorInfo[KEY_ERROR_SHOULD_EXIT] = [NSNumber numberWithBool:YES];
- //TODO: renable
//display error msg
- //[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
+ [((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
//need to sleep, otherwise returning from this function will cause OS to kill agent
// ->instead, we want error popup to be displayed (which will exit agent when closed)
@@ -178,9 +175,8 @@ void signalHandler(int signal, siginfo_t *info, void *context)
// ->agent should exit
errorInfo[KEY_ERROR_SHOULD_EXIT] = [NSNumber numberWithBool:YES];
- //TODO: renable
//display error msg
- //[((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
+ [((AppDelegate*)[[NSApplication sharedApplication] delegate]) displayErrorWindow:errorInfo];
//end app-specific code
#endif
diff --git a/Shared/Logging.m b/Shared/Logging.m
index fb79fbb..d48badb 100644
--- a/Shared/Logging.m
+++ b/Shared/Logging.m
@@ -42,8 +42,5 @@ void logMsg(int level, NSString* msg)
//log to syslog
syslog(level, "%s: %s\n", [logPrefix UTF8String], [msg UTF8String]);
- //TODO: remove
- NSLog(@"%s: %s", [logPrefix UTF8String], [msg UTF8String]);
-
return;
}
diff --git a/Shared/Utilities.h b/Shared/Utilities.h
index 3c73874..4f17046 100644
--- a/Shared/Utilities.h
+++ b/Shared/Utilities.h
@@ -14,8 +14,6 @@
/* FUNCTIONS */
-//TODO: cleanup/remove un-needed
-
//get app's version
// ->extracted from Info.plist
NSString* getAppVersion();
@@ -36,13 +34,6 @@ SInt32 getVersion(OSType selector);
// parse it back up to find app's bundle
NSBundle* findAppBundle(NSString* binaryPath);
-//given a directory and a filter predicate
-// ->return all matches
-NSArray* directoryContents(NSString* directory, NSString* predicate);
-
-//hash (sha1/md5) a file
-NSDictionary* hashFile(NSString* filePath);
-
//get app's version
// ->extracted from Info.plist
NSString* getAppVersion();
@@ -54,15 +45,15 @@ NSString* getLatestVersion();
// -1, YES or NO
NSInteger isNewVersion(NSMutableString* versionString);
-//exec a process and grab it's output
-NSData* execTask(NSString* binaryPath, NSArray* arguments);
-
//get process's path
NSString* getProcessPath(pid_t pid);
+//given a pid
+// ->get the name of the process
+NSString* getProcessName(pid_t pid);
+
//wait until a window is non nil
// ->then make it modal
void makeModal(NSWindowController* windowController);
-
#endif
diff --git a/Shared/Utilities.m b/Shared/Utilities.m
index cc7d138..4edb730 100644
--- a/Shared/Utilities.m
+++ b/Shared/Utilities.m
@@ -254,7 +254,7 @@ NSData* execTask(NSString* binaryPath, NSArray* arguments)
//launch
[task launch];
}
- @catch(NSException *exception)
+ @catch(NSException* exception)
{
//bail
goto bail;
@@ -412,6 +412,53 @@ bail:
return taskPath;
}
+//given a pid
+// ->get the name of the process
+NSString* getProcessName(pid_t pid)
+{
+ //task path
+ NSString* processName = nil;
+
+ //process path
+ NSString* processPath = nil;
+
+ //app's bundle
+ NSBundle* appBundle = nil;
+
+ //get process path
+ processPath = getProcessPath(pid);
+ if( (nil == processPath) ||
+ (0 == processPath.length) )
+ {
+ //default to 'unknown'
+ processName = @"";
+
+ //bail
+ goto bail;
+ }
+
+ //try find an app bundle
+ appBundle = findAppBundle(processPath);
+ if(nil != appBundle)
+ {
+ //grab name from app's bundle
+ processName = [appBundle infoDictionary][@"CFBundleName"];
+ }
+
+ //still nil?
+ // ->just grab from path
+ if(nil == processName)
+ {
+ //from path
+ processName = [processPath lastPathComponent];
+ }
+
+//bail
+bail:
+
+ return processName;
+}
+
//determine if there is a new version
// -1, YES or NO
NSInteger isNewVersion(NSMutableString* versionString)