char * get_empty_ruleset_policy(const char *rulesetname) { t_firewall_ruleset *rs; rs = get_ruleset(rulesetname); if(rs == NULL) return NULL; return rs->emptyrulesetpolicy; }
/** Remove mark when auth server is reachable again */ int iptables_fw_auth_reachable(void) { int got_authdown_ruleset = NULL == get_ruleset(FWRULESET_AUTH_IS_DOWN) ? 0 : 1; if (got_authdown_ruleset) return iptables_do_command("-t mangle -F " CHAIN_AUTH_IS_DOWN); else return 1; }
/** Set a mark when auth server is not reachable */ int iptables_fw_auth_unreachable(int tag) { int got_authdown_ruleset = NULL == get_ruleset(FWRULESET_AUTH_IS_DOWN) ? 0 : 1; if (got_authdown_ruleset) return iptables_do_command("-t mangle -A " CHAIN_AUTH_IS_DOWN " -j MARK --set-mark 0x%u/0x00ff", tag); else return 1; }
t_firewall_rule * get_ruleset_list(const char *ruleset) { t_firewall_ruleset *tmp = get_ruleset(ruleset); if (tmp == NULL) return NULL; return (tmp->rules); }
/** @internal Parses an empty ruleset policy directive */ static void parse_empty_ruleset_policy(char *ptr, const char *filename, int lineno) { char *rulesetname, *policy; t_firewall_ruleset *ruleset; /* find first whitespace delimited word; this is ruleset name */ while ((*ptr != '\0') && (isblank(*ptr))) ptr++; rulesetname = ptr; while ((*ptr != '\0') && (!isblank(*ptr))) ptr++; *ptr = '\0'; /* get the ruleset struct with this name; error if it doesn't exist */ debug(LOG_DEBUG, "Parsing EmptyRuleSetPolicy for %s", rulesetname); ruleset = get_ruleset(rulesetname); if(ruleset == NULL) { debug(LOG_ERR, "Unrecognized FirewallRuleSet name: %s at line %d in %s", rulesetname, lineno, filename); debug(LOG_ERR, "Exiting..."); exit(-1); } /* find next whitespace delimited word; this is policy name */ ptr++; while ((*ptr != '\0') && (isblank(*ptr))) ptr++; policy = ptr; while ((*ptr != '\0') && (!isblank(*ptr))) ptr++; *ptr = '\0'; /* make sure policy is one of the possible ones: "passthrough" means iptables RETURN "allow" means iptables ACCEPT "block" means iptables REJECT */ if (ruleset->emptyrulesetpolicy != NULL) free(ruleset->emptyrulesetpolicy); if(!strcasecmp(policy,"passthrough")) { ruleset->emptyrulesetpolicy = safe_strdup("RETURN"); } else if (!strcasecmp(policy,"allow")) { ruleset->emptyrulesetpolicy = safe_strdup("ACCEPT"); } else if (!strcasecmp(policy,"block")) { ruleset->emptyrulesetpolicy = safe_strdup("REJECT"); } else { debug(LOG_ERR, "Unknown EmptyRuleSetPolicy directive: %s at line %d in %s", policy, lineno, filename); debug(LOG_ERR, "Exiting..."); exit(-1); } debug(LOG_DEBUG, "Set EmptyRuleSetPolicy for %s to %s", rulesetname, policy); }
/** * @internal * Load all the rules in a rule set. * @arg ruleset Name of the ruleset * @arg table Table containing the chain. * @arg chain IPTables chain the rules go into */ static void iptables_load_ruleset(const char * table, const char *ruleset, const char *chain) { t_firewall_rule *rule; char *cmd; debug(LOG_DEBUG, "Load ruleset %s into table %s, chain %s", ruleset, table, chain); for (rule = get_ruleset(ruleset); rule != NULL; rule = rule->next) { cmd = iptables_compile(table, chain, rule); debug(LOG_DEBUG, "Loading rule \"%s\" into table %s, chain %s", cmd, table, chain); iptables_do_command(cmd); free(cmd); } debug(LOG_DEBUG, "Ruleset %s loaded into table %s, chain %s", ruleset, table, chain); }
/** Add a firewall ruleset with the given name, and return it. * Do not allow duplicates. */ t_firewall_ruleset * add_ruleset(const char rulesetname[]) { t_firewall_ruleset * ruleset; ruleset = get_ruleset(rulesetname); if(ruleset != NULL) { debug(LOG_DEBUG, "add_ruleset(): FirewallRuleSet %s already exists.", rulesetname); return ruleset; } debug(LOG_DEBUG, "add_ruleset(): Creating FirewallRuleSet %s.", rulesetname); /* Create and place at head of config.rulesets */ ruleset = safe_malloc(sizeof(t_firewall_ruleset)); memset(ruleset, 0, sizeof(t_firewall_ruleset)); ruleset->name = safe_strdup(rulesetname); ruleset->next = config.rulesets; config.rulesets = ruleset; return ruleset; }
/** The 404 handler is also responsible for redirecting to the auth server */ void http_callback_404(httpd * webserver, request * r, int error_code) { char tmp_url[MAX_BUF], *url, *mac; s_config *config = config_get_config(); t_auth_serv *auth_server = get_auth_server(); memset(tmp_url, 0, sizeof(tmp_url)); /* * XXX Note the code below assumes that the client's request is a plain * http request to a standard port. At any rate, this handler is called only * if the internet/auth server is down so it's not a huge loss, but still. */ snprintf(tmp_url, (sizeof(tmp_url) - 1), "http://%s%s%s%s", r->request.host, r->request.path, r->request.query[0] ? "?" : "", r->request.query); url = httpdUrlEncode(tmp_url); if (!is_online()) { /* The internet connection is down at the moment - apologize and do not redirect anywhere */ char *buf; safe_asprintf(&buf, "<p>We apologize, but it seems that the internet connection that powers this hotspot is temporarily unavailable.</p>" "<p>If at all possible, please notify the owners of this hotspot that the internet connection is out of service.</p>" "<p>The maintainers of this network are aware of this disruption. We hope that this situation will be resolved soon.</p>" "<p>In a while please <a href='%s'>click here</a> to try your request again.</p>", tmp_url); send_http_page(r, "Uh oh! Internet access unavailable!", buf); free(buf); debug(LOG_INFO, "Sent %s an apology since I am not online - no point sending them to auth server", r->clientAddr); } else if (!is_auth_online()) { /* The auth server is down at the moment - apologize and do not redirect anywhere */ char *buf; safe_asprintf(&buf, "<p>We apologize, but it seems that we are currently unable to re-direct you to the login screen.</p>" "<p>The maintainers of this network are aware of this disruption. We hope that this situation will be resolved soon.</p>" "<p>In a couple of minutes please <a href='%s'>click here</a> to try your request again.</p>", tmp_url); send_http_page(r, "Uh oh! Login screen unavailable!", buf); free(buf); debug(LOG_INFO, "Sent %s an apology since auth server not online - no point sending them to auth server", r->clientAddr); } else { /* Re-direct them to auth server */ char *urlFragment; if (!(mac = arp_get(r->clientAddr))) { /* We could not get their MAC address */ debug(LOG_INFO, "Failed to retrieve MAC address for ip %s, so not putting in the login request", r->clientAddr); safe_asprintf(&urlFragment, "%sgw_address=%s&gw_port=%d&gw_id=%s&ip=%s&url=%s", auth_server->authserv_login_script_path_fragment, config->gw_address, config->gw_port, config->gw_id, r->clientAddr, url); } else { debug(LOG_INFO, "Got client MAC address for ip %s: %s", r->clientAddr, mac); safe_asprintf(&urlFragment, "%sgw_address=%s&gw_port=%d&gw_id=%s&ip=%s&mac=%s&url=%s", auth_server->authserv_login_script_path_fragment, config->gw_address, config->gw_port, config->gw_id, r->clientAddr, mac, url); free(mac); } // if host is not in whitelist, maybe not in conf or domain'IP changed, it will go to here. debug(LOG_INFO, "Check host %s is in whitelist or not", r->request.host); // e.g. www.example.com t_firewall_rule *rule; //e.g. example.com is in whitelist // if request http://www.example.com/, it's not equal example.com. for (rule = get_ruleset("global"); rule != NULL; rule = rule->next) { debug(LOG_INFO, "rule mask %s", rule->mask); if (strstr(r->request.host, rule->mask) == NULL) { debug(LOG_INFO, "host %s is not in %s, continue", r->request.host, rule->mask); continue; } int host_length = strlen(r->request.host); int mask_length = strlen(rule->mask); if (host_length != mask_length) { char prefix[1024] = { 0 }; // must be *.example.com, if not have ".", maybe Phishing. e.g. phishingexample.com strncpy(prefix, r->request.host, host_length - mask_length - 1); // e.g. www strcat(prefix, "."); // www. strcat(prefix, rule->mask); // www.example.com if (strcasecmp(r->request.host, prefix) == 0) { debug(LOG_INFO, "allow subdomain"); fw_allow_host(r->request.host); http_send_redirect(r, tmp_url, "allow subdomain"); free(url); free(urlFragment); return; } } else { // e.g. "example.com" is in conf, so it had been parse to IP and added into "iptables allow" when wifidog start. but then its' A record(IP) changed, it will go to here. debug(LOG_INFO, "allow domain again, because IP changed"); fw_allow_host(r->request.host); http_send_redirect(r, tmp_url, "allow domain"); free(url); free(urlFragment); return; } } debug(LOG_INFO, "Captured %s requesting [%s] and re-directing them to login page", r->clientAddr, url); http_send_redirect_to_auth(r, urlFragment, "Redirect to login page"); free(urlFragment); } free(url); }
static void khmer_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, int length, const PangoAnalysis *analysis, PangoGlyphString *glyphs) { PangoFcFont *fc_font; FT_Face face; PangoOTRuleset *ruleset; PangoOTBuffer *buffer; glong n_chars; gunichar *wcs; const char *p; int i; glong syllable; KhmerCharClass charClass; glong cursor = 0; g_return_if_fail (font != NULL); g_return_if_fail (text != NULL); g_return_if_fail (length >= 0); g_return_if_fail (analysis != NULL); fc_font = PANGO_FC_FONT (font); face = pango_fc_font_lock_face (fc_font); if (!face) return; buffer = pango_ot_buffer_new (fc_font); wcs = g_utf8_to_ucs4_fast (text, length, &n_chars); p = text; /* This loop only exits when we reach the end of a run, which may contain * several syllables. */ while (cursor < n_chars) { /* write a pre vowel or the pre part of a split vowel first * and look out for coeng + ro. RO is the only vowel of type 2, and * therefore the only one that requires saving space before the base. */ glong coengRo = -1; /* There is no Coeng Ro, if found this value will change */ syllable = find_syllable (wcs, cursor, n_chars); for (i = cursor; i < syllable; i += 1) { charClass = get_char_class (wcs[i]); /* if a split vowel, write the pre part. In Khmer the pre part * is the same for all split vowels, same glyph as pre vowel C_VOWEL_E */ if (charClass & CF_SPLIT_VOWEL) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_VOWEL_E), pref_p, p - text); break; /* there can be only one vowel */ } /* if a vowel with pos before write it out */ if (charClass & CF_POS_BEFORE) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pref_p, p - text); break; /* there can be only one vowel */ } /* look for coeng + ro and remember position * works because coeng + ro is always in front of a vowel (if there is a vowel) * and because CC_CONSONANT2 is enough to identify it, as it is the only consonant * with this flag */ if ((charClass & CF_COENG) && (i + 1 < syllable) && ((get_char_class (wcs[i + 1]) & CF_CLASS_MASK) == CC_CONSONANT2)) { coengRo = i; } } /* write coeng + ro if found */ if (coengRo > -1) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_COENG), pref_p, p - text); pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_RO), pref_p, p - text); } /* shall we add a dotted circle? * If in the position in which the base should be (first char in the string) there is * a character that has the Dotted circle flag (a character that cannot be a base) * then write a dotted circle */ if (get_char_class (wcs[cursor]) & CF_DOTTED_CIRCLE) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_DOTTED_CIRCLE), default_p, p - text); } /* copy what is left to the output, skipping before vowels and * coeng Ro if they are present */ for (i = cursor; i < syllable; i += 1) { charClass = get_char_class (wcs[i]); /* skip a before vowel, it was already processed */ if (charClass & CF_POS_BEFORE) { p = g_utf8_next_char (p); continue; } /* skip coeng + ro, it was already processed */ if (i == coengRo) { p = g_utf8_next_char (p); i += 1; p = g_utf8_next_char (p); continue; } switch (charClass & CF_POS_MASK) { case CF_POS_ABOVE : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), abvf_p, p - text); break; case CF_POS_AFTER : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text); break; case CF_POS_BELOW : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; default: /* assign the correct flags to a coeng consonant * Consonants of type 3 are taged as Post forms and those type 1 as below forms */ if ((charClass & CF_COENG) && i + 1 < syllable) { if ((get_char_class (wcs[i + 1]) & CF_CLASS_MASK) == CC_CONSONANT3) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text); p = g_utf8_next_char (p); i += 1; pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text); break; } else { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); p = g_utf8_next_char (p); i += 1; pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } } /* if a shifter is followed by an above vowel change the shifter to below form, * an above vowel can have two possible positions i + 1 or i + 3 * (position i+1 corresponds to unicode 3, position i+3 to Unicode 4) * and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two * different positions, right after the shifter or after a vowel (Unicode 4) */ if ((charClass & CF_SHIFTER) && (i + 1 < syllable)) { if (get_char_class (wcs[i + 1]) & CF_ABOVE_VOWEL) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } if (i + 2 < syllable && (wcs[i + 1] == C_VOWEL_AA) && (wcs[i + 2] == C_SIGN_NIKAHIT) ) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } if (i + 3 < syllable && (get_char_class (wcs[i + 3]) & CF_ABOVE_VOWEL) ) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } if (i + 4 < syllable && (wcs[i + 3] == C_VOWEL_AA) && (wcs[i + 4] == C_SIGN_NIKAHIT) ) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; } } /* default - any other characters */ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), default_p, p - text); break; } /* switch */ p = g_utf8_next_char (p); } /* for */ cursor = syllable; /* move the pointer to the start of next syllable */ } /* while */ /* do gsub processing */ ruleset = get_ruleset (face); if (ruleset != NULL) { pango_ot_ruleset_substitute (ruleset, buffer); pango_ot_ruleset_position (ruleset, buffer); } pango_ot_buffer_output (buffer, glyphs); g_free (wcs); pango_ot_buffer_destroy (buffer); pango_fc_font_unlock_face (fc_font); }
static void tibetan_engine_shape (PangoEngineShape *engine, PangoFont *font, const char *text, int length, const PangoAnalysis *analysis, PangoGlyphString *glyphs) { PangoFcFont *fc_font; FT_Face face; PangoOTRuleset *ruleset; PangoOTBuffer *buffer; glong n_chars; gunichar *wcs; const char *p; int i; glong syllable; TibetanCharClass charClass; glong cursor = 0; g_return_if_fail (font != NULL); g_return_if_fail (text != NULL); g_return_if_fail (length >= 0); g_return_if_fail (analysis != NULL); fc_font = PANGO_FC_FONT (font); face = pango_fc_font_lock_face (fc_font); if (!face) return; buffer = pango_ot_buffer_new (fc_font); wcs = g_utf8_to_ucs4_fast (text, length, &n_chars); p = text; /* This loop only exits when we reach the end of a run, which may contain * several syllables. */ while (cursor < n_chars) { syllable = find_syllable (wcs, cursor, n_chars); /* shall we add a dotted circle? * If in the position in which the base should be (first char in the string) there is * a character that has the Dotted circle flag (a character that cannot be a base) * then write a dotted circle */ if (get_char_class (wcs[cursor]) & CF_DOTTED_CIRCLE) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_DOTTED_CIRCLE), default_p, p - text); } /* If it encounters a digit followed by number pre combining mark, then reorder the two characters * coeng Ro if they are present */ for (i = cursor; i < syllable; i += 1) { charClass = get_char_class (wcs[i]); if ((charClass & CF_DIGIT ) && ( get_char_class (wcs[i+1]) & CF_PREDIGIT)) { pango_ot_buffer_add_glyph (buffer, get_index (fc_font, C_PRE_NUMBER_MARK), pref_p, p - text); p = g_utf8_next_char (p); pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pref_p, p - text); i += 1; } else { switch (charClass & CF_POS_MASK) { case CF_POS_ABOVE : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), abvf_p, p - text); break; case CF_POS_AFTER : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), pstf_p, p - text); break; case CF_POS_BELOW : pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), blwf_p, p - text); break; default: /* default - any other characters */ pango_ot_buffer_add_glyph (buffer, get_index (fc_font, wcs[i]), default_p, p - text); break; } /* switch */ } p = g_utf8_next_char (p); } /* for */ cursor = syllable; /* move the pointer to the start of next syllable */ } /* while */ /* do gsub processing */ ruleset = get_ruleset (face); if (ruleset != NULL) { pango_ot_ruleset_substitute (ruleset, buffer); pango_ot_ruleset_position (ruleset, buffer); } pango_ot_buffer_output (buffer, glyphs); g_free (wcs); pango_ot_buffer_destroy (buffer); pango_fc_font_unlock_face (fc_font); }
/** Remove the firewall rules * This is used when we do a clean shutdown of WiFiDog and when it starts to make * sure there are no rules left over */ int iptables_fw_destroy(void) { int got_authdown_ruleset = NULL == get_ruleset(FWRULESET_AUTH_IS_DOWN) ? 0 : 1; fw_quiet = 1; debug(LOG_DEBUG, "Destroying our iptables entries"); /* * * Everything in the MANGLE table * */ debug(LOG_DEBUG, "Destroying chains in the MANGLE table"); iptables_fw_destroy_mention("mangle", "PREROUTING", CHAIN_TRUSTED); iptables_fw_destroy_mention("mangle", "PREROUTING", CHAIN_OUTGOING); if (got_authdown_ruleset) iptables_fw_destroy_mention("mangle", "PREROUTING", CHAIN_AUTH_IS_DOWN); iptables_fw_destroy_mention("mangle", "POSTROUTING", CHAIN_INCOMING); iptables_do_command("-t mangle -F " CHAIN_TRUSTED); iptables_do_command("-t mangle -F " CHAIN_OUTGOING); if (got_authdown_ruleset) iptables_do_command("-t mangle -F " CHAIN_AUTH_IS_DOWN); iptables_do_command("-t mangle -F " CHAIN_INCOMING); iptables_do_command("-t mangle -X " CHAIN_TRUSTED); iptables_do_command("-t mangle -X " CHAIN_OUTGOING); if (got_authdown_ruleset) iptables_do_command("-t mangle -X " CHAIN_AUTH_IS_DOWN); iptables_do_command("-t mangle -X " CHAIN_INCOMING); /* * * Everything in the NAT table * */ debug(LOG_DEBUG, "Destroying chains in the NAT table"); iptables_fw_destroy_mention("nat", "PREROUTING", CHAIN_OUTGOING); iptables_do_command("-t nat -F " CHAIN_AUTHSERVERS); iptables_do_command("-t nat -F " CHAIN_OUTGOING); if (got_authdown_ruleset) iptables_do_command("-t nat -F " CHAIN_AUTH_IS_DOWN); iptables_do_command("-t nat -F " CHAIN_TO_ROUTER); iptables_do_command("-t nat -F " CHAIN_TO_INTERNET); iptables_do_command("-t nat -F " CHAIN_GLOBAL); iptables_do_command("-t nat -F " CHAIN_UNKNOWN); iptables_do_command("-t nat -X " CHAIN_AUTHSERVERS); iptables_do_command("-t nat -X " CHAIN_OUTGOING); if (got_authdown_ruleset) iptables_do_command("-t nat -X " CHAIN_AUTH_IS_DOWN); iptables_do_command("-t nat -X " CHAIN_TO_ROUTER); iptables_do_command("-t nat -X " CHAIN_TO_INTERNET); iptables_do_command("-t nat -X " CHAIN_GLOBAL); iptables_do_command("-t nat -X " CHAIN_UNKNOWN); /* * * Everything in the FILTER table * */ debug(LOG_DEBUG, "Destroying chains in the FILTER table"); iptables_fw_destroy_mention("filter", "FORWARD", CHAIN_TO_INTERNET); iptables_do_command("-t filter -F " CHAIN_TO_INTERNET); iptables_do_command("-t filter -F " CHAIN_AUTHSERVERS); iptables_do_command("-t filter -F " CHAIN_LOCKED); iptables_do_command("-t filter -F " CHAIN_GLOBAL); iptables_do_command("-t filter -F " CHAIN_VALIDATE); iptables_do_command("-t filter -F " CHAIN_KNOWN); iptables_do_command("-t filter -F " CHAIN_UNKNOWN); if (got_authdown_ruleset) iptables_do_command("-t filter -F " CHAIN_AUTH_IS_DOWN); iptables_do_command("-t filter -X " CHAIN_TO_INTERNET); iptables_do_command("-t filter -X " CHAIN_AUTHSERVERS); iptables_do_command("-t filter -X " CHAIN_LOCKED); iptables_do_command("-t filter -X " CHAIN_GLOBAL); iptables_do_command("-t filter -X " CHAIN_VALIDATE); iptables_do_command("-t filter -X " CHAIN_KNOWN); iptables_do_command("-t filter -X " CHAIN_UNKNOWN); if (got_authdown_ruleset) iptables_do_command("-t filter -X " CHAIN_AUTH_IS_DOWN); return 1; }
/** Initialize the firewall rules */ int iptables_fw_init(void) { const s_config *config; char *ext_interface = NULL; int gw_port = 0; t_trusted_mac *p; int proxy_port; fw_quiet = 0; int got_authdown_ruleset = NULL == get_ruleset(FWRULESET_AUTH_IS_DOWN) ? 0 : 1; LOCK_CONFIG(); config = config_get_config(); gw_port = config->gw_port; if (config->external_interface) { ext_interface = safe_strdup(config->external_interface); } else { ext_interface = get_ext_iface(); } if (ext_interface == NULL) { UNLOCK_CONFIG(); debug(LOG_ERR, "FATAL: no external interface"); return 0; } /* * * Everything in the MANGLE table * */ /* Create new chains */ iptables_do_command("-t mangle -N " CHAIN_TRUSTED); iptables_do_command("-t mangle -N " CHAIN_OUTGOING); iptables_do_command("-t mangle -N " CHAIN_INCOMING); if (got_authdown_ruleset) iptables_do_command("-t mangle -N " CHAIN_AUTH_IS_DOWN); int index = 0; char* cur_interface; while(index < 3 && (cur_interface = config->gw_interface[index])){ /* Assign links and rules to these new chains */ iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_OUTGOING, cur_interface); iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_TRUSTED, cur_interface); //this rule will be inserted before the prior one //if (got_authdown_ruleset) // iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_AUTH_IS_DOWN, cur_interface); //this rule must be last in the chain iptables_do_command("-t mangle -I POSTROUTING 1 -o %s -j " CHAIN_INCOMING, cur_interface); index++; } /* Assign links and rules to these new chains */ // iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_OUTGOING, config->gw_interface); // iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_TRUSTED, config->gw_interface); //this rule will be inserted before the prior one // if (got_authdown_ruleset) // iptables_do_command("-t mangle -I PREROUTING 1 -i %s -j " CHAIN_AUTH_IS_DOWN, config->gw_interface); //this rule must be last in the chain // iptables_do_command("-t mangle -I POSTROUTING 1 -o %s -j " CHAIN_INCOMING, config->gw_interface); for (p = config->trustedmaclist; p != NULL; p = p->next) iptables_do_command("-t mangle -A " CHAIN_TRUSTED " -m mac --mac-source %s -j MARK --set-mark %d", p->mac, FW_MARK_KNOWN); /* * * Everything in the NAT table * */ /* Create new chains */ iptables_do_command("-t nat -N " CHAIN_OUTGOING); iptables_do_command("-t nat -N " CHAIN_TO_ROUTER); iptables_do_command("-t nat -N " CHAIN_TO_INTERNET); iptables_do_command("-t nat -N " CHAIN_GLOBAL); iptables_do_command("-t nat -N " CHAIN_UNKNOWN); iptables_do_command("-t nat -N " CHAIN_AUTHSERVERS); if (got_authdown_ruleset) iptables_do_command("-t nat -N " CHAIN_AUTH_IS_DOWN); index = 0; while(index < 3 && (cur_interface = config->gw_interface[index])){ /* Assign links and rules to these new chains */ iptables_do_command("-t nat -A PREROUTING -i %s -j " CHAIN_OUTGOING, cur_interface); index++; } iptables_do_command("-t nat -A " CHAIN_OUTGOING " -d %s -j " CHAIN_TO_ROUTER, config->gw_address); iptables_do_command("-t nat -A " CHAIN_TO_ROUTER " -j ACCEPT"); iptables_do_command("-t nat -A " CHAIN_OUTGOING " -j " CHAIN_TO_INTERNET); if ((proxy_port = config_get_config()->proxy_port) != 0) { debug(LOG_DEBUG, "Proxy port set, setting proxy rule"); iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -p tcp --dport 80 -m mark --mark 0x%u/0x00ff -j DNAT --to-destination %s:%u", FW_MARK_KNOWN, config->gw_address, proxy_port); iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -p tcp --dport 80 -m mark --mark 0x%u/0x00ff -j DNAT --to-destination %s:%u", FW_MARK_PROBATION, config->gw_address, proxy_port); } iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u/0x00ff -j ACCEPT", FW_MARK_KNOWN); iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u/0x00ff -j ACCEPT", FW_MARK_PROBATION); iptables_do_command("-t nat -A " CHAIN_TO_INTERNET " -j " CHAIN_UNKNOWN); iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_AUTHSERVERS); iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_GLOBAL); if (got_authdown_ruleset) { iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -j " CHAIN_AUTH_IS_DOWN); iptables_do_command("-t nat -A " CHAIN_AUTH_IS_DOWN " -m mark --mark 0x%u/0x00ff -j ACCEPT", FW_MARK_AUTH_IS_DOWN); } iptables_do_command("-t nat -A " CHAIN_UNKNOWN " -p tcp --dport 80 -j DNAT --to-destination %s:%d", config->gw_address, gw_port); /* * * Everything in the FILTER table * */ /* Create new chains */ iptables_do_command("-t filter -N " CHAIN_TO_INTERNET); iptables_do_command("-t filter -N " CHAIN_AUTHSERVERS); iptables_do_command("-t filter -N " CHAIN_LOCKED); iptables_do_command("-t filter -N " CHAIN_GLOBAL); iptables_do_command("-t filter -N " CHAIN_VALIDATE); iptables_do_command("-t filter -N " CHAIN_KNOWN); iptables_do_command("-t filter -N " CHAIN_UNKNOWN); if (got_authdown_ruleset) iptables_do_command("-t filter -N " CHAIN_AUTH_IS_DOWN); /* Assign links and rules to these new chains */ index = 0; while(index < 3 && (cur_interface = config->gw_interface[index])){ /* Insert at the beginning */ iptables_do_command("-t filter -I FORWARD -i %s -j " CHAIN_TO_INTERNET, cur_interface); index++; } iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m state --state INVALID -j DROP"); /* XXX: Why this? it means that connections setup after authentication stay open even after the connection is done... iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m state --state RELATED,ESTABLISHED -j ACCEPT"); */ //Won't this rule NEVER match anyway?!?!? benoitg, 2007-06-23 //iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -i %s -m state --state NEW -j DROP", ext_interface); /* TCPMSS rule for PPPoE */ iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -o %s -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu", ext_interface); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -j " CHAIN_AUTHSERVERS); iptables_fw_set_authservers(); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u/0x00ff -j " CHAIN_LOCKED, FW_MARK_LOCKED); iptables_load_ruleset("filter", FWRULESET_LOCKED_USERS, CHAIN_LOCKED); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -j " CHAIN_GLOBAL); iptables_load_ruleset("filter", FWRULESET_GLOBAL, CHAIN_GLOBAL); iptables_load_ruleset("nat", FWRULESET_GLOBAL, CHAIN_GLOBAL); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u/0x00ff -j " CHAIN_VALIDATE, FW_MARK_PROBATION); iptables_load_ruleset("filter", FWRULESET_VALIDATING_USERS, CHAIN_VALIDATE); iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u/0x00ff -j " CHAIN_KNOWN, FW_MARK_KNOWN); iptables_load_ruleset("filter", FWRULESET_KNOWN_USERS, CHAIN_KNOWN); if (got_authdown_ruleset) { iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -m mark --mark 0x%u/0x00ff -j " CHAIN_AUTH_IS_DOWN, FW_MARK_AUTH_IS_DOWN); iptables_load_ruleset("filter", FWRULESET_AUTH_IS_DOWN, CHAIN_AUTH_IS_DOWN); } iptables_do_command("-t filter -A " CHAIN_TO_INTERNET " -j " CHAIN_UNKNOWN); iptables_load_ruleset("filter", FWRULESET_UNKNOWN_USERS, CHAIN_UNKNOWN); iptables_do_command("-t filter -A " CHAIN_UNKNOWN " -j REJECT --reject-with icmp-port-unreachable"); UNLOCK_CONFIG(); free(ext_interface); return 1; }
/** @internal Parses firewall rule set information */ static void parse_firewall_ruleset(const char *rulesetname, FILE *fd, const char *filename, int *linenum) { char line[MAX_BUF], *p1, *p2; int opcode; t_firewall_ruleset *ruleset; /* find whitespace delimited word in ruleset string; this is its name */ p1 = strchr(rulesetname,' '); if(p1) *p1 = '\0'; p1 = strchr(rulesetname,'\t'); if(p1) *p1 = '\0'; debug(LOG_DEBUG, "Parsing FirewallRuleSet %s", rulesetname); ruleset = get_ruleset(rulesetname); if(ruleset == NULL) { debug(LOG_ERR, "Unrecognized FirewallRuleSet name: %s", rulesetname); debug(LOG_ERR, "Exiting..."); exit(-1); } /* Parsing the rules in the set */ while (fgets(line, MAX_BUF, fd)) { (*linenum)++; p1 = _strip_whitespace(line); /* if nothing left, get next line */ if(p1[0] == '\0') continue; /* if closing brace, we are done */ if(p1[0] == '}') break; /* next, we coopt the parsing of the regular config */ /* keep going until word boundary is found. */ p2 = p1; while ((*p2 != '\0') && (!isblank(*p2))) p2++; /* if this is end of line, it's a problem */ if(p2[0] == '\0') { debug(LOG_ERR, "FirewallRule incomplete on line %d in %s", *linenum, filename); debug(LOG_ERR, "Exiting..."); exit(-1); } /* terminate first word, point past it */ *p2 = '\0'; p2++; /* skip whitespace to point at arg */ while (isblank(*p2)) p2++; /* Get opcode */ opcode = config_parse_opcode(p1, filename, *linenum); debug(LOG_DEBUG, "p1 = [%s]; p2 = [%s]", p1, p2); switch (opcode) { case oFirewallRule: _parse_firewall_rule(ruleset, p2); break; case oBadOption: default: debug(LOG_ERR, "Bad option %s parsing FirewallRuleSet on line %d in %s", p1, *linenum, filename); debug(LOG_ERR, "Exiting..."); exit(-1); break; } } debug(LOG_DEBUG, "FirewallRuleSet %s parsed.", rulesetname); }