Esempio n. 1
0
    def verify(self):
        """
		Run some basic verifications on the rule
		This will e.g. verify that the hosts referred to do exist, services are
		properly defined and so on.
		"""
        # verify server name given
        if self.server != "":
            if not Firewall.hosts.has_key(self.server):
                raise PyromanException("Rule refers to unknown host as server: '%s' at %s" \
                 % (self.server, self.loginfo))
        # verify client name given
        if self.client != "":
            if not Firewall.hosts.has_key(self.client):
                raise PyromanException("Rule refers to unknown host as client: '%s' at %s" \
                 % (self.client, self.loginfo))
        # for services not yet defined, try to autocreate them
        if self.service != "" and self.service not in Firewall.services:
            try:
                s = Service(name=self.service,
                            sports="",
                            dports=self.service,
                            include=None,
                            loginfo=self.loginfo)
                Firewall.services[self.service] = s
            except PortInvalidSpec:
                raise PyromanException("Rule refers to unknown service: '%s' at %s" \
                 % (self.service, self.loginfo))
Esempio n. 2
0
    def __init__(self, name, sports="", dports="", include="", loginfo=""):
        """
		Create new service object with string parameters

		sports -- source port specifications like "www/tcp dns/udp"
		dports -- destination port specifications
		include -- include rules for other services to be included/aliased
		loginfo -- reference line number for user error messages
		"""
        if name == "" or not Util.verify_name(name, servicename=True):
            raise PyromanException("service lacking a proper name: '%s' at %s" \
             % (name, loginfo))
        if Firewall.services.has_key(name):
            raise PyromanException(
                "Duplicate service specification: '%s' at %s" %
                (name, loginfo))
        if sports == "" and dports == "" and include == "" and (name != "ANY"):
            raise PyromanException(
                "service specification invalid: '%s' at %s" % (name, loginfo))

        self.name = name
        self.loginfo = loginfo
        try:
            self.sports = map(lambda p: Port(p), Util.splitter.split(sports))
            self.dports = map(lambda p: Port(p), Util.splitter.split(dports))
        except PortInvalidSpec, p:
            raise PyromanException("Service '%s' contains invalid port spec '%s' at %s: %s" \
             % (name, p.spec, loginfo, p.err))
Esempio n. 3
0
	def make_chain_name(inface, outface, client, server):
		"""
		Generate chain name from interface and host names

		The maximum length for iptables is 32 chars, this will be
		checked and an error reported if the name becomes too long.
		"""
		if client and client.islocalhost():
			if not outface:
				outface = inface
			inface = None
		if server and server.islocalhost():
			if not inface:
				inface = outface
			outface = None

		# get ascii names
		ifname, ofname, cname, sname = ("","","","")
		if inface:
			ifname = inface.name
		if outface:
			ofname = outface.name
		if client:
			cname = client.name
		if server:
			sname = server.name

		chain = "%s_%s_%s_%s" % (ifname, ofname, cname, sname)
		if len(chain) >= 32:
			raise PyromanException("Chain name length too long, use shorter nicknames: %s" % chain)

		return chain
Esempio n. 4
0
    def verify(self):
        """
		Verify that the host is properly specified.
		Verifies that the interface given was properly defined.
		"""
        if not Firewall.interfaces.has_key(self.iface):
            raise PyromanException("Host '%s' is assigned interface '%s' which is not defined at %s" \
             % (self.name, self.iface, self.loginfo))
Esempio n. 5
0
    def verify(self):
        """
		Verify that the service doesn't try to include a service which is not
		defined. Future versions might want to add a loop detection.
		"""
        for i in self.include:
            if not i == "" and not Firewall.services.has_key(i):
                raise PyromanException("Service '%s' tries to include undefined '%s' at %s" \
                 % (self.name, i, self.loginfo))
Esempio n. 6
0
File: nat.py Progetto: wil/pyroman
    def generate(self):
        for c in self.client:
            for s in self.server:
                client = Firewall.hosts[c]
                server = Firewall.hosts[s]
                # sanity checks, that should be moved to "verify"
                if not client or not server:
                    raise PyromanException(
                        "Client or server not found for NAT defined at %s" %
                        self.loginfo)
                if client.iface == server.iface:
                    raise PyromanException(
                        "client interface and server interface match (i.e. cannot NAT!) for NAT defined at %s"
                        % self.loginfo)

                if self.dir in ["in", "both"]:
                    self.gen_dnat(client, server)
                if self.dir in ["out", "both"]:
                    self.gen_snat(client, server)
Esempio n. 7
0
    def __init__(self, name, ip, iface, hostname="", loginfo=""):
        """
		Create a new host object, with the given name, IP specification and interface

		name -- Nickname for the host
		ip -- IP specification for the host or subnet (e.g. "127.0.0.1 10.0.0.0/24")
		iface -- Interface nickname this is connected to (only one!)
		"""
        # verify and store name
        if name == "" and not Util.verify_name(name):
            raise PyromanException("Host '%s' lacking a valid name at %s" \
             % (name, iface, loginfo))
        if Firewall.hosts.has_key(name):
            raise PyromanException("Duplicate host specification: '%s' at %s" %
                                   (name, loginfo))
        self.name = name
        # verify and store IPs
        if ip == "":
            raise PyromanException(
                "Host '%s' definition lacking IP address at %s" %
                (name, loginfo))
        self.ip = Util.splitter.split(ip)
        for i in self.ip:
            if not Util.verify_ipnet(i):
                raise PyromanException("IP specification '%s' invalid for host '%s' at %s" \
                 % (i, name, loginfo))
        # verify and store interface
        self.iface = iface
        if iface == "":
            raise PyromanException("Host definition '%s' lacking kernel interfaces at %s" \
             % (name, loginfo))
        # store "real" hostname (which may be longer than nick)
        # this is used for "localhost detection"
        self.hostname = hostname
        # store loginfo
        self.loginfo = loginfo
        # register with firewall
        Firewall.hosts[name] = self
Esempio n. 8
0
    def __init__(self, name, iface, loginfo):
        """
		Create a new interface

		name -- name for this interface (-group)
		iface -- kernel interface names, e.g. "eth0 eth1"
		"""
        if name == "" or not Util.verify_name(name):
            raise PyromanException("Interface lacking a valid name (name: %s, iface: %s) at %s" \
             % (name, iface, loginfo))
        if Firewall.interfaces.has_key(name):
            raise PyromanException(
                "Duplicate interface specification: %s at %s" %
                (name, loginfo))
        if iface == "":
            raise PyromanException("Interface definition lacking kernel interfaces: %s at %s" \
             % (name, loginfo))
        self.name = name
        self.iface = Util.splitter.split(iface)
        self.loginfo = loginfo

        # register with firewall
        Firewall.interfaces[name] = self
Esempio n. 9
0
    def __init__(self, target, server, client, service, loginfo):
        """
		Create a new rule, with given action, source, destination and service

		target -- the action if the rule matches, e.g. do_accept
		server -- host the packets are addressed to
		client -- host the packets originate from
		service -- service (i.e. ports) the packages use
		loginfo -- user information about origin of this rule for errors
		"""
        # store parameters for later use
        self.target = target
        self.server = server
        self.client = client
        self.service = service
        self.loginfo = loginfo

        if not server and not client:
            raise PyromanException(
                "Rules need at least a server or a client at %s" % loginfo)
Esempio n. 10
0
    def get_filter(self, dir, v4v6):
        """
		Generate filter rules for this service by generating a list of
		filter rules for all source and destination port combinations

		dir -- either "d" or "s" for destination filter or source filter
		v4v6 -- either 4 or 6 for IPv4 or IPv6
		"""
        # set 1 and 2 to source/dest filter characters
        if dir == "d":
            dir1 = "s"
            dir2 = "d"
        elif dir == "s":
            dir1 = "d"
            dir2 = "s"
        else:
            raise PyromanException("Invalid direction specified: %s" % dir)
        result = []
        for sp in self.sports:
            if v4v6 == 4 and not sp.forIPv4(): continue
            if v4v6 == 6 and not sp.forIPv6(): continue
            for dp in self.dports:
                if v4v6 == 4 and not dp.forIPv4(): continue
                if v4v6 == 6 and not dp.forIPv6(): continue
                # only generate rules when source and destination protocol match
                if not sp.proto or not dp.proto or sp.proto == dp.proto:
                    f1 = ""
                    if sp.proto:
                        f1 = sp.get_filter_proto() + " "
                    elif dp.proto:
                        f1 = dp.get_filter_proto() + " "
                    f2 = sp.get_filter_port(dir1)
                    f3 = dp.get_filter_port(dir2)
                    if f2 != "" or f3 != "":
                        result.append(f1 + " " + f2 + " " + f3)

        for i in self.include:
            result.extend(i.get_filter(dir, v4v6))
        return result
Esempio n. 11
0
    def get_filter(self, dir):
        """
		Generate filter rules for this interface by generating a list of
		filter rules for all source specifications

		dir -- either "d" or "s" for destination filter or source filter
		"""
        idir = None
        if dir == "d":
            idir = "o"
        elif dir == "s":
            idir = "i"
        else:
            raise PyromanException("Unknown direction specified: %s" % dir)
        # when necessary, turn around filter directions
        result = []
        for i in self.iface:
            if i == "": continue
            if i == "*":
                result.append("")
            else:
                result.append("-%s %s" % (idir, i))
        return result
Esempio n. 12
0
	def get_chain(inface, outface, client, server, loginfo):
		"""
		Make a chain for the given hosts and add it to the interface chain
		"""
		chain = Chain.make_chain_name(inface, outface, client, server)
		if not Firewall.chains.has_key(chain):
			c = Chain(chain, loginfo)

			parent = Firewall.forward

			# if we are talking about localhost, things are different...
			if client and client.islocalhost():
				parent = Firewall.output
				if not outface:
					outface = inface
				inface = None
			if server and server.islocalhost():
				parent = Firewall.input
				if not inface:
					inface = outface
				outface = None

			if not Firewall.chains.has_key(parent):
				raise PyromanException("Unknown chain specified: %s" % parent)
			p = Firewall.chains[parent]

			# this is localhost talking to localhost...
			if server and server.islocalhost() and client and client.islocalhost():
				raise PyromanException("Localhost talking to localhost?")

			crules4 = [""]
			crules6 = [""]
			srules4 = [""]
			srules6 = [""]
			ifrules = [""]
			ofrules = [""]
			if client:
				crules4 = client.get_filter4("s")
				crules6 = client.get_filter6("s")
			if server:
				srules4 = server.get_filter4("d")
				srules6 = server.get_filter6("d")
			if inface:
				ifrules = inface.get_filter("s")
			if outface:
				ofrules = outface.get_filter("d")

			for cr in crules4:
				for sr in srules4:
					for infi in ifrules:
						for outfi in ofrules:
							filter = "%s %s %s %s -j %s" % (infi, outfi, cr, sr, chain)
							p.append4(filter, loginfo)

			for cr in crules6:
				for sr in srules6:
					for infi in ifrules:
						for outfi in ofrules:
							filter = "%s %s %s %s -j %s" % (infi, outfi, cr, sr, chain)
							p.append6(filter, loginfo)

			Firewall.chains[chain]=c
			return c
		else:
			return Firewall.chains[chain]
Esempio n. 13
0
File: nat.py Progetto: wil/pyroman
    def __init__(self, client, server, ip, port, dport, dir, loginfo):
        """
		Create a new NAT rule

		client -- clients allowed to access this NAT rule
		server -- host nick the NAT is applied to
		ip -- IP that is used in NAT
		port -- Ports that are used in NAT
		dport -- Destination port for single port redirections
		dir -- incoming, outgoing or bidirecitonal NAT

		Note that the NAT is always applied to the "server" host, the UI
		accessible function is responsible to eventually exchange client
		and server for "outgoing" NATs (where the naming of client, server
		makes more sense the other way, think of workstations accessing
		web server via a NAT)
		"""
        if server == "":
            raise PyromanException(
                "Nat lacking a server host (client: %s, server: %s, ip: %s) at %s"
                % (client, server, ip, loginfo))
        if ip == "":
            raise PyromanException(
                "Nat lacking IP address: (client: %s, server: %s) at %s" %
                (client, server, loginfo))
        if dir not in ["in", "out", "both"]:
            raise PyromanException(
                "Nat with invalid direction: (client: %s, server: %s, ip: %s, dir: %s) at %s"
                % (client, server, ip, dir, loginfo))
        if not Util.verify_ip4(ip):
            raise PyromanException(
                "Nat with invalid IP address: (client: %s, server: %s, ip: %s) at %s"
                % (client, server, ip, loginfo))
        if port:
            try:
                self.port = Port(port)
            except PortInvalidSpec:
                raise PyromanException(
                    "Nat port specification invalid: (client: %s, server: %s, ip: %s, port: %s) at %s "
                    % (client, server, ip, port, loginfo))
            if not self.port.forIPv4():
                raise PyromanException("Non-IPv4 port specified: " + port)
        else:
            self.port = None
        if dport:
            try:
                self.dport = Port(dport)
            except PortInvalidSpec:
                raise PyromanException(
                    "Nat dport specification invalid: (client: %s, server: %s, ip: %s, port: %s, dport: %s) at %s "
                    % (client, server, ip, port, dport, loginfo))
            if not self.dport.forIPv4():
                raise PyromanException("Non-IPv4 port specified: " + dport)
        else:
            self.dport = None
        if self.dport and not (self.port.proto == self.dport.proto):
            raise PyromanException(
                "Nat ports have different protocols: (client: %s, server: %s, ip: %s, port: %s, dport: %s) at %s"
                % (client, server, ip, port, dport, loginfo))
        if dport and not port:
            raise PyromanException(
                "Nat with destination port, but no source port: (client: %s, server: %s, ip: %s, dport: %s) at %s"
                % (client, server, ip, dport, loginfo))
        self.client = Util.splitter.split(client)
        self.server = Util.splitter.split(server)
        self.ip = ip
        # port, dport are set above
        self.dir = dir
        self.loginfo = loginfo
Esempio n. 14
0
	def __init__(self):
		"""
		Dummy initialization function, will raise PyromanException(an exception!)
		"""
		raise PyromanException("Instanciation not supported!")