Permalink
Browse files

Added scheckup to make super-sure that blocks will come off, stopping…

… the permablock issue (hopefully). Yes, I know it's really messy.
1 parent 1ac5268 commit 3a95bf3f7e8fbfa937c0ef7963fc2d364f7de847 @cstigler cstigler committed Jul 14, 2010
View
@@ -29,6 +29,7 @@
#import <Security/Security.h>
#import <SystemConfiguration/SCNetwork.h>
#import <unistd.h>
+#import "SelfControlCommon.h"
// The main controller for the SelfControl app, which includes several methods
// to handle command flow and acts as delegate for the initial window.
View
@@ -22,7 +22,6 @@
#import "AppController.h"
-NSString* const kSelfControlLockFilePath = @"/etc/SelfControl.lock";
NSString* const kSelfControlErrorDomain = @"SelfControlErrorDomain";
@implementation AppController
@@ -166,6 +165,8 @@ - (IBAction)addBlock:(id)sender {
return;
}
+ [timerWindowController_ resetStrikes];
+
[NSThread detachNewThreadSelector: @selector(installBlock) toTarget: self withObject: nil];
}
@@ -211,6 +212,8 @@ - (void)refreshUserInterface {
[blockLock_ unlock];
}
+ [timerWindowController_ blockEnded];
+
NSWindow* mainWindow = [NSApp mainWindow];
// We don't necessarily want the initial window to be key and front,
// but no other message seems to show it properly.
@@ -301,7 +304,22 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
}
- (BOOL)selfControlLaunchDaemonIsLoaded {
- return [[NSFileManager defaultManager] fileExistsAtPath: kSelfControlLockFilePath];
+ // First we check the host file, and see if a block is in there
+ NSString* hostFileContents = [NSString stringWithContentsOfFile: @"/etc/hosts"];
+ if(hostFileContents != nil && [hostFileContents rangeOfString: @"# BEGIN SELFCONTROL BLOCK"].location != NSNotFound) {
+ return YES;
+ }
+
+ // Next we see whether defaults thinks a block is on (if BlockStartedDate is a valid date)
+ NSDate* blockStartedDate = [defaults_ objectForKey: @"BlockStartedDate"];
+ if(blockStartedDate != nil && ![blockStartedDate isEqualToDate: [NSDate distantFuture]]) {
+ return YES;
+ }
+
+ // If there's no block in the hosts file, no defaults BlockStartedDate, and no lock-file,
+ // we'll assume we're clear of blocks. Checking ipfw would be nice but usually requires
+ // root permissions, so it would be difficult to do here.
+ return [[NSFileManager defaultManager] fileExistsAtPath: SelfControlLockFilePath];
}
- (IBAction)showDomainList:(id)sender {
@@ -554,6 +572,9 @@ - (NSError*)errorFromHelperToolStatusCode:(int)status {
case -218:
[description appendString: @"Could not remove SelfControl lock file."];
break;
+ case -219:
+ [description appendString: @"SelfControl lock file already exists. Please try your block again."];
+ break;
default:
[description appendString: [NSString stringWithFormat: @"Helper tool failed with unknown error code: %d", status]];
View
@@ -0,0 +1,10 @@
+/*
+ * CheckupMain.h
+ * SelfControl
+ *
+ * Created by Charlie Stigler on 7/13/10.
+ * Copyright 2010 Harvard-Westlake Student. All rights reserved.
+ *
+ */
+
+#import "HelperCommon.h"
View
@@ -0,0 +1,74 @@
+/*
+ * CheckupMain.c
+ * SelfControl
+ *
+ * Created by Charlie Stigler on 7/13/10.
+ * Copyright 2010 Harvard-Westlake Student. All rights reserved.
+ *
+ */
+
+#include "CheckupMain.h"
+
+int main(int argc, char* argv[]) {
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+ if(geteuid()) {
+ NSLog(@"ERROR: SUID bit not set on scheckup.");
+ printStatus(-201);
+ exit(EX_NOPERM);
+ }
+
+ NSDictionary* curDictionary = [NSDictionary dictionaryWithContentsOfFile: SelfControlLockFilePath];
+ NSDate* blockStartedDate = [curDictionary objectForKey: @"BlockStartedDate"];
+ NSTimeInterval blockDuration = [[curDictionary objectForKey: @"BlockDuration"] intValue];
+
+
+ if(blockStartedDate == nil || [[NSDate distantFuture] isEqualToDate: blockStartedDate] || blockDuration < 1) {
+ // The lock file seems to be broken. Try defaults.
+ NSLog(@"WARNING: Lock file unreadable or invalid");
+ [NSUserDefaults resetStandardUserDefaults];
+ seteuid(getuid());
+ defaults = [NSUserDefaults standardUserDefaults];
+ [defaults addSuiteNamed:@"org.eyebeam.SelfControl"];
+ blockStartedDate = [defaults objectForKey: @"BlockStartedDate"];
+ blockDuration = [[defaults objectForKey: @"BlockDuration"] intValue];
+ [defaults synchronize];
+ [NSUserDefaults resetStandardUserDefaults];
+ seteuid(0);
+
+ if(blockStartedDate == nil || [[NSDate distantFuture] isEqualToDate: blockStartedDate] || blockDuration < 1) {
+ // Defaults is broken too! Let's get out of here!
+ NSLog(@"WARNING: Checkup ran but no block found. Attempting to remove block.");
+
+ // get rid of this block
+ removeBlock(getuid());
+
+ printStatus(-215);
+ exit(EX_SOFTWARE);
+ }
+ }
+
+ // convert to seconds
+ blockDuration *= 60;
+
+ NSTimeInterval timeSinceStarted = [[NSDate date] timeIntervalSinceDate: blockStartedDate];
+
+ if( blockStartedDate == nil || blockDuration < 1 || [[NSDate distantFuture] isEqualToDate: blockStartedDate] || timeSinceStarted >= blockDuration) {
+ NSLog(@"INFO: Checkup helper ran, block expired, removing block.");
+
+#ifdef DEBUG
+ NSLog(@"BLOCK EXPIRED DUE TO CONDITIONS:");
+ NSLog(@"blockStartedDate == nil: %d", blockStartedDate == nil);
+ NSLog(@"[[NSDate distantFuture] isEqualToDate: blockStartedDate]: %d", [[NSDate distantFuture] isEqualToDate: blockStartedDate]);
+ NSLog(@"timeSinceStarted >= blockDuration: %d", timeSinceStarted >= blockDuration);
+ NSLog(@"END CONDITIONS");
+#endif
+
+ removeBlock(getuid());
+ }
+
+ [pool drain];
+ NSLog(@"INFO: scheckup run but block should still be ongoing.");
+ exit(EXIT_SUCCESS);
+}
+
@@ -24,9 +24,7 @@
#import <Cocoa/Cocoa.h>
#import "HostImporter.h"
#import "ThunderbirdPreferenceParser.h"
-
-// This is a reference to the kSelfControlLockFilePath const variable in AppController.m
-extern NSString* const kSelfControlLockFilePath;
+#import "SelfControlCommon.h"
// A subclass of NSWindowController created to manage the domain list (actually
// host list, but domain list seems more understandable to inexperienced users
View
@@ -1,26 +1,28 @@
--101 (AppController.m -addBlock:) - Attempting to add block, but a block appears to be in progress.
--102 (AppController.m -addBlock:) - Attempting to add block, but no blocklist is set.
--103 (AppController.m -addToBlockList:) - Attempting to add host to block, but no block appears to be in progress.
--104 (AppController.m -installBlock) - The helper tool crashed. This may cause unexpected errors.
--105 (AppController.m -refreshBlock) - The helper tool crashed. This may cause unexpected errors.
+-101 - Attempting to add block, but a block appears to be in progress.
+-102 - Attempting to add block, but no blocklist is set.
+-103 - Attempting to add host to block, but no block appears to be in progress.
+-104 - The helper tool crashed. This may cause unexpected errors.
+-105 - The helper tool crashed. This may cause unexpected errors.
--201 (HelperMain.m main(int argc, char* argv[])) - Helper tool not launched as root.
--202 (HelperMain.m main(int argc, char* argv[])) - Helper tool launched with insufficient arguments.
--203 (HelperMain.m main(int argc, char* argv[])) - Host blocklist not set
--204 (HelperMain.m main(int argc, char* argv[])) - Could not write launchd plist file to LaunchDaemons folder.
--205 (HelperMain.m main(int argc, char* argv[])) - Could not create PrivilegedHelperTools directory.
--206 (HelperMain.m main(int argc, char* argv[])) - Could not change permissions on PrivilegedHelperTools directory.
--207 (HelperMain.m main(int argc, char* argv[])) - Could not delete old helper binary.
--208 (HelperMain.m main(int argc, char* argv[])) - Could not copy SelfControl's helper binary to PrivilegedHelperTools directory.
--209 (HelperMain.m main(int argc, char* argv[])) - Could not change permissions on SelfControl's helper binary.
--210 (HelperMain.m main(int argc, char* argv[])) - Insufficient block information found.
--211 (HelperMain.m main(int argc, char* argv[])) - Launch daemon load returned a failure status code.
--212 (HelperMain.m main(int argc, char* argv[])) - Remove option called
--213 (HelperMain.m main(int argc, char* argv[])) - Refreshing domain blacklist, but no block is currently ongoing.
--214 (HelperMain.m main(int argc, char* argv[])) - Insufficient block information found.
--215 (HelperMain.m main(int argc, char* argv[])) - Checkup ran but no block found.
--216 (HelperMain.m main(int argc, char* argv[])) - Could not write lock file.
--217 (HelperMain.m main(int argc, char* argv[])) - Could not write lock file.
+-201 - Helper tool not launched as root.
+-202 - Helper tool launched with insufficient arguments.
+-203 - Host blocklist not set
+-204 - Could not write launchd plist file to LaunchDaemons folder.
+-205 - Could not create PrivilegedHelperTools directory.
+-206 - Could not change permissions on PrivilegedHelperTools directory.
+-207 - Could not delete old helper binary.
+-208 - Could not copy SelfControl's helper binary to PrivilegedHelperTools directory.
+-209 - Could not change permissions on SelfControl's helper binary.
+-210 - Insufficient block information found.
+-211 - Launch daemon load returned a failure status code.
+-212 - Remove option called
+-213 - Refreshing domain blacklist, but no block is currently ongoing.
+-214 - Insufficient block information found.
+-215 - Checkup ran but no block found.
+-216 - Could not write lock file.
+-217 - Could not write lock file.
+-218 - Could not remove lock file.
+-219 - Trying to add block but lock file already found. Please try again.
--901 (AppController.m -soundSelectionChanged:) - Selected sound not found.
--902 (AppController.m -save) - Error serializing blacklist for save
+-901 - Selected sound not found.
+-902 - Error serializing blacklist for save
View
@@ -0,0 +1,69 @@
+//
+// HelperCommonFunctions.h
+// SelfControl
+//
+// Created by Charlie Stigler on 07/13/09.
+// Copyright 2009 Eyebeam.
+
+// This file is part of SelfControl.
+//
+// SelfControl is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// All the functions etc. formerly used for HelperMain are now separated into this file.
+// This is so that another helper tool can be created that easily uses those same functions.
+
+// imports for all helper tools
+#import <Foundation/Foundation.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import "IPFirewall.h"
+#import "LaunchctlHelper.h"
+#import "SelfControlUtilities.h"
+#import <unistd.h>
+#import <Cocoa/Cocoa.h>
+#import <sysexits.h>
+#import "HostFileBlocker.h"
+#import "SelfControlCommon.h"
+
+// These don't comply with the "end instance variables with an underscore" rule
+// because they aren't instance variables. Note this file is, although in
+// Objective-C, not a class. It contains only functions.
+NSUserDefaults* defaults;
+NSArray* domainList;
+
+// Reads the domain block list from the defaults for SelfControl, and adds deny
+// rules for all of the IPs (or the A DNS record IPS for doamin names) to the
+// ipfw firewall.
+void addRulesToFirewall(signed long long int controllingUID);
+
+// Removes from ipfw all rules that were created by SelfControl.
+void removeRulesFromFirewall(signed long long int controllingUID);
+
+// Returns an autoreleased NSSet containing all IP adresses for evaluated
+// "common subdomains" for the specified hostname
+NSSet* getEvaluatedHostNamesFromCommonSubdomains(NSString* hostName, int port);
+
+// Checks the defaults system to see whether the user wants their web browser
+// caches cleared, and deletes the specific cache folders for a few common
+// web browsers if it is required.
+void clearCachesIfRequested(signed long long int controllingUID);
+
+// Prints out the given status code to stdout using printf
+void printStatus(int status);
+
+// Parses hostName, to find a mask length (for IP ranges) and port number, if
+// specified. Returns by reference baseName, which is hostName without mask
+// length or port number, and the mask length and port number unless they were
+// not specified, in which case they will be initialized to -1.
+void parseHost(NSString* hostName, NSString** baseName, int* maskLength, int* portNumber);
+
+// Removes block via setting the defaults, removing the lock file, host file rules and ipfw
+// rules, unloading the org.eyebeam.SelfControl item, and deleting user caches if requested.
+void removeBlock(signed long long int controllingUID);
Oops, something went wrong.

0 comments on commit 3a95bf3

Please sign in to comment.