/* FirewallTool.m */ /* Written by Elizabeth C. Douglas */ /* Mary Chan 4/2004 */ /* Copyright: Apple Computer, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RULE_0 10 #define RULE_1 2000 #define RULE_2 2010 #define RULE_3 2020 #define RULE_4 2030 #define RULE_5 2040 #define RULE_6 2050 #define RULE_7 2060 #define RULE_8 12180 #define RULE_9 12190 #define ICMPECHOREQRULE 20000 #define RULE_D 65535 #define NUM_DEFAULT 9 /* UDP Rules */ #define UDPRULEDNS 20310 #define UDPRULEBOOTP 20320 #define UDPRULEBOOTSERVER 20321 #define UDPRULEMDNSRESPONSE 20322 #define UDPRULENTP 20330 #define UDPRULESMB 20340 #define UDPRULESRVLOC 20350 #define UDPRULEIPP 20360 #define UDPRULEMDNS 20370 #define UDPRPCRULESTART 20400 #define UDPUSERDEFINEDSTARTS 22000 #define UDPRULECHECKSTATE 30500 #define UDPRULEKEEPSTATE 30510 #define UDPRULEDEFAULTFRAG 30520 #define UDPRULEDEFAULTDENY 35000 /* UDP port number */ #define DNSPORT 53 #define BOOTSERVERPORT 67 #define BOOTPCLIENTPPORT 68 #define RPCPORT 111 #define NTPPORT 123 #define SMBPORT 137 #define SRVLOCPORT 427 #define IPPPORT 631 #define MDNSPORT 5353 #define ARDPORT 3283 #define RSTPCLIENTPORT 6970 #6970-6980 #define kFirewallKey CFSTR("firewall") #define kStateKey CFSTR("state") #define kEnableKey CFSTR("enable") #define kPortKey CFSTR("port") #define kAllPortsKey CFSTR("allports") #define kFirewallAppSignature CFSTR("com.apple.sharing.firewall") #define kUDPEnableKey CFSTR("udpenabled") #define kLogEnableKey CFSTR("loggingenabled") #define kStealthEnableKey CFSTR("stealthenabled") #define kUDPPortKey CFSTR("udpport") #define RULE_START 2070 #define SUCCESS 0 #define ERROR 1 #define SIGNAL_FTP -1 #define kAppleRule 0 #define kOneRule -1 #define kThirdPartyRule -2 #define kError ERROR #define LOGDEFAULTVALUE 0 // default value for logging when the key is missing #define STEALTHDEFAULTVALUE 0 // default value for stealth mode when the key is missing #define MAXDEFAULTUDPRULES 6 // needs to be updated whenever DEFAULTUDPSET changes #define LOGGERPROGPATH "/usr/libexec/ipfwloggerd" #define LOGGERPIDPATH "/var/run/ipfwlogger.pid" typedef struct DEFAULTUDPRULETYPE { int theport; int therule; } DEFAULTUDPRULETYPE; typedef struct DEFAULTUDPRULESET{ DEFAULTUDPRULETYPE set[MAXDEFAULTUDPRULES]; }DEFAULTUDPRULESET; struct DEFAULTUDPRULESET DEFAULTUDPSET={ { { DNSPORT , UDPRULEDNS}, { BOOTPCLIENTPPORT , UDPRULEBOOTP}, { SMBPORT , UDPRULESMB}, { SRVLOCPORT , UDPRULESRVLOC}, { IPPPORT , UDPRULEIPP}, { MDNSPORT , UDPRULEMDNS} } }; int ReadFile(CFPropertyListRef *dictionaryRef, CFPropertyListRef *stateRef, Boolean *UDPenabled, Boolean *LOGGINGenabled, Boolean *STEALTHenabled); int DoV4Firewall(CFPropertyListRef dictionaryRef, CFPropertyListRef stateRef, Boolean udpenabled, Boolean loggingenabled, Boolean stealthenabled); int DoV6Firewall(CFPropertyListRef dictionaryRef, CFPropertyListRef stateRef, Boolean udpenabled, Boolean loggingenabled, Boolean stealthenabled); int FlushOldRules(int controlSocket); int FlushOldRulesV6(int controlSocket); int WriteRulesToSockets(int controlSocket, CFPropertyListRef dictionaryRef, Boolean isV6, Boolean udpenabled, Boolean loggingenabled, Boolean stealthenabled); int AddDefaultRules(int controlSocket, Boolean doUDP, Boolean loggingenabled, Boolean stealthenabled); int AddDefaultRulesV6(int controlSocket, Boolean doUDP, Boolean loggingenabled, Boolean stealthenabled); int AddDefaultRule1LoopBack(int controlSocket); int AddDefaultRule1LoopBackV6(int controlSocket); int AddDefaultRule2DiscardLoopbackIn(int controlSocket); int AddDefaultRule2DiscardLoopbackInV6(int controlSocket); int AddDefaultRule3DiscardLoopbackOut(int controlSocket); int AddDefaultRule3DiscardLoopbackOutV6(int controlSocket); int AddDefaultRule4DiscardBroadcastMulticast(int controlSocket); int AddDefaultRule4DiscardBroadcastMulticastV6(int controlSocket); int AddDefaultRule5DiscardTCPBroadcastMulticast(int controlSocket); int AddDefaultRule5DiscardTCPBroadcastMulticastV6(int controlSocket); int AddDefaultRule6OutboundOK(int controlSocket); int AddDefaultRule6OutboundOKV6(int controlSocket); int AddDefaultRule7KeepEstablished(int controlSocket); int AddDefaultRule7KeepEstablishedV6(int controlSocket); int AddDefaultRule9DenyTCP(int controlSocket, Boolean loggingenabled); int AddDefaultRule9DenyTCPV6(int controlSocket, Boolean loggingenabled); int AddDefaultUDPRULE(int controlSocket, int udpport, int rulenumber ); int AddDefaultUDPBootServer(int controlSocket ); int AddDefaultUDPMDNS( int controlSocket); int AddDefaultUDPCheckState(int controlSocket); int AddDefaultUDPKeepState(int controlSocket); int AddDefaultUDPFRAG(int controlSocket ); int AddDefaultUDPDeny(int controlSocket, Boolean loggingenabled ); int AddDefaultUDPRPCRULE(int controlSocket, Boolean isV6 ); int AddDefaultUDPRULEV6(int controlSocket, int udpport, int rulenumber ); int AddDefaultUDPV6BootServer(int controlSocket ); int AddDefaultUDPCheckStateV6(int controlSocket); int AddDefaultUDPKeepStateV6(int controlSocket); int AddDefaultUDPFRAGV6(int controlSocket ); int AddDefaultUDPDenyV6(int controlSocket, Boolean loggingenabled ); int AddICMPRule( int controlSocket, Boolean loggingenabled ); int AddICMPRuleV6( int controlSocket, Boolean loggingenabled ); boolean_t checklist( long unsigned *udpportlist, long unsigned theport, int max ); int AddUserDefinedRule(int controlSocket, int ruleNumber, SInt32 start, SInt32 end, boolean_t useRange, boolean_t doUDP); int AddUserDefinedRuleV6(int controlSocket, int ruleNumber, SInt32 start, SInt32 end, boolean_t useRange, boolean_t doUDP); int WriteOutInternetSharingRule(int controlSocket, struct ip_fw *rule); boolean_t isInternetSharingRunning(int controlSocket, struct ip_fw *rule); boolean_t IsExpectedCFType(CFPropertyListRef variableInQuestion, CFTypeID expectedType); int GetPortRange(CFStringRef portString, SInt32 *start, SInt32 *end, boolean_t *useRange); void EnableLogging(boolean_t enable); void EnableBlackHole(boolean_t enable); void KillLogDaemon(); int DoCheckApplerules(); int SetFirewallRules(); int checkV4Firewall( CFBooleanRef state); int checkV6Firewall( CFBooleanRef state); int compareRulesToFile( struct ip_fw *rules, int numRules, int numExpected); int compareV6RulesToFile( struct ip6_fw *rules, int numRules, int numExpected); int UnblockPort( int controlSocket, CFDictionaryRef portDict, int *ruleNumber, Boolean isV6, Boolean doUDP ); //******************************************************************************** // main //******************************************************************************** int main(int argc, char *argv[]) { int error = SUCCESS; int c; boolean_t checkapplerules = false; /* do we want to check for Apple rules */ while ((c = getopt(argc, argv, "a")) != EOF) { switch (c) { case 'a': checkapplerules = true; break; default: error = 99; break; } } if ( checkapplerules ) { error = DoCheckApplerules(); exit( error ); } else if ( error == 99 ) { exit( 1 ); // firewall tool was called with an unknown options, exit with status = 1 } error = SetFirewallRules(); return error; } //******************************************************************************** // DoCheckApplerules //******************************************************************************** int DoCheckApplerules() { int returncode; CFBooleanRef state = (CFBooleanRef)CFPreferencesCopyValue( (CFStringRef)kStateKey, (CFStringRef)kFirewallAppSignature, (CFStringRef)kCFPreferencesAnyUser, (CFStringRef)kCFPreferencesCurrentHost); returncode = checkV4Firewall( state ); if ( returncode == kAppleRule ) { returncode = checkV6Firewall( state ); } return returncode; } //******************************************************************************** // checkV4Firewall //******************************************************************************** int checkV4Firewall( CFBooleanRef state) { int returncode = kError; struct ip_fw *rules = NULL; int dataSize = 0; int actualDataSize = 0; int numRules = 0; int controlSocket, i; int iterations = 1; // boolean_t internetSharingRunning = false; int internetSharingRunning = false; int numRulesExpected = 1; int num = 0; // open the control socket controlSocket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if( controlSocket < 0 ) { printf("Firewall Tool: Error opening socket!\n"); return kError; } // do the silly socket memory thing to figure out how much to allocate do { dataSize = (sizeof(struct ip_fw) * 10) * iterations; rules = (struct ip_fw *)realloc(rules, dataSize); if (rules == NULL ) { printf("Firewall Tool: Error getting rules! Realloc Failed!\n"); return kError; } rules->version = IP_FW_CURRENT_API_VERSION; // send down the version actualDataSize = dataSize; i = getsockopt(controlSocket, IPPROTO_IP, IP_FW_GET, rules, &actualDataSize); if( i < 0 ) { printf("Firewall Tool: Error getting rules! Not written into structure...\n"); free(rules); return kError; } iterations++; }while( dataSize == actualDataSize ); numRules = actualDataSize/sizeof(struct ip_fw); /* check for dynamic rules */ while (rules[num].fw_number < RULE_D) num++; num++; if (num * sizeof (rules[0]) != actualDataSize) { /* we have dynamic rules, ignore them when comparing rules to apple defined rules */ numRules = num; } internetSharingRunning = isInternetSharingRunning( controlSocket, rules); if( internetSharingRunning ) numRulesExpected = 2; if( state == NULL ) // one rule, corrupted file { returncode = (numRules == 1 || numRules == numRulesExpected) ? kOneRule : kThirdPartyRule; if( returncode == kThirdPartyRule ) printf("Firewall Tool: ThirdPartyRule NumRules != 1. State is not defined!\n"); } else if( CFGetTypeID(state) != CFBooleanGetTypeID() ) { returncode = (numRules == 1 || numRules == numRulesExpected) ? kOneRule : kError; if( returncode == kError ) printf("Firewall Tool: Corrupted File! State is not of type Boolean!\n"); } else if( state == kCFBooleanFalse ) // state is off but there are rules { returncode = (numRules == 1 || numRules == numRulesExpected) ? kAppleRule : kThirdPartyRule; if( returncode == kThirdPartyRule ) printf("Firewall Tool: Apple Firewall is off, but there are %d rules in IP Firewall!\n", numRules); } else if( state == kCFBooleanTrue && (numRules == 1 || numRules == numRulesExpected) ) { returncode = kOneRule; // state is true and there is only one rule printf("Firewall Tool: Apple Firewall is on, but the rules aren't there!\n"); } else // state is true and there is more then one rule { // the firewall is on so we have to compare what's in ipfw to pref file returncode = compareRulesToFile( rules, numRules, numRulesExpected); } if( rules ) free(rules); close(controlSocket); return returncode; } //******************************************************************************** // checkV6Firewall //******************************************************************************** int checkV6Firewall( CFBooleanRef state) { int returncode = kError; struct ip6_fw *rules = NULL; int dataSize = 0; int actualDataSize = 0; int numRules = 0; int controlSocket, i; int iterations = 1; int numRulesExpected = 1; // open the control socket controlSocket = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW); if( controlSocket < 0 ) { printf("Firewall: Error opening V6 socket!\n"); return kError; } // do the silly socket memory thing to figure out how much to allocate do { dataSize = (sizeof(struct ip6_fw) * 10) * iterations; rules = (struct ip6_fw *)realloc(rules, dataSize); if (rules == NULL ) { printf("Firewall: Error getting V6 rules! Realloc Failed!\n"); return kError; } rules->version = IPV6_FW_CURRENT_API_VERSION; // send down the version actualDataSize = dataSize; i = getsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_GET, rules, &actualDataSize); if( i < 0 ) { printf("Firewall: Error getting V6 rules! Not written into structure...\n"); free(rules); return kError; } iterations++; }while( dataSize == actualDataSize ); //printf("Actual Data Size: %d, struct size: %d", actualDataSize, sizeof(struct ip_fw)); numRules = actualDataSize/sizeof(struct ip6_fw); if( state == NULL ) // one rule, corrupted file { returncode = (numRules == 1 || numRules == numRulesExpected) ? kOneRule : kThirdPartyRule; if( returncode == kThirdPartyRule ) printf("ThirdParty: NumRules V6 != 1. State is not defined!"); } else if( CFGetTypeID(state) != CFBooleanGetTypeID() ) { returncode = (numRules == 1 || numRules == numRulesExpected) ? kOneRule : kError; if( returncode == kError ) printf("Corrupted File! State V6 is not of type Boolean!"); } else if( state == kCFBooleanFalse ) // state is off but there are rules { returncode = (numRules == 1 || numRules == numRulesExpected) ? kAppleRule : kThirdPartyRule; if( returncode == kThirdPartyRule ) printf("Apple Firewall is off, but there are %d rules in IP V6 Firewall!", numRules); } else if( state == kCFBooleanTrue && (numRules == 1 || numRules == numRulesExpected) ) { returncode = kOneRule; // state is true and there is only one rule printf("Apple Firewall is on, but the V6 rules aren't there!"); } else // state is true and there is more then one rule { // the firewall is on so we have to compare what's in ipfw to pref file returncode = compareV6RulesToFile( rules, numRules, numRulesExpected); } if( rules ) free(rules); close(controlSocket); return returncode; } // compareRulesToFile int compareRulesToFile( struct ip_fw *rules, int numRules, int numExpected) { int returncode = kAppleRule; int i; #ifdef oldcode int defaultRulesFound = 0; #endif int defaultExpected = NUM_DEFAULT; boolean_t nonapple = false; if( numExpected == 2 ) // we found a nat rule defaultExpected+=1; CFPropertyListRef ports = CFPreferencesCopyValue( (CFStringRef)kAllPortsKey, (CFStringRef)kFirewallAppSignature, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if( ports == NULL ) { returncode = (numRules == 1 || numRules == numExpected ) ? kOneRule : kError; if( returncode == kError ) printf("Firewall Tool: Corrupted File! No Port List defined!\n"); } else if( CFGetTypeID(ports) != CFArrayGetTypeID() ) // the pref file is corrupted.... { returncode = (numRules == 1 || numRules == numExpected ) ? kOneRule : kError; if( returncode == kError ) printf("Firewall Tool: Corrupted File! Port List is not of type Array!\n"); } for( i = 0; i < numRules; i++ ) { int ruleNumber = rules[i].fw_number; int signature = (int)rules[i].context; if ( (signature != 'AAPL') && (ruleNumber != RULE_D)) { /* ignore divert ruler */ if ((rules[i].fw_flg & IP_FW_F_COMMAND) == IP_FW_F_DIVERT) { continue; } nonapple = true; break; } #ifdef oldcode // we are expecting these rules! // RULE_8 is commented out because of radar 3066015 - reset rule causing havoc if( ruleNumber == RULE_1 || ruleNumber == RULE_2 || ruleNumber == RULE_3 || ruleNumber == RULE_4 || ruleNumber == RULE_5 || ruleNumber == RULE_6 || ruleNumber == RULE_7 /*|| ruleNumber == RULE_8 */ || ruleNumber == RULE_9 || ruleNumber == RULE_D || ruleNumber == RULE_0) { defaultRulesFound++; }else { // we only define in between RULE_1 and RULE_9 so any other number is invalid! if( (ruleNumber < RULE_1 || ruleNumber > RULE_9) && ruleNumber != RULE_D && ruleNumber != RULE_0 ) { returnString = kThirdPartyString; printf("Firewall: Non recognized rule: %d", ruleNumber); break; } else // see if this port should be listed! { NSString *portString = NULL; int startVal = rules[i].fw_uar.fw_pts[0]; int endVal = rules[i].fw_uar.fw_pts[1]; if( !endVal ) { portString = [NSString stringWithFormat: @"%d", startVal]; } else { portString = [NSString stringWithFormat: @"%d-%d", startVal, endVal]; } if( [(NSArray *)ports indexOfObject: portString] == NSNotFound ) { returnString = kThirdPartyRule; printf("Firewall: Non recognized rule: %d Port: %@", ruleNumber, portString); break; } } }// end of big else #endif }// end of for loop #ifdef oldcode // if( defaultRulesFound != defaultExpected ) { printf("Apple firewall is supposed to be on but we only found %d defaultRules!", defaultRulesFound); returnString = kThirdPartyString; } #endif if ( nonapple ) { //printf("Apple firewall is supposed to be on but we only found %d defaultRules!\n", defaultRulesFound); returncode = kThirdPartyRule; } if( ports != NULL ) CFRelease(ports); return returncode; } // compareV6RulesToFile int compareV6RulesToFile( struct ip6_fw *rules, int numRules, int numExpected) { int returncode = kAppleRule; int i; #ifdef oldcode int defaultRulesFound = 0; #endif int defaultExpected = NUM_DEFAULT; boolean_t nonapple = false; if( numExpected == 2 ) // we found a nat rule defaultExpected+=1; CFPropertyListRef ports = CFPreferencesCopyValue( (CFStringRef)kAllPortsKey, (CFStringRef)kFirewallAppSignature, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if( ports == NULL ) { returncode = (numRules == 1 || numRules == numExpected ) ? kOneRule : kError; if( returncode == kError ) printf("Firewall Tool: Corrupted File! No V6 Port List defined!"); } else if( CFGetTypeID(ports) != CFArrayGetTypeID() ) // the pref file is corrupted.... { returncode = (numRules == 1 || numRules == numExpected ) ? kOneRule : kError; if( returncode == kError ) printf("Firewall Tool: Corrupted File! V6 Port List is not of type Array!"); } for( i = 0; i < numRules; i++ ) { int ruleNumber = rules[i].fw_number; int signature = (int)rules[i].context; if ( (signature != 'AAPL') && (ruleNumber != RULE_D)) { /* ignore divert ruler */ if ((rules[i].fw_flg & IP_FW_F_COMMAND) == IP_FW_F_DIVERT) { continue; } nonapple = true; break; } #ifdef oldcode // we are expecting these rules! // RULE_8 is commented out because of radar 3066015 - reset rule causing havoc if( ruleNumber == RULE_1 || ruleNumber == RULE_2 || ruleNumber == RULE_3 || ruleNumber == RULE_4 || ruleNumber == RULE_5 || ruleNumber == RULE_6 || ruleNumber == RULE_7 /*|| ruleNumber == RULE_8 */ || ruleNumber == RULE_9 || ruleNumber == RULE_D || ruleNumber == RULE_0) { defaultRulesFound++; }else { // we only define in between RULE_1 and RULE_9 so any other number is invalid! if( (ruleNumber < RULE_1 || ruleNumber > RULE_9) && ruleNumber != RULE_D && ruleNumber != RULE_0 ) { returncode = kThirdPartyRule; printf("Firewall: Non recognized rule: %d", ruleNumber); break; } else // see if this port should be listed! { NSString *portString = NULL; int startVal = rules[i].fw_pts[0]; int endVal = rules[i].fw_pts[1]; if( !endVal ) { portString = [NSString stringWithFormat: @"%d", startVal]; } else { portString = [NSString stringWithFormat: @"%d-%d", startVal, endVal]; } if( [(NSArray *)ports indexOfObject: portString] == NSNotFound ) { returncode = kThirdPartyRule; printf("Firewall: Non recognized rule: %d Port: %@", ruleNumber, portString); break; } } }// end of big else #endif }// end of for loop #ifdef oldcode if( defaultRulesFound != defaultExpected ) { printf("Apple firewall is supposed to be on but we only found %d defaultRules!", defaultRulesFound); returncode = kThirdPartyRule; } #endif if ( nonapple ) { //printf("Apple firewall is supposed to be on but we only found %d defaultRules!\n", defaultRulesFound); returncode = kThirdPartyRule; } if( ports != NULL ) CFRelease(ports); return returncode; } //******************************************************************************** // KillLogDaemon //******************************************************************************** void KillLogDaemon() { pid_t pid; FILE *fp; /* kill logging daemon? */ /* read PID to file */ fp = fopen(LOGGERPIDPATH, "r"); if (fp != NULL) { fscanf(fp, "%d", &pid); fclose(fp); if ( kill( pid, SIGKILL )) printf("cannot kill logger daemon pid %d errno = %d\n", (int)pid, errno); unlink( LOGGERPIDPATH ); } } //******************************************************************************** // SetFirewallRules //******************************************************************************** int SetFirewallRules() { CFPropertyListRef dictionaryRef = NULL; CFPropertyListRef stateRef = NULL; int error = SUCCESS; Boolean udpenabled; Boolean loggingenabled; Boolean stealthenabled; char *argv[2]; struct stat sb; /* setting Apple Rules */ do { // read in the firewall configuration file error = ReadFile(&dictionaryRef, &stateRef, &udpenabled, &loggingenabled, &stealthenabled ); if( error != SUCCESS ) { printf("Firewall Tool: Error, Error reading in file!\n"); break; } if ( stateRef == kCFBooleanTrue ) { /* Firewall is on */ /* check stealth mode */ EnableBlackHole( stealthenabled ); EnableLogging( loggingenabled ); if( loggingenabled ) /* logging enabled, do logging */ { pid_t pid; /* start up logging deamon if it's not already running */ /* check for running deamon */ if ( stat(LOGGERPIDPATH, &sb) ) { if (errno == ENOENT) { pid = fork(); switch (pid) { case -1 : { /* if error */ printf("fork() failed, cannot start up logger daemon %d\n", errno); break; } case 0: { /* if child */ argv[0]=LOGGERPROGPATH; argv[1]=NULL; (void)execv( LOGGERPROGPATH, argv); printf("child::execv failed, cannot start up logger daemon errno = %d\n", errno); exit(1); } default: waitpid( pid, NULL, 0); break; } } } }else KillLogDaemon(); }else { /* Firewall is off, turn off logging */ EnableLogging( false ); /* turn off stealth mode */ EnableBlackHole( false ); stealthenabled = false; /* set stealthenabled to false if firewall is not enabled, reset ICMP rule */ KillLogDaemon(); } error = DoV4Firewall(dictionaryRef, stateRef, udpenabled, loggingenabled, stealthenabled); if( error != SUCCESS ) { printf("Firewall Tool: Error %d, Error setting up V4 Firewall!\n", error); } error = DoV6Firewall(dictionaryRef, stateRef, udpenabled, loggingenabled, stealthenabled); if( error != SUCCESS ) { printf("Firewall Tool: Error %d, Error setting up V6 Firewall!\n", error); } }while(false); if( dictionaryRef ) CFRelease(dictionaryRef); if( stateRef ) CFRelease(stateRef); return error; } //******************************************************************************** // DoV4Firewall //******************************************************************************** int DoV4Firewall(CFPropertyListRef dictionaryRef, CFPropertyListRef stateRef, Boolean udpenabled, Boolean loggingenabled, Boolean stealthenabled) { int controlSocket; int error = SUCCESS; boolean_t internetSharingOn = false; struct ip_fw rule; do { // open the socket controlSocket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if( controlSocket < 0 ) { printf("Firewall Tool: Error opening socket\n"); error = ERROR; break; } memset(&rule, 0, sizeof(rule)); internetSharingOn = isInternetSharingRunning( controlSocket, &rule); // flush the old rules error = FlushOldRules(controlSocket); if( error != SUCCESS ) { printf("Firewall Tool: Error Flusing Old Rules!\n"); break; } if( internetSharingOn ) error = WriteOutInternetSharingRule(controlSocket, &rule); // do something with error or keep going? // write to the sockets based on the rules if( stateRef == kCFBooleanTrue ) error = WriteRulesToSockets(controlSocket, dictionaryRef, false, udpenabled, loggingenabled, stealthenabled); if( error != SUCCESS ) { printf("Firewall Tool: Error writing out rules! Attempting to Flush...\n"); FlushOldRules(controlSocket); // if that doesn't work try to flush all... break; } }while(false); if( controlSocket >= 0 ) close(controlSocket); return error; } //******************************************************************************** // DoV6Firewall //******************************************************************************** int DoV6Firewall(CFPropertyListRef dictionaryRef, CFPropertyListRef stateRef, Boolean udpenabled, Boolean loggingenabled, Boolean stealthenabled) { int controlSocket; int error = SUCCESS; do { // open the socket controlSocket = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW); if( controlSocket < 0 ) { printf("Firewall Tool: Error opening socket for V6!\n"); error = ERROR; break; } // flush the old rules error = FlushOldRulesV6(controlSocket); if( error != SUCCESS ) { printf("Firewall Tool: Error Flusing Old V6 Rules!\n"); break; } // write to the sockets based on the rules if( stateRef == kCFBooleanTrue ) error = WriteRulesToSockets(controlSocket, dictionaryRef, true, udpenabled, loggingenabled, stealthenabled); if( error != SUCCESS ) { printf("Firewall Tool: Error writing out V6 rules! Attempting to Flush...\n"); FlushOldRulesV6(controlSocket); // if that doesn't work try to flush all... break; } }while(false); if( controlSocket >= 0 ) close(controlSocket); return error; } //******************************************************************************** // FlushOldRules //******************************************************************************** int FlushOldRules(int controlSocket) { int i; struct ip_fw rule; rule.version = IP_FW_CURRENT_API_VERSION; // send down the version // flush the old rules (all of them!) i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_FLUSH, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error flushing rules\n"); return ERROR; } return SUCCESS; } //******************************************************************************** // FlushOldRulesV6 //******************************************************************************** int FlushOldRulesV6(int controlSocket) { int i; struct ip6_fw rule; rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version // flush the old rules (all of them!) i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_FLUSH, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error flushing rules (V6) \n"); return ERROR; } return SUCCESS; } //******************************************************************************** // ReadFile //******************************************************************************** int ReadFile(CFPropertyListRef *dictionaryRef, CFPropertyListRef *stateRef, Boolean *UDPenabled, Boolean *LOGGINGenabled, Boolean *STEALTHenabled ) { CFPropertyListRef udpenabledRef, logenabledRef, stealthenabledRef; int value; *dictionaryRef = NULL; *stateRef = NULL; logenabledRef = NULL; udpenabledRef = NULL; stealthenabledRef = NULL; *UDPenabled = false; // set UDP firewall default value to disabled *LOGGINGenabled = LOGDEFAULTVALUE; // default value if key is missing *STEALTHenabled = STEALTHDEFAULTVALUE; // default value if key is missing *dictionaryRef = CFPreferencesCopyValue( kFirewallKey, kFirewallAppSignature, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if( !IsExpectedCFType(*dictionaryRef, CFDictionaryGetTypeID()) ) { printf("Firewall Tool: Error, kFirewallKey does not return a CFDictionary\n"); return ERROR; } *stateRef = CFPreferencesCopyValue( kStateKey, kFirewallAppSignature, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if( !IsExpectedCFType(*stateRef, CFBooleanGetTypeID()) ) { printf("Firewall Tool: Error, kStateKey does not return a CFBoolean\n"); return ERROR; } logenabledRef = CFPreferencesCopyValue( kLogEnableKey, kFirewallAppSignature, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if ( logenabledRef != NULL ) { if( !IsExpectedCFType( logenabledRef, CFNumberGetTypeID()) ) { printf("Firewall Tool: Error, logenabledRef does not return the correct type.\n"); return ERROR; } if( !CFNumberGetValue((CFNumberRef)logenabledRef, kCFNumberIntType, &value) ) { printf("Firewall Tool: Error, could not convert CFNumber to LOGGINGenabled value\n"); } else if ( value == 0 ) *LOGGINGenabled = false; else if ( value == 1 ) *LOGGINGenabled = true; CFRelease(logenabledRef); } stealthenabledRef = CFPreferencesCopyValue( kStealthEnableKey, kFirewallAppSignature, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if ( stealthenabledRef != NULL ) { if( !IsExpectedCFType( stealthenabledRef, CFNumberGetTypeID()) ) { printf("Firewall Tool: Error, stealthenabledRef does not return the correct type.\n"); return ERROR; } if( !CFNumberGetValue((CFNumberRef)stealthenabledRef, kCFNumberIntType, &value) ) { printf("Firewall Tool: Error, could not convert CFNumber to STEALTHenabled value\n"); } else if ( value == 0 ) *STEALTHenabled = false; else if ( value == 1 ) *STEALTHenabled = true; CFRelease(stealthenabledRef); } udpenabledRef = CFPreferencesCopyValue( kUDPEnableKey, kFirewallAppSignature, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); if ( udpenabledRef != NULL ) { if( !IsExpectedCFType( udpenabledRef, CFNumberGetTypeID()) ) { printf("Firewall Tool: Error, udpenabledRef does not return the correct type.\n"); return ERROR; } if( !CFNumberGetValue((CFNumberRef)udpenabledRef, kCFNumberIntType, &value) ) { printf("Firewall Tool: Error, could not convert CFNumber to UDPenabled value\n"); } else if ( value == 1 ) *UDPenabled = true; //printf("Firewall Tool: eabledUDP value = %d\n", value); //printf("Firewall Tool: udp is enabled\n"); CFRelease(udpenabledRef); } return SUCCESS; } //******************************************************************************** // UnblockPort //******************************************************************************** int UnblockPort( int controlSocket, CFDictionaryRef portDict, int *ruleNumber, Boolean isV6, Boolean doUDP ) { // if the user wants this port to be allowed CFPropertyListRef arrayOfPorts = NULL; CFPropertyListRef portString = NULL; SInt32 start, end; boolean_t useRange; int j, portCount = 0; if ( doUDP ) arrayOfPorts = CFDictionaryGetValue(portDict, kUDPPortKey); else arrayOfPorts = CFDictionaryGetValue(portDict, kPortKey); if ( arrayOfPorts == NULL ) // no port or udpport list, try next one return SUCCESS; if( !IsExpectedCFType(arrayOfPorts, CFArrayGetTypeID()) ) { printf("Firewall Tool: Error, kPortKey did not return a CFArray\n"); return ERROR; } if( arrayOfPorts ) portCount = CFArrayGetCount((CFArrayRef)arrayOfPorts); for( j = 0; j < portCount; j++) { portString = CFArrayGetValueAtIndex((CFArrayRef)arrayOfPorts, j); if( !IsExpectedCFType(portString, CFStringGetTypeID()) ) { printf("Firewall Tool: Error, port array did not return a CFString value\n"); return ERROR; } // figure out if its one port or if its a port range if( GetPortRange((CFStringRef)portString, &start, &end, &useRange) == SUCCESS ) { if( !isV6 ) // set up the v4 user defined rules { // add the rule if( AddUserDefinedRule(controlSocket, *ruleNumber, start, end, useRange, doUDP) != SUCCESS) { printf("Firewall Tool: Error, could not add user defined rule!\n"); return ERROR; } } else // set up the v6 user defined rules { // add the rule, for the v6 firewall if( AddUserDefinedRuleV6(controlSocket, *ruleNumber, start, end, useRange, doUDP) != SUCCESS) { printf("Firewall Tool: Error, could not add user defined rule!\n"); return ERROR; } } *ruleNumber+=10; } portString = NULL; } return SUCCESS; } //******************************************************************************** // WriteRulesToSockets //******************************************************************************** int WriteRulesToSockets(int controlSocket, CFPropertyListRef dictionaryRef, Boolean isV6, Boolean udpenabled, Boolean loggingenabled, Boolean stealthenabled) { int i; CFIndex count = 0; CFDictionaryRef *values = NULL; int error; int ruleNumber = RULE_START; int udpruleNumber = UDPUSERDEFINEDSTARTS; // we already flushed ipfw so its currently off! // separate out the v6 and v4 calls to this function if( !isV6 ) error = AddDefaultRules(controlSocket, udpenabled, loggingenabled, stealthenabled); else error = AddDefaultRulesV6(controlSocket, udpenabled, loggingenabled, stealthenabled); if( error != SUCCESS ) { printf("Firewall Tool: Error adding default rules!\n"); return ERROR; } if( dictionaryRef ) // don't call this if dictionary could be NULL count = CFDictionaryGetCount(dictionaryRef); if( count > 0 ) { values = CFAllocatorAllocate(NULL, count * sizeof(CFDictionaryRef), 0); if( values == NULL ) { printf("Firewall Tool: CFAllocatorAllocate failed!\n"); return ERROR; } else { CFDictionaryGetKeysAndValues(dictionaryRef, NULL, (const void **)values); } } for( i = 0; i < count; i++) { CFDictionaryRef portDict = values[i]; CFPropertyListRef enabled; int value; enabled = CFDictionaryGetValue(portDict, kEnableKey); if( !IsExpectedCFType(enabled, CFNumberGetTypeID()) ) { printf("Firewall Tool: Error, kEnableKey did not return a CFNumber\n"); CFAllocatorDeallocate(NULL, values); return ERROR; } // conversion to a numeric useable value if( !CFNumberGetValue((CFNumberRef)enabled, kCFNumberIntType, &value) ) { printf("Firewall Tool: Error, could not convert CFNumber to enabled value\n"); CFAllocatorDeallocate(NULL, values); return ERROR; } if ( value ) { if ( UnblockPort( controlSocket, portDict, &ruleNumber, isV6, false )) // check TCP port { CFAllocatorDeallocate(NULL, values); return ERROR; } if ( udpenabled ) { if ( UnblockPort( controlSocket, portDict, &udpruleNumber, isV6, true )) // check UDP port { CFAllocatorDeallocate(NULL, values); return ERROR; } } } } CFAllocatorDeallocate(NULL, values); return SUCCESS; } //******************************************************************************** // AddDefaultRules //******************************************************************************** int AddDefaultRules(int controlSocket, Boolean doUDP, Boolean loggingenabled, Boolean stealthenabled) { int error = SUCCESS; int i; do { error = AddDefaultRule1LoopBack(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule2DiscardLoopbackIn(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule3DiscardLoopbackOut(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule4DiscardBroadcastMulticast(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule5DiscardTCPBroadcastMulticast(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule6OutboundOK(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule7KeepEstablished(controlSocket); if( error != SUCCESS ) break; // RULE_8 is commented out because of radar 3066015 - reset rule causing havoc // error = AddDefaultRule8ResetTCPInSetup(controlSocket); // if( error != SUCCESS ) break; error = AddDefaultRule9DenyTCP(controlSocket, loggingenabled); if( error != SUCCESS ) break; if ( stealthenabled ) { error = AddICMPRule( controlSocket, loggingenabled ); if( error != SUCCESS ) break; } /* add default UDP rules */ if ( doUDP ) { for ( i= 0; i < MAXDEFAULTUDPRULES; i++ ){ error = AddDefaultUDPRULE( controlSocket, DEFAULTUDPSET.set[i].theport, DEFAULTUDPSET.set[i].therule); if ( error != SUCCESS ) break; } error = AddDefaultUDPBootServer( controlSocket); if ( error != SUCCESS ) break; error = AddDefaultUDPMDNS( controlSocket); if ( error != SUCCESS ) break; error = AddDefaultUDPKeepState( controlSocket); if ( error != SUCCESS ) break; error = AddDefaultUDPFRAG( controlSocket ); if ( error != SUCCESS ) break; #ifdef doRPC error = AddDefaultUDPRPCRULE( controlSocket, false); if ( error != SUCCESS ) break; #endif error = AddDefaultUDPDeny( controlSocket, loggingenabled ); if ( error != SUCCESS ) break; } }while(false); return error; } //******************************************************************************** // AddDefaultRulesV6 //******************************************************************************** int AddDefaultRulesV6(int controlSocket, Boolean doUDP, Boolean loggingenabled, Boolean stealthenabled) { int error = SUCCESS; int i; do { error = AddDefaultRule1LoopBackV6(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule2DiscardLoopbackInV6(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule3DiscardLoopbackOutV6(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule4DiscardBroadcastMulticastV6(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule5DiscardTCPBroadcastMulticastV6(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule6OutboundOKV6(controlSocket); if( error != SUCCESS ) break; error = AddDefaultRule7KeepEstablishedV6(controlSocket); if( error != SUCCESS ) break; // RULE_8 is commented out because of radar 3066015 - reset rule causing havoc // error = AddDefaultRule8ResetTCPInSetupV6(controlSocket); // if( error != SUCCESS ) break; error = AddDefaultRule9DenyTCPV6(controlSocket, loggingenabled); if( error != SUCCESS ) break; if ( stealthenabled ) { error = AddICMPRuleV6( controlSocket, loggingenabled ); if( error != SUCCESS ) break; } /* add default UDP rules */ if ( doUDP ) { for ( i= 0; i < MAXDEFAULTUDPRULES; i++ ){ error = AddDefaultUDPRULEV6( controlSocket, DEFAULTUDPSET.set[i].theport, DEFAULTUDPSET.set[i].therule); if ( error != SUCCESS ) break; } #ifdef later error = AddDefaultUDPV6BootServer( controlSocket); if ( error != SUCCESS ) break; error = AddDefaultUDPCheckStateV6( controlSocket); if ( error != SUCCESS ) break; error = AddDefaultUDPKeepStateV6( controlSocket); if ( error != SUCCESS ) break; #endif error = AddDefaultUDPFRAGV6( controlSocket ); if ( error != SUCCESS ) break; #ifdef doRPC error = AddDefaultUDPRPCRULE( controlSocket, true ); if ( error != SUCCESS ) break; #endif error = AddDefaultUDPDenyV6( controlSocket, loggingenabled ); if ( error != SUCCESS ) break; } }while(false); return error; } //******************************************************************************** // AddDefaultRule1LoopBack //******************************************************************************** int AddDefaultRule1LoopBack(int controlSocket) { struct ip_fw rule; int i; // ipfw add 2000 allow all from any to any via lo0 memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_1; // rule # rule.fw_flg |= IP_FW_F_ACCEPT; // allow rule.fw_prot = IPPROTO_IP; // ip strcpy(rule.fw_in_if.fu_via_if.name, "lo"); // via lo0 rule.fw_in_if.fu_via_if.unit = -1; strcpy(rule.fw_out_if.fu_via_if.name, "lo"); rule.fw_out_if.fu_via_if.unit = -1; rule.fw_flg |= (IP_FW_F_IIFACE | IP_FW_F_OIFACE); // check both interfaces (in & out) rule.fw_flg |= (IP_FW_F_IIFNAME | IP_FW_F_OIFNAME); // interface to check specified by name rule.fw_flg |= (IP_FW_F_OUT | IP_FW_F_IN); // packets both directions i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_1); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule1LoopBackV6 //******************************************************************************** int AddDefaultRule1LoopBackV6(int controlSocket) { struct ip6_fw rule; int i; // ipfw add 2000 allow all from any to any via lo0 memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_1; // rule # rule.fw_flg |= IPV6_FW_F_ACCEPT; // allow rule.fw_prot = IPPROTO_IPV6; // ip strcpy(rule.fw_in_if.fu_via_if.name, "lo"); // via lo0 rule.fw_in_if.fu_via_if.unit = -1; strcpy(rule.fw_out_if.fu_via_if.name, "lo"); rule.fw_out_if.fu_via_if.unit = -1; rule.fw_flg |= (IPV6_FW_F_IIFACE | IPV6_FW_F_OIFACE); // check both interfaces (in & out) rule.fw_flg |= (IPV6_FW_F_IIFNAME | IPV6_FW_F_OIFNAME); // interface to check specified by name rule.fw_flg |= (IPV6_FW_F_OUT | IPV6_FW_F_IN); // packets both directions i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding V6 rule: %d\n", RULE_1); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule2DiscardLoopbackIn //******************************************************************************** int AddDefaultRule2DiscardLoopbackIn(int controlSocket) { struct ip_fw rule; int i; // ipfw add 2010 deny all from 127.0.0.0/8 to any in memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_2; // rule # rule.fw_flg |= IP_FW_F_DENY; // deny //rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_IP; // ip rule.fw_src.s_addr = htonl(0x7F000000); // 127.0.0.0 rule.fw_smsk.s_addr = htonl(0xFF000000); // /8 rule.fw_flg |= IP_FW_F_IN; // packets both directions i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_2); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule2DiscardLoopbackInV6 //******************************************************************************** int AddDefaultRule2DiscardLoopbackInV6(int controlSocket) { struct ip6_fw rule; int i; // ip6fw add 2010 deny all from ::1 to any in memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; rule.context = (void*)'AAPL'; rule.fw_number = RULE_2; // rule # rule.fw_flg |= IPV6_FW_F_DENY; // deny //rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_IPV6; // ip // hmm, isn't this nice rule.fw_src.__u6_addr.__u6_addr8[0] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[1] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[2] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[3] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[4] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[5] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[6] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[7] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[8] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[9] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[10] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[11] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[12] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[13] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[14] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[15] = 0x01; rule.fw_smsk.__u6_addr.__u6_addr8[0] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[1] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[2] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[3] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[4] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[5] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[6] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[7] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[8] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[9] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[10] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[11] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[12] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[13] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[14] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[15] = 0xFF; rule.fw_flg |= IPV6_FW_F_IN; // in i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_2); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule3DiscardLoopbackOut //******************************************************************************** int AddDefaultRule3DiscardLoopbackOut(int controlSocket) { struct ip_fw rule; int i; // ipfw add 2020 deny all from any to 127.0.0.0/8 in memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_3; // rule # rule.fw_flg |= IP_FW_F_DENY; // deny //rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_IP; // ip rule.fw_dst.s_addr = htonl(0x7F000000); // 127.0.0.0 rule.fw_dmsk.s_addr = htonl(0xFF000000); // /8 rule.fw_flg |= IP_FW_F_IN; // packets both directions i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_3); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule3DiscardLoopbackOutV6 //******************************************************************************** int AddDefaultRule3DiscardLoopbackOutV6(int controlSocket) { struct ip6_fw rule; int i; // ip6fw add 2020 deny all from any to ::1 in memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; rule.context = (void*)'AAPL'; rule.fw_number = RULE_3; // rule # rule.fw_flg |= IPV6_FW_F_DENY; // deny //rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_IPV6; // ip // hmm, isn't this nice rule.fw_dst.__u6_addr.__u6_addr8[0] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[1] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[2] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[3] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[4] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[5] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[6] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[7] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[8] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[9] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[10] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[11] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[12] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[13] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[14] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[15] = 0x01; rule.fw_dmsk.__u6_addr.__u6_addr8[0] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[1] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[2] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[3] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[4] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[5] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[6] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[7] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[8] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[9] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[10] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[11] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[12] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[13] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[14] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[15] = 0xFF; rule.fw_flg |= IPV6_FW_F_IN; // in i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_3); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule4DiscardBroadcastMulticast //******************************************************************************** int AddDefaultRule4DiscardBroadcastMulticast(int controlSocket) { struct ip_fw rule; int i; // ipfw add 2030 deny all from 224.0.0.0/3 to any in memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_4; // rule # rule.fw_flg |= IP_FW_F_DENY; // deny //rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_IP; // ip rule.fw_src.s_addr = htonl(0xE0000000); // 224.0.0.0 rule.fw_smsk.s_addr = htonl(0xE0000000); // /3 rule.fw_flg |= IP_FW_F_IN; // packets both directions i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_4); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule4DiscardBroadcastMulticastV6 //******************************************************************************** int AddDefaultRule4DiscardBroadcastMulticastV6(int controlSocket) { struct ip6_fw rule; int i; // ip6fw add 2030 deny all from FF::/8 to any in memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; rule.context = (void*)'AAPL'; rule.fw_number = RULE_4; // rule # rule.fw_flg |= IPV6_FW_F_DENY; // allow //rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_IPV6; // ip // hmm, isn't this nice rule.fw_src.__u6_addr.__u6_addr8[0] = 0xFF; rule.fw_src.__u6_addr.__u6_addr8[1] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[2] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[3] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[4] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[5] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[6] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[7] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[8] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[9] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[10] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[11] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[12] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[13] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[14] = 0x00; rule.fw_src.__u6_addr.__u6_addr8[15] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[0] = 0xFF; rule.fw_smsk.__u6_addr.__u6_addr8[1] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[2] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[3] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[4] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[5] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[6] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[7] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[8] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[9] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[10] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[11] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[12] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[13] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[14] = 0x00; rule.fw_smsk.__u6_addr.__u6_addr8[15] = 0x00; rule.fw_flg |= IPV6_FW_F_IN; // packets both directions i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_4); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule5DiscardTCPBroadcastMulticast //******************************************************************************** int AddDefaultRule5DiscardTCPBroadcastMulticast(int controlSocket) { struct ip_fw rule; int i; // ipfw add 2040 deny tcp from any to 224.0.0.0/3 in memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_5; // rule # rule.fw_flg |= IP_FW_F_DENY; // deny //rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_TCP; // ip rule.fw_dst.s_addr = htonl(0xE0000000); // 224.0.0.0 rule.fw_dmsk.s_addr = htonl(0xE0000000); // /3 rule.fw_flg |= IP_FW_F_IN; // packets both directions i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_5); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule5DiscardTCPBroadcastMulticastV6 //******************************************************************************** int AddDefaultRule5DiscardTCPBroadcastMulticastV6(int controlSocket) { struct ip6_fw rule; int i; // ip6fw add 2040 deny tcp from any to FF::/8 in memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; rule.context = (void*)'AAPL'; rule.fw_number = RULE_5; // rule # rule.fw_flg |= IPV6_FW_F_DENY; // deny //rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_TCP; // tcp // hmm, isn't this nice rule.fw_dst.__u6_addr.__u6_addr8[0] = 0xFF; rule.fw_dst.__u6_addr.__u6_addr8[1] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[2] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[3] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[4] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[5] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[6] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[7] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[8] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[9] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[10] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[11] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[12] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[13] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[14] = 0x00; rule.fw_dst.__u6_addr.__u6_addr8[15] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[0] = 0xFF; rule.fw_dmsk.__u6_addr.__u6_addr8[1] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[2] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[3] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[4] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[5] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[6] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[7] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[8] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[9] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[10] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[11] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[12] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[13] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[14] = 0x00; rule.fw_dmsk.__u6_addr.__u6_addr8[15] = 0x00; rule.fw_flg |= IPV6_FW_F_IN; // in i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_5); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule6OutboundOK //******************************************************************************** int AddDefaultRule6OutboundOK(int controlSocket) { struct ip_fw rule; int i; // ipfw add 2010 allow tcp from any to any out memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_6; // rule # rule.fw_flg |= IP_FW_F_ACCEPT; // allow rule.fw_prot = IPPROTO_TCP; // tcp rule.fw_flg |= IP_FW_F_OUT; // outbound // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_6); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule6OutboundOKV6 //******************************************************************************** int AddDefaultRule6OutboundOKV6(int controlSocket) { struct ip6_fw rule; int i; // ipfw add 2010 allow tcp from any to any out memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_6; // rule # rule.fw_flg |= IPV6_FW_F_ACCEPT; // allow rule.fw_prot = IPPROTO_TCP; // tcp rule.fw_flg |= IPV6_FW_F_OUT; // outbound // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding V6 rule: %d\n", RULE_6); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule7KeepEstablished //******************************************************************************** int AddDefaultRule7KeepEstablished(int controlSocket) { struct ip_fw rule; int i; // ipfw add 2020 allow tcp from any to any established memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_7; // rule # rule.fw_flg |= IP_FW_F_ACCEPT; // allow rule.fw_prot = IPPROTO_TCP; // tcp #ifdef IP_FW_IF_TCPEST rule.fw_ipflg = IP_FW_IF_TCPEST; // new #endif //rule.fw_tcpf |= IP_FW_TCPF_ESTAB; // old (erase later) rule.fw_flg |= (IP_FW_F_OUT | IP_FW_F_IN); // any to any // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_7); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule7KeepEstablishedV6 //******************************************************************************** int AddDefaultRule7KeepEstablishedV6(int controlSocket) { struct ip6_fw rule; int i; // ipfw add 2020 allow tcp from any to any established memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_7; // rule # rule.fw_flg |= IPV6_FW_F_ACCEPT; // allow rule.fw_prot = IPPROTO_TCP; // tcp rule.fw_ipflg = IPV6_FW_IF_TCPEST; // new //rule.fw_tcpf |= IP_FW_TCPF_ESTAB; // old (erase later) rule.fw_flg |= (IPV6_FW_F_OUT | IPV6_FW_F_IN); // any to any // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding V6 rule: %d\n", RULE_7); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule9DenyTCP //******************************************************************************** int AddDefaultRule9DenyTCP(int controlSocket, Boolean loggingenabled) { struct ip_fw rule; int i; // ipfw add 12150 deny tcp from any to any memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_9; // rule # rule.fw_flg |= IP_FW_F_DENY; // deny if ( loggingenabled ) rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_TCP; // tcp rule.fw_flg |= (IP_FW_F_OUT | IP_FW_F_IN); // any to any // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_9); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultRule9DenyTCPV6 //******************************************************************************** int AddDefaultRule9DenyTCPV6(int controlSocket, Boolean loggingenabled) { struct ip6_fw rule; int i; // ipfw add 12150 deny tcp from any to any memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = RULE_9; // rule # rule.fw_flg |= IPV6_FW_F_DENY; // deny if ( loggingenabled ) rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_TCP; // tcp rule.fw_flg |= (IPV6_FW_F_OUT | IPV6_FW_F_IN); // any to any // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding V6 rule: %d\n", RULE_9); return i; } return SUCCESS; } /**************************************** UDP RULES ******************************/ //******************************************************************************** // AddDefaultUDPRULE //******************************************************************************** int AddDefaultUDPRULE(int controlSocket, int udpport, int rulenumber ) { struct ip_fw rule; int i; memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = rulenumber; rule.fw_flg |= IP_FW_F_ACCEPT; rule.fw_prot = IPPROTO_UDP; rule.fw_uar.fw_pts[0] = udpport; IP_FW_SETNDSTP(&rule, 1); rule.fw_flg |= IP_FW_F_IN; i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", rulenumber, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPBootServer //******************************************************************************** int AddDefaultUDPBootServer( int controlSocket) { struct ip_fw rule; int i; // add allow udp from me to any out keep-state memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEBOOTSERVER; // rule # rule.fw_flg |= IP_FW_F_ACCEPT; // allow keep state rule.fw_prot = IPPROTO_UDP; // udp rule.fw_uar.fw_pts[0] = BOOTSERVERPORT; IP_FW_SETNSRCP(&rule, 1); rule.fw_flg |= (IP_FW_F_DME | IP_FW_F_IN); // dst me i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEBOOTSERVER, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPMDNS //******************************************************************************** int AddDefaultUDPMDNS( int controlSocket) { struct ip_fw rule; int i; // add allow udp from me to any out keep-state memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEMDNSRESPONSE; // rule # rule.fw_flg |= IP_FW_F_ACCEPT; // allow keep state rule.fw_prot = IPPROTO_UDP; // udp rule.fw_uar.fw_pts[0] = MDNSPORT; IP_FW_SETNSRCP(&rule, 1); rule.fw_flg |= (IP_FW_F_DME | IP_FW_F_IN); // dst me i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEMDNSRESPONSE, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPCheckState //******************************************************************************** int AddDefaultUDPCheckState(int controlSocket ) { struct ip_fw rule; int i; // add check-state memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULECHECKSTATE; // rule # rule.fw_flg |= (IP_FW_F_CHECK_S | IP_FW_F_ACCEPT); // accept check state //rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_UDP; // udp i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULECHECKSTATE, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPKeepState //******************************************************************************** int AddDefaultUDPKeepState(int controlSocket ) { struct ip_fw rule; int i; // add allow udp from me to any out keep-state memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEKEEPSTATE; // rule # rule.fw_flg |= (IP_FW_F_KEEP_S | IP_FW_F_ACCEPT); // allow keep state //rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_UDP; // udp rule.fw_flg |= (IP_FW_F_SME | IP_FW_F_OUT); // source me to any i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEKEEPSTATE, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPFRAG //******************************************************************************** int AddDefaultUDPFRAG(int controlSocket ) { struct ip_fw rule; int i; // add allow udp from any to any in frag memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEDEFAULTFRAG; // rule # rule.fw_flg |= IP_FW_F_ACCEPT; // deny //rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_UDP; // udp rule.fw_flg |= (IP_FW_F_IN | IP_FW_F_FRAG); // any to in frag i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEDEFAULTFRAG, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPDeny //******************************************************************************** int AddDefaultUDPDeny(int controlSocket, Boolean loggingenabled ) { struct ip_fw rule; int i; // ipfw add deny udp from any to any in memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEDEFAULTDENY; // rule # rule.fw_flg |= IP_FW_F_DENY; // deny if (loggingenabled) rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_UDP; // udp rule.fw_flg |= IP_FW_F_IN; // any to any i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEDEFAULTDENY, errno); return i; } return SUCCESS; } //******************************************************************************** // checklist //******************************************************************************** boolean_t checklist( long unsigned *udpportlist, long unsigned theport, int max ) { int i; for ( i=0; ipml_next) { if (head->pml_map.pm_prot == IPPROTO_UDP) { if ( checklist( udpportlist, head->pml_map.pm_port, index )) { // add UDP port to list if it is not already in the list udpportlist[index++] = head->pml_map.pm_port; } } } // add all RPC ports to FireWall rule if ( isV6 ) { for ( i = 0; i < index; i++){ error = AddDefaultUDPRULEV6( controlSocket, udpportlist[i], UDPRPCRULESTART+i); if ( error != SUCCESS ) break; } } else { for ( i = 0; i < index; i++){ error = AddDefaultUDPRULE( controlSocket, udpportlist[i], UDPRPCRULESTART+i); if ( error != SUCCESS ) break; } } return error; } /*********************** ICMP ******************************************/ //******************************************************************************** // AddICMPRule //******************************************************************************** int AddICMPRule( int controlSocket, Boolean loggingenabled) { struct ip_fw rule; int i; // ipfw add 12150 deny tcp from any to any memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = ICMPECHOREQRULE; // rule # rule.fw_flg |= IP_FW_F_DENY; // deny if ( loggingenabled ) rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_ICMP; // icmp rule.fw_uar.fw_icmptypes[ICMP_ECHO / (sizeof(unsigned) * 8)] |= 1 << (ICMP_ECHO % (sizeof(unsigned) * 8)); rule.fw_flg |= IP_FW_F_ICMPBIT; // ICMP type rule.fw_flg |= (IP_FW_F_IN | IP_FW_F_DME); // any to me // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", RULE_9); return i; } return SUCCESS; } /**************************************** V6 UDP RULES ******************************/ //******************************************************************************** // AddDefaultUDPRULEV6 //******************************************************************************** int AddDefaultUDPRULEV6(int controlSocket, int udpport, int rulenumber ) { struct ip6_fw rule; int i; memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = rulenumber; rule.fw_flg |= IPV6_FW_F_ACCEPT; rule.fw_prot = IPPROTO_UDP; rule.fw_pts[0] = udpport; IPV6_FW_SETNDSTP(&rule, 1); rule.fw_flg |= IPV6_FW_F_IN; i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", rulenumber, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPV6BootServer //******************************************************************************** int AddDefaultUDPV6BootServer( int controlSocket) { struct ip6_fw rule; int i; // add allow udp from me to any out keep-state memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEBOOTSERVER; // rule # rule.fw_flg |= IPV6_FW_F_ACCEPT; // allow keep state rule.fw_prot = IPPROTO_UDP; // udp rule.fw_pts[0] = BOOTSERVERPORT; IPV6_FW_SETNSRCP(&rule, 1); //rule.fw_flg |= (IPV6_FW_F_DME | IPV6_FW_F_IN); // dst me rule.fw_flg |= ( IPV6_FW_F_IN); // dst me i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEBOOTSERVER, errno); return i; } return SUCCESS; } #ifdef later //******************************************************************************** // AddDefaultUDPCheckStateV6 //******************************************************************************** int AddDefaultUDPCheckStateV6(int controlSocket ) { struct ip6_fw rule; int i; // add check-state memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULECHECKSTATE; // rule # /* no check state rule for ipv6 */ rule.fw_flg |= (IPV6_FW_F_CHECK_S | IPV6_FW_F_ACCEPT); // accept check state //rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_UDP; // udp i = setsockopt(controlSocket, IPPROTO_IPV6, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULECHECKSTATE, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPKeepStateV6 //******************************************************************************** int AddDefaultUDPKeepStateV6(int controlSocket ) { struct ip6_fw rule; int i; // add allow udp from me to any out keep-state memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEKEEPSTATE; // rule # /* no keep state rule for ipv6 */ rule.fw_flg |= (IPV6_FW_F_KEEP_S | IPV6_FW_F_ACCEPT); // allow keep state //rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_UDP; // udp rule.fw_flg |= (IPV6_FW_F_SME | IPV6_FW_F_OUT); // source me to any i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEKEEPSTATE, errno); return i; } return SUCCESS; } #endif //******************************************************************************** // AddDefaultUDPFRAGV6 //******************************************************************************** int AddDefaultUDPFRAGV6(int controlSocket ) { struct ip6_fw rule; int i; // add allow udp from any to any in frag memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEDEFAULTFRAG; // rule # rule.fw_flg |= IPV6_FW_F_ACCEPT; // deny //rule.fw_flg |= IP_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_UDP; // udp rule.fw_flg |= (IPV6_FW_F_IN | IPV6_FW_F_FRAG); // any to in frag i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEDEFAULTFRAG, errno); return i; } return SUCCESS; } //******************************************************************************** // AddDefaultUDPDenyV6 //******************************************************************************** int AddDefaultUDPDenyV6(int controlSocket, Boolean loggingenabled ) { struct ip6_fw rule; int i; // ipfw add deny udp from any to any in memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = UDPRULEDEFAULTDENY; // rule # rule.fw_flg |= IPV6_FW_F_DENY; // deny if ( loggingenabled ) rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_UDP; // udp rule.fw_flg |= IPV6_FW_F_IN; // any to any i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d, errno = %d\n", UDPRULEDEFAULTDENY, errno); return i; } return SUCCESS; } //******************************************************************************** // AddUserDefinedRule //******************************************************************************** int AddUserDefinedRule(int controlSocket, int ruleNumber, SInt32 start, SInt32 end, boolean_t useRange, boolean_t doUDP) { struct ip_fw rule; int i; memset(&rule, 0, sizeof(rule)); rule.version = IP_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = ruleNumber; rule.fw_flg |= IP_FW_F_ACCEPT; if (doUDP) rule.fw_prot = IPPROTO_UDP; else rule.fw_prot = IPPROTO_TCP; if( !doUDP && (start == SIGNAL_FTP && end == SIGNAL_FTP && useRange) ) // special FTP Case! { rule.fw_uar.fw_pts[0] = 21; IP_FW_SETNDSTP(&rule, 1); rule.fw_flg |= IP_FW_F_IN; } else // regular case: add allow tcp from any to any in (user configurable!) { rule.fw_uar.fw_pts[0] = start; IP_FW_SETNDSTP(&rule, 1); rule.fw_flg |= IP_FW_F_IN; if( useRange ) // a range of ports like 20-30 { rule.fw_uar.fw_pts[1] = end; IP_FW_SETNDSTP(&rule, 2); rule.fw_flg |= IP_FW_F_DRNG; } // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any } i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", ruleNumber); return i; } return SUCCESS; } //******************************************************************************** // AddUserDefinedRuleV6 //******************************************************************************** int AddUserDefinedRuleV6(int controlSocket, int ruleNumber, SInt32 start, SInt32 end, boolean_t useRange, boolean_t doUDP) { struct ip6_fw rule; int i; memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = ruleNumber; rule.fw_flg |= IPV6_FW_F_ACCEPT; if (doUDP) rule.fw_prot = IPPROTO_UDP; else rule.fw_prot = IPPROTO_TCP; if( !doUDP && (start == SIGNAL_FTP && end == SIGNAL_FTP && useRange) ) // special FTP Case! { rule.fw_pts[0] = 21; IPV6_FW_SETNDSTP(&rule, 1); rule.fw_flg |= IPV6_FW_F_IN; } else // regular case: add allow tcp from any to any in (user configurable!) { rule.fw_pts[0] = start; IPV6_FW_SETNDSTP(&rule, 1); rule.fw_flg |= IPV6_FW_F_IN; if( useRange ) // a range of ports like 20-30 { rule.fw_pts[1] = end; IPV6_FW_SETNDSTP(&rule, 2); rule.fw_flg |= IPV6_FW_F_DRNG; } // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any } i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding V6 rule: %d\n", ruleNumber); return i; } return SUCCESS; } //******************************************************************************** // AddICMPRuleV6 //******************************************************************************** int AddICMPRuleV6( int controlSocket, Boolean loggingenabled ) { struct ip6_fw rule; int i; // ipfw add 12150 deny tcp from any to any memset(&rule, 0, sizeof(rule)); rule.version = IPV6_FW_CURRENT_API_VERSION; // send down the version rule.context = (void*)'AAPL'; rule.fw_number = ICMPECHOREQRULE; // rule # rule.fw_flg |= IPV6_FW_F_DENY; // deny if ( loggingenabled ) rule.fw_flg |= IPV6_FW_F_PRN; // for logging rule.fw_prot = IPPROTO_ICMPV6; // icmpv6 rule.fw_icmp6types[ICMP6_ECHO_REQUEST / (sizeof(unsigned) * 8)] |= 1 << (ICMP6_ECHO_REQUEST % (sizeof(unsigned) * 8)); rule.fw_flg |= IPV6_FW_F_ICMPBIT ; // ICMP type rule.fw_flg |= IPV6_FW_F_IN; // any in // fw_src, fw_dst, fw_smsk, fw_dmsk is 0 for any to any i = setsockopt(controlSocket, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof(rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d\n", ICMPECHOREQRULE); return i; } return SUCCESS; } //******************************************************************************** // WriteOutInternetSharingRule //******************************************************************************** int WriteOutInternetSharingRule(int controlSocket, struct ip_fw *rule) { int i; i = setsockopt(controlSocket, IPPROTO_IP, IP_FW_ADD, rule, sizeof(*rule)); if( i ) { printf("Firewall Tool: Error adding rule: %d (Internet Sharing)\n", RULE_0); return i; } return SUCCESS; } //******************************************************************************** // GetPortRange //******************************************************************************** int GetPortRange(CFStringRef portString, SInt32 *start, SInt32 *end, boolean_t *useRange) { char buffer[256]; if( portString == NULL ) return ERROR; if( CFStringGetLength(portString) == 0 ) return ERROR; if( CFStringGetCString(portString, buffer, 256, kCFStringEncodingMacRoman) ) { char *ptr = NULL; char bufferCopy[256]; strcpy(bufferCopy, buffer); ptr = strtok(bufferCopy, "-"); if( ptr ) // ptr does not equal NULL { if( strcmp(ptr, "*") == 0 ) // special FTP CASE { *start = SIGNAL_FTP; *end = SIGNAL_FTP; *useRange = true; return SUCCESS; }else { int startVal = strtol(ptr, (char**)NULL, 10); if( startVal > 0 && startVal <= 65535 && startVal != LONG_MAX && startVal != LONG_MIN ) { *start = startVal; } else { printf("Firewall Tool: Error, Start Port (%d) invalid!\n", startVal); return ERROR; } } }else { printf("Firewall Tool: Error, No Start Port defined!\n"); return ERROR; } ptr = strtok(NULL, "\0"); if( ptr ) { int endVal = strtol(ptr, (char**)NULL, 10); if( endVal > 0 && endVal <= 65535 && endVal != LONG_MAX && endVal != LONG_MIN ) { *end = endVal; *useRange = true; } else { printf("Firewall Tool: Error, End Port (%d) invalid!\n", endVal); return ERROR; } }else { *end = 0; *useRange = false; } return SUCCESS; }else { return ERROR; } } // isInternetSharingRunning boolean_t isInternetSharingRunning(int controlSocket, struct ip_fw *rule) { struct ip_fw *rules = NULL; int dataSize = 0; int actualDataSize = 0; int numRules = 0; int iterations = 1; int i, j; // do the stupid socket memory thing to figure out how much to allocate do { dataSize = (sizeof(struct ip_fw) * 10) * iterations; rules = (struct ip_fw *)realloc(rules, dataSize); if (rules == NULL ) { printf("Firewall Tool: Error getting rules! Realloc Failed!\n"); return false; } rules->version = IP_FW_CURRENT_API_VERSION; // send down the version actualDataSize = dataSize; i = getsockopt(controlSocket, IPPROTO_IP, IP_FW_GET, rules, &actualDataSize); if( i < 0 ) { printf("Firewall Tool: Error getting rules! Not written into structure...\n"); free(rules); return false; } iterations++; }while( dataSize == actualDataSize ); numRules = actualDataSize/sizeof(struct ip_fw); for( j = 0; j < numRules; j++ ) { int ruleNumber = rules[i].fw_number; if( ruleNumber == RULE_0 ) { rule = memcpy(rule, &rules[i], sizeof(struct ip_fw)); return true; } } if( rules ) free( rules ); return false; } //******************************************************************************** // EnableLogging //******************************************************************************** void EnableLogging(boolean_t enable) { int newValue = enable ? 2 : 0; int errorCode; errorCode = sysctlbyname("net.inet.ip.fw.verbose", NULL, NULL, &newValue, sizeof(newValue)); if( errorCode < 0 ) { printf("Firewall Tool: Error, sysctlbyname returned: %d\n", errorCode); } } //******************************************************************************** // IsExpectedCFType //******************************************************************************** boolean_t IsExpectedCFType(CFPropertyListRef variableInQuestion, CFTypeID expectedType) { if( variableInQuestion == NULL ) // variable in question does not exist! { printf("Firewall Tool: Error, IsExpectedCFType(variableInQuestion) variable == NULL!\n"); return false; } else if( CFGetTypeID(variableInQuestion) == expectedType ) { return true; } else { return false; } } //******************************************************************************** // EnableBlackHole //******************************************************************************** void EnableBlackHole(boolean_t enable) { int lognewValue = enable ? 3 : 0; int newValue = enable ? 1 : 0; int errorCode; errorCode = sysctlbyname("net.inet.tcp.blackhole", NULL, NULL, &newValue, sizeof(newValue)); if( errorCode < 0 ) { printf("Firewall Tool: Error, sysctlbyname(net.inet.tcp.blackhole): %d\n", errno); } errorCode = sysctlbyname("net.inet.tcp.log_in_vain", NULL, NULL, &lognewValue, sizeof(newValue)); if( errorCode < 0 ) { printf("Firewall Tool: Error, sysctlbyname(net.inet.tcp.log_in_vain): %d\n", errno); } errorCode = sysctlbyname("net.inet.udp.blackhole", NULL, NULL, &newValue, sizeof(newValue)); if( errorCode < 0 ) { printf("Firewall Tool: Error, sysctlbyname(net.inet.udp.blackhole): %d\n", errno); } errorCode = sysctlbyname("net.inet.udp.log_in_vain", NULL, NULL, &lognewValue, sizeof(newValue)); if( errorCode < 0 ) { printf("Firewall Tool: Error, sysctlbyname(net.inet.udp.log_in_vain): %d\n", errno); } }