home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / YaST2 / modules / SuSEFirewallExpertRules.ycp < prev    next >
Text File  |  2006-11-29  |  10KB  |  304 lines

  1. /**
  2.  * Copyright 2004, Novell, Inc.  All rights reserved.
  3.  *
  4.  * File:    modules/SuSEFirewallExpertRules.ycp
  5.  * Package:    SuSEFirewall configuration
  6.  * Summary:    Interface manipulation of /etc/sysconfig/SuSEFirewall (expert rules)
  7.  * Authors:    Lukas Ocilka <locilka@suse.cz>
  8.  * Flags:    Unstable
  9.  *
  10.  * $id$
  11.  *
  12.  * Module for handling SuSEfirewall2 Expert Rules.
  13.  */
  14.  
  15. {
  16.     module "SuSEFirewallExpertRules";
  17.     textdomain "base";
  18.  
  19.     import "SuSEFirewall";
  20.     import "Netmask";
  21.     import "IP";
  22.  
  23.     /***
  24.      * Firewall Expert Rulezz
  25.      *
  26.      * ATTENTION: You have to call SuSEFirewall::Read() to read the configuration
  27.      * into the memory and call SuSEFirewall::Write() to write the configuration
  28.      * and restart the firewall service.
  29.      */
  30.  
  31.     /**
  32.      * List of all possible protocols for expert rulezz.
  33.      * _rpc_ expects RPC service name as the destination port then.
  34.      */
  35.     list <string> allowed_expert_protocols = ["udp", "tcp", "icmp", "all", "_rpc_"];
  36.  
  37.     /**
  38.      * Returns list of all protocols accepted by the expert rules.
  39.      */
  40.     global list <string> GetAllExpertRulesProtocols () {
  41.     return allowed_expert_protocols;
  42.     }
  43.  
  44.     // used to identify the IPv4 in regexp
  45.     string type_ip4 = "[0123456789]\.[0123456789]\.[0123456789]\.[0123456789]";
  46.  
  47.     /**
  48.      * Returns whether the netmask bits are valid.
  49.      */
  50.     boolean ValidNetmaskBits (integer netmask_bits) {
  51.     return (netmask_bits > 1 && netmask_bits <= 32);
  52.     }
  53.  
  54.     /**
  55.      * Function checks the network definition used for firewall expert rules.
  56.      *
  57.      * @example
  58.      * IsValidNetwork("192.168.0.1")               -> true
  59.      * IsValidNetwork("192.168.0.355")             -> false
  60.      * IsValidNetwork("192.168.0.0/24")            -> true
  61.      * IsValidNetwork("192.168.0.1/32")            -> true
  62.      * IsValidNetwork("192.168.0.1/0")             -> false
  63.      * IsValidNetwork("192.168.0.0/255.255.0.0")   -> true
  64.      * IsValidNetwork("192.168.0.0/255.255.333.0") -> false
  65.      * IsValidNetwork("192.168.0.0/255.255.224.0") -> true
  66.      * IsValidNetwork("0/0")                       -> true
  67.      *
  68.      * @see `man iptables`
  69.      * @param string network
  70.      * @return boolean if it is a valid network definition
  71.      */
  72.     global boolean IsValidNetwork (string network) {
  73.     // A.B.C.D (IP)
  74.     if (regexpmatch(network, "^" + type_ip4 + "$")) {
  75.         return IP::Check4(network);
  76.     }
  77.  
  78.     // A.B.C.D/1 - A.B.C.D/32 (IP with a numeric netmask)
  79.     else if (regexpmatch(network, "^" + type_ip4 + "/[01234567890]$")) {
  80.         string part_ip   = regexpsub (network, "^(" + type_ip4 + ")/[01234567890]$", "\\1");
  81.         string part_bits = regexpsub (network, "^" + type_ip4 + "(/[01234567890])$", "\\1");
  82.         
  83.         return (IP::Check4(part_ip) && ValidNetmaskBits(tointeger(part_bits)));
  84.     }
  85.  
  86.     // 0/0 (all)
  87.     else if (network == "0/0") {
  88.         return true;
  89.     }
  90.  
  91.     // A.B.C.D/E.F.G.H (IP with Netmask)
  92.     else if (regexpmatch(network, "^" + type_ip4 + "/" + type_ip4 + "$")) {
  93.         string part_ip      = regexpsub (network, "^(" + type_ip4 + ")/" + type_ip4 + "$", "\\1");
  94.         string part_netmask = regexpsub (network, "^" + type_ip4 + "/(" + type_ip4 + ")$", "\\1");
  95.         
  96.         return (IP::Check4(part_ip) && Netmask::Check4(part_netmask));
  97.     }
  98.     
  99.     // The rest
  100.     else {
  101.         y2warning("Unknown network type: %1", network);
  102.         return false;
  103.     }
  104.     }
  105.     
  106.     /**
  107.      * Returns string of valid network definition.
  108.      *
  109.      * @return string describing the valid network.
  110.      */
  111.     global string ValidNetwork () {
  112.     // TRANSLATORS: description of the valid network definition
  113.     return _("A valid network definition can contain the IP,
  114. IP/Netmask, IP/Netmask_Bits, or 0/0 for all networks.
  115.  
  116. Examples:
  117. IP: 192.168.0.1
  118. IP/Netmask: 192.168.0.0/255.255.255.0
  119. IP/Netmask_Bits: 192.168.0.0/24 or 192.168.0.1/32
  120. ");
  121.     }
  122.  
  123.     /**
  124.      * Adjusts parameters to the acceptable representation
  125.      */
  126.     map <string, string> AdjustParameters (map <string, string> params) {
  127.     if (params["network"]:"" == "") {
  128.         y2warning("No network defined, using '0/0' instead!");
  129.         params["network"]  = "0/0";
  130.     }
  131.     if (params["protocol"]:"" == "") {
  132.         y2warning("No protocol defined, using 'all' instead!");
  133.         params["protocol"] = "all";
  134.     }
  135.     params["protocol"] = tolower(params["protocol"]:"");
  136.     
  137.     return params;
  138.     }
  139.  
  140.     /**
  141.      * Returns list of rules (maps) describing protocols and ports that are allowed
  142.      * to be accessed from listed hosts. "network" and "protocol" are needed arguments,
  143.      * "dport" and "sport" are optional. Undefined values are returned as empty strings.
  144.      *
  145.      * "network" is either an IP, IP/Netmask or IP/Netmask_Bits where the connection
  146.      * originates; "protocol" defines the transport protocol; "dport" is the destination
  147.      * port on the current host; "sport" is the source port on the client.
  148.      *
  149.      * Port can be port number, port name, port range. Protocol can be 'tcp', 'udp',
  150.      * 'icmp', 'all' or '_rpc_' (dport is then a RPC service name, e.g., ypbind).
  151.      *
  152.      * @see IsValidNetwork()
  153.      *
  154.      * @struct This might return, e.g., [
  155.      *     // All requests from 80.44.11.22 to TCP port 22
  156.      *       $[ "network" : "80.44.11.22",   "protocol" : "tcp", "dport" : "22",  "sport" : ""   ],
  157.      *
  158.      *     // All requests from network 80.44.11.0/24 to UDP port 53 originating on port 53
  159.      *       $[ "network" : "80.44.11.0/24", "protocol" : "udp", "dport" : "53",  "sport" : "53" ],
  160.      *
  161.      *     // All requests from network 0/0 (everywhere) to TCP port 443
  162.      *       $[ "network" : "0/0",           "protocol" : "tcp", "dport" : "443", "sport" : ""   ],
  163.      * ]
  164.      *
  165.      * @param string zone
  166.      * @return list <map <string, string> > of rules
  167.      *
  168.      * @example
  169.      * GetListOfAcceptRules("EXT") -> $[]
  170.      */
  171.     global list <map <string, string> > GetListOfAcceptRules (string zone) {
  172.     zone = toupper(zone);
  173.  
  174.     // Check the zone
  175.     if (! contains(SuSEFirewall::GetKnownFirewallZones(), zone)) {
  176.         y2error("Unknown firewall zone: %1", zone);
  177.         return nil;
  178.     }
  179.  
  180.     //
  181.     // FW_SERVICES_ACCEPT_EXT, FW_SERVICES_ACCEPT_INT, FW_SERVICES_ACCEPT_DMZ
  182.     // Format: space separated list of net,protocol[,dport][,sport]
  183.     //
  184.     list <map <string, string> > rules = maplist (
  185.         string one_rule,
  186.         splitstring(SuSEFirewall::GetAcceptExpertRules(zone), " +"),
  187.     {
  188.         // comma separated
  189.         list <string> rule_splitted = splitstring(one_rule, ",");
  190.         return $[
  191.         "network"  : rule_splitted[0]:"",
  192.         "protocol" : rule_splitted[1]:"",
  193.         "dport"    : rule_splitted[2]:"",
  194.         "sport"    : rule_splitted[3]:"",
  195.         ];
  196.     });
  197.     
  198.     // filtering out empty rules
  199.     rules = filter (map <string, string> one_rule, rules, {
  200.         return ! (
  201.         one_rule["network"]:""  == "" &&
  202.         one_rule["protocol"]:"" == "" &&
  203.         one_rule["dport"]:""    == "" &&
  204.         one_rule["sport"]:""    == ""
  205.         );
  206.     });
  207.     
  208.     return rules;
  209.     }
  210.  
  211.     /**
  212.      * Adds a new accept-rule. Possible keys for parameters are "network",
  213.      * "protocol", "dport" and "sport". Needed are "network" and "protocol".
  214.      *
  215.      * @param string zone
  216.      * @param map <string, string> params
  217.      * @see GetListOfAcceptRules()
  218.      * @see RemoveAcceptRule()
  219.      *
  220.      * @example
  221.      * AddNewAcceptRule (
  222.      *     "EXT",
  223.      *     $["network":"192.168.0.1/255.255.240.0", "protocol":"tcp", "sport":"22"]
  224.      * ) -> true
  225.      */
  226.     global boolean AddNewAcceptRule (string zone, map <string, string> params) {
  227.     zone = toupper(zone);
  228.  
  229.     // Check the zone
  230.     if (! contains(SuSEFirewall::GetKnownFirewallZones(), zone)) {
  231.         y2error("Unknown firewall zone: %1", zone);
  232.         return nil;
  233.     }
  234.     
  235.     // Get all current rules
  236.     string current_rules = SuSEFirewall::GetAcceptExpertRules(zone);
  237.     if (current_rules == nil) {
  238.         y2error("Impossible to set new AcceptExpertRule for zone %1", zone);
  239.         return false;
  240.     }
  241.  
  242.     // Adjusting params
  243.     params = AdjustParameters(params);
  244.  
  245.     // Creating new record
  246.     string new_rule = params["network"]:"" + "," + params["protocol"]:"";
  247.     if (params["dport"]:"" != "") new_rule = new_rule + "," + params["dport"]:"";
  248.     if (params["sport"]:"" != "") new_rule = new_rule + "," + params["sport"]:"";
  249.     if (new_rule == "0/0,all") {
  250.         y2warning("Adding rule '%1' that allows everything from all networks!", new_rule);
  251.     }
  252.     
  253.     current_rules = current_rules + (size(current_rules) > 0 ? " ":"") + new_rule;
  254.     
  255.     return SuSEFirewall::SetAcceptExpertRules(zone, current_rules);
  256.     }
  257.     
  258.     /**
  259.      * Removes a single expert firewall rule.
  260.      *
  261.      * @param string zone
  262.      * @param map <string, string> params
  263.      * @see GetListOfAcceptRules() for possible keys in map
  264.      * @see AddNewAcceptRule()
  265.      *
  266.      * @example
  267.      * RemoveAcceptRule (
  268.      *     "EXT",
  269.      *     $["network":"192.168.0.1/255.255.240.0", "protocol":"tcp", "sport":"22"]
  270.      * ) -> true
  271.      */
  272.     global boolean RemoveAcceptRule (string zone, map <string, string> params) {
  273.     zone = toupper(zone);
  274.  
  275.     // Check the zone
  276.     if (! contains(SuSEFirewall::GetKnownFirewallZones(), zone)) {
  277.         y2error("Unknown firewall zone: %1", zone);
  278.         return nil;
  279.     }
  280.  
  281.     string current_rules = SuSEFirewall::GetAcceptExpertRules(zone);
  282.     if (current_rules == nil) {
  283.         y2error("Impossible remove any AcceptExpertRule for zone %1", zone);
  284.         return false;
  285.     }
  286.  
  287.     // Creating record to be removed
  288.     string remove_rule = params["network"]:"" + "," + params["protocol"]:"";
  289.     if (params["dport"]:"" != "") remove_rule = remove_rule + "," + params["dport"]:"";
  290.     if (params["sport"]:"" != "") remove_rule = remove_rule + "," + params["sport"]:"";
  291.  
  292.     // Filtering out the record
  293.     list <string> current_rules_list = splitstring (current_rules, " ");
  294.     current_rules_list = filter (string one_rule, current_rules_list, {
  295.         return (one_rule != remove_rule && one_rule != "" && one_rule != ",");
  296.     });
  297.     current_rules = mergestring (current_rules_list, " ");
  298.     
  299.     return SuSEFirewall::SetAcceptExpertRules(zone, current_rules);
  300.     }
  301.  
  302. /* EOF */
  303. }
  304.