# Gufw 10.10.1 - http://gufw.tuxfamily.org
# Copyright (C) 2008-2010 Marcos Alvarez Costales <marcos@ubuntu-ast.org>
#
# Gufw is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# 
# Gufw is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Gufw; if not, see http://www.gnu.org/licenses for more
# information.

import commands

from GufwLog import GufwLog
from Rule    import Rule


class Firewall:
    """Set or get the properties of Firewall"""
    def __init__(self):
        self.gufw_log = GufwLog()
        self.rule = Rule()
        
        self.status = self.get_ufw_status()
        self.report = self.get_initial_report()
        self.incoming_policy = self.get_ufw_policy("incoming")
        self.outgoing_policy = self.get_ufw_policy("outgoing")
        self.ufw_logging = self.get_ufw_log()
    
    def get_initial_report(self):
        cmd = commands.getstatusoutput("grep report=enable /etc/gufw/gufw.cfg")
        if cmd[1].find("enable") != -1:
            return "enable"
        else:
            return "disable"
    
    def get_ufw_status(self):
        ufw_status = commands.getstatusoutput("LANGUAGE=C ufw status")
        if ufw_status[1].find("Status: active") != -1:
            return "enable"
        else:
            return "disable"
    
    def get_ufw_policy(self, policy):
        if policy == "incoming":
            ufw_default_incoming = commands.getstatusoutput("grep DEFAULT_INPUT_POLICY /etc/default/ufw")
            if ufw_default_incoming[1].find("ACCEPT") != -1:
                return "allow"
            elif ufw_default_incoming[1].find("DROP") != -1:
                return "deny"
            elif ufw_default_incoming[1].find("REJECT") != -1:
                return "reject"
        
        elif policy == "outgoing":
            ufw_default_outgoing = commands.getstatusoutput("grep DEFAULT_OUTPUT_POLICY /etc/default/ufw")
            if ufw_default_outgoing[1].find("ACCEPT") != -1:
                return "allow"
            elif ufw_default_outgoing[1].find("DROP") != -1:
                return "deny"
            elif ufw_default_outgoing[1].find("REJECT") != -1:
                return "reject"
    
    def get_ufw_log(self):
        ufw_cmd = commands.getstatusoutput("LANGUAGE=C ufw status verbose")
        if ufw_cmd[1].find("Logging: on (high)") != -1:
            return "high"
        elif ufw_cmd[1].find("Logging: on (medium)") != -1:
            return "medium"
        elif ufw_cmd[1].find("Logging: on (low)") != -1:
            return "low"
        elif ufw_cmd[1].find("Logging: on (full)") != -1:
            return "full"
        else:
            return "off"
    
    def get_status(self):
        """Return actual status"""
        return self.status
    
    def get_report(self):
        """Return actual listening report"""
        return self.report
    
    def set_report(self,report):
        """Set actual listening report"""
        self.report = report
        
    def set_status(self, status):
        """Set status to ufw [enable|disable]"""
        if status == "enable":
            cmd = "ufw enable"
            self.status = "enable"
        else:
            cmd = "ufw disable"
            self.status = "disable"
        
        ufw_cmd = commands.getstatusoutput(cmd)
        self.gufw_log.add_log(cmd)
    
    def get_listening_report(self):
        return_report = []
        actual_protocol = "None"
        
        ufw_report = commands.getstatusoutput("LANGUAGE=C ufw show listening")
        report_lines = ufw_report[1].replace("\n   [","%")
        report_lines = report_lines.split("\n")
        for descomponent_report in report_lines:
            # Set actual protocol
            if descomponent_report == "":
                continue
            if descomponent_report.find("tcp6:") != -1:
                actual_protocol = "TCP6"
                continue
            if descomponent_report.find("tcp:") != -1:
                actual_protocol = "TCP"
                continue
            if descomponent_report.find("udp6:") != -1:
                actual_protocol = "UDP6"
                continue
            if descomponent_report.find("udp:") != -1:
                actual_protocol = "UDP"
                continue
                
            policy = "None"
            descomponent_report = descomponent_report.strip()
            descomponent_report = descomponent_report.replace("(","")
            descomponent_report = descomponent_report.replace(")","")
            
            if descomponent_report.find("]") != -1:
                descomponent_policy = descomponent_report.split("]")
                if descomponent_policy[1].find("allow") != -1:
                    policy = "allow"
                elif descomponent_policy[1].find("deny") != -1:
                    policy = "deny"
                elif descomponent_policy[1].find("reject") != -1:
                    policy = "reject"
                elif descomponent_policy[1].find("limit") != -1:
                    policy = "limit"
            
            descomponent_report = descomponent_report.split("%")
            descomponent_fields = descomponent_report[0].split(" ")
            # Order: protocol % port % address % application % policy
            return_report.append(actual_protocol + "%" + descomponent_fields[0] + "%" + descomponent_fields[1] + "%" + descomponent_fields[2] + "%" + policy)
        
        return return_report
    
    def get_default_policy(self, policy):
        """Get actual policy for incoming or outgoing traffic [allow|deny|reject]"""
        if policy == "incoming":
            return self.incoming_policy
        else:
            return self.outgoing_policy
            
    def set_default_policy(self, direction, policy):
        """Set policy [allow|deny|reject] for the direction [incoming|outgoing] specify"""
        if direction == "incoming":
            if policy == "allow":
                cmd = "ufw default allow incoming"
                self.incoming_policy = "allow"
            elif policy == "deny":
                cmd = "ufw default deny incoming"
                self.incoming_policy = "deny"
            elif policy == "reject":
                cmd = "ufw default reject incoming"
                self.incoming_policy = "reject"
                
        elif direction == "outgoing":
            if policy == "allow":
                cmd = "ufw default allow outgoing"
                self.outgoing_policy = "allow"
            elif policy == "deny":
                cmd = "ufw default deny outgoing"
                self.outgoing_policy = "deny"
            elif policy == "reject":
                cmd = "ufw default reject outgoing"
                self.outgoing_policy = "reject"
        
        ufw_cmd = commands.getstatusoutput(cmd)
        self.gufw_log.add_log(cmd)
    
    def reset_configuration(self):
        """Reset the configuration to initial status"""
        cmd = "ufw --force reset"
        ufw_cmd = commands.getstatusoutput(cmd)
        self.rule.refresh_rules()
        self.gufw_log.add_log(cmd)
    
    def get_ufw_logging(self):
        """Return the ufw logging"""
        return self.ufw_logging
        
    def refresh_ufw_logging(self):
        """Reload the ufw logging"""
        self.ufw_logging = self.get_ufw_log()
    
    def set_ufw_logging(self, logging):
        """Set the ufw logging"""
        if logging == "off":
            cmd = "ufw logging off"
        elif logging == "on":
            cmd = "ufw logging on"
        elif logging == "low":
            cmd = "ufw logging low"
        elif logging == "medium":
            cmd = "ufw logging medium"
        elif logging == "high":
            cmd = "ufw logging high"
        elif logging == "full":
            cmd = "ufw logging full"
        
        ufw_cmd = commands.getstatusoutput(cmd)
        self.gufw_log.add_log(cmd)
        self.ufw_logging = self.get_ufw_log()
        
    
    def get_gufw_log(self):
        log_local, log_server = self.gufw_log.get_log()
        return log_local, log_server
    
    def remove_gufw_log(self):
        self.gufw_log.remove_log()
    
    def get_gufw_logging(self):
        return self.gufw_log.get_logging()
    
    def set_gufw_logging(self, logging):
        self.gufw_log.set_logging(logging)
    
    def add_rule(self, is_program, insert_number, action, direction, log, protocol, fromip, fromport, toip, toport):
        previus_rules = self.get_rules()
        ufw_result, cmd = self.rule.add_rule(is_program, insert_number, action, direction, log, protocol, fromip, fromport, toip, toport)
        self.gufw_log.add_log(cmd)
        if previus_rules != self.get_rules():
            return 0
        else:
            return 1
    
    def remove_rule(self, number_rule):
        ufw_result, cmd = self.rule.remove_rule(number_rule)
        self.gufw_log.add_log(cmd)
        return ufw_result
    
    def get_rules(self):
        return self.rule.get_rules()
        
