Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/certbot/certbot.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'certbot-apache/certbot_apache/_internal/obj.py')
-rw-r--r--certbot-apache/certbot_apache/_internal/obj.py269
1 files changed, 269 insertions, 0 deletions
diff --git a/certbot-apache/certbot_apache/_internal/obj.py b/certbot-apache/certbot_apache/_internal/obj.py
new file mode 100644
index 000000000..8b3aeb376
--- /dev/null
+++ b/certbot-apache/certbot_apache/_internal/obj.py
@@ -0,0 +1,269 @@
+"""Module contains classes used by the Apache Configurator."""
+import re
+
+from acme.magic_typing import Set # pylint: disable=unused-import, no-name-in-module
+from certbot.plugins import common
+
+
+class Addr(common.Addr):
+ """Represents an Apache address."""
+
+ def __eq__(self, other):
+ """This is defined as equivalent within Apache.
+
+ ip_addr:* == ip_addr
+
+ """
+ if isinstance(other, self.__class__):
+ return ((self.tup == other.tup) or
+ (self.tup[0] == other.tup[0] and
+ self.is_wildcard() and other.is_wildcard()))
+ return False
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __repr__(self):
+ return "certbot_apache._internal.obj.Addr(" + repr(self.tup) + ")"
+
+ def __hash__(self): # pylint: disable=useless-super-delegation
+ # Python 3 requires explicit overridden for __hash__ if __eq__ or
+ # __cmp__ is overridden. See https://bugs.python.org/issue2235
+ return super(Addr, self).__hash__()
+
+ def _addr_less_specific(self, addr):
+ """Returns if addr.get_addr() is more specific than self.get_addr()."""
+ # pylint: disable=protected-access
+ return addr._rank_specific_addr() > self._rank_specific_addr()
+
+ def _rank_specific_addr(self):
+ """Returns numerical rank for get_addr()
+
+ :returns: 2 - FQ, 1 - wildcard, 0 - _default_
+ :rtype: int
+
+ """
+ if self.get_addr() == "_default_":
+ return 0
+ elif self.get_addr() == "*":
+ return 1
+ return 2
+
+ def conflicts(self, addr):
+ r"""Returns if address could conflict with correct function of self.
+
+ Could addr take away service provided by self within Apache?
+
+ .. note::IP Address is more important than wildcard.
+ Connection from 127.0.0.1:80 with choices of *:80 and 127.0.0.1:*
+ chooses 127.0.0.1:\*
+
+ .. todo:: Handle domain name addrs...
+
+ Examples:
+
+ ========================================= =====
+ ``127.0.0.1:\*.conflicts(127.0.0.1:443)`` True
+ ``127.0.0.1:443.conflicts(127.0.0.1:\*)`` False
+ ``\*:443.conflicts(\*:80)`` False
+ ``_default_:443.conflicts(\*:443)`` True
+ ========================================= =====
+
+ """
+ if self._addr_less_specific(addr):
+ return True
+ elif self.get_addr() == addr.get_addr():
+ if self.is_wildcard() or self.get_port() == addr.get_port():
+ return True
+ return False
+
+ def is_wildcard(self):
+ """Returns if address has a wildcard port."""
+ return self.tup[1] == "*" or not self.tup[1]
+
+ def get_sni_addr(self, port):
+ """Returns the least specific address that resolves on the port.
+
+ Examples:
+
+ - ``1.2.3.4:443`` -> ``1.2.3.4:<port>``
+ - ``1.2.3.4:*`` -> ``1.2.3.4:*``
+
+ :param str port: Desired port
+
+ """
+ if self.is_wildcard():
+ return self
+
+ return self.get_addr_obj(port)
+
+
+class VirtualHost(object):
+ """Represents an Apache Virtualhost.
+
+ :ivar str filep: file path of VH
+ :ivar str path: Augeas path to virtual host
+ :ivar set addrs: Virtual Host addresses (:class:`set` of
+ :class:`common.Addr`)
+ :ivar str name: ServerName of VHost
+ :ivar list aliases: Server aliases of vhost
+ (:class:`list` of :class:`str`)
+
+ :ivar bool ssl: SSLEngine on in vhost
+ :ivar bool enabled: Virtual host is enabled
+ :ivar bool modmacro: VirtualHost is using mod_macro
+ :ivar VirtualHost ancestor: A non-SSL VirtualHost this is based on
+
+ https://httpd.apache.org/docs/2.4/vhosts/details.html
+
+ .. todo:: Any vhost that includes the magic _default_ wildcard is given the
+ same ServerName as the main server.
+
+ """
+ # ?: is used for not returning enclosed characters
+ strip_name = re.compile(r"^(?:.+://)?([^ :$]*)")
+
+ def __init__(self, filep, path, addrs, ssl, enabled, name=None,
+ aliases=None, modmacro=False, ancestor=None):
+
+ """Initialize a VH."""
+ self.filep = filep
+ self.path = path
+ self.addrs = addrs
+ self.name = name
+ self.aliases = aliases if aliases is not None else set()
+ self.ssl = ssl
+ self.enabled = enabled
+ self.modmacro = modmacro
+ self.ancestor = ancestor
+
+ def get_names(self):
+ """Return a set of all names."""
+ all_names = set() # type: Set[str]
+ all_names.update(self.aliases)
+ # Strip out any scheme:// and <port> field from servername
+ if self.name is not None:
+ all_names.add(VirtualHost.strip_name.findall(self.name)[0])
+
+ return all_names
+
+ def __str__(self):
+ return (
+ "File: {filename}\n"
+ "Vhost path: {vhpath}\n"
+ "Addresses: {addrs}\n"
+ "Name: {name}\n"
+ "Aliases: {aliases}\n"
+ "TLS Enabled: {tls}\n"
+ "Site Enabled: {active}\n"
+ "mod_macro Vhost: {modmacro}".format(
+ filename=self.filep,
+ vhpath=self.path,
+ addrs=", ".join(str(addr) for addr in self.addrs),
+ name=self.name if self.name is not None else "",
+ aliases=", ".join(name for name in self.aliases),
+ tls="Yes" if self.ssl else "No",
+ active="Yes" if self.enabled else "No",
+ modmacro="Yes" if self.modmacro else "No"))
+
+ def display_repr(self):
+ """Return a representation of VHost to be used in dialog"""
+ return (
+ "File: {filename}\n"
+ "Addresses: {addrs}\n"
+ "Names: {names}\n"
+ "HTTPS: {https}\n".format(
+ filename=self.filep,
+ addrs=", ".join(str(addr) for addr in self.addrs),
+ names=", ".join(self.get_names()),
+ https="Yes" if self.ssl else "No"))
+
+
+ def __eq__(self, other):
+ if isinstance(other, self.__class__):
+ return (self.filep == other.filep and self.path == other.path and
+ self.addrs == other.addrs and
+ self.get_names() == other.get_names() and
+ self.ssl == other.ssl and
+ self.enabled == other.enabled and
+ self.modmacro == other.modmacro)
+
+ return False
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return hash((self.filep, self.path,
+ tuple(self.addrs), tuple(self.get_names()),
+ self.ssl, self.enabled, self.modmacro))
+
+ def conflicts(self, addrs):
+ """See if vhost conflicts with any of the addrs.
+
+ This determines whether or not these addresses would/could overwrite
+ the vhost addresses.
+
+ :param addrs: Iterable Addresses
+ :type addrs: Iterable :class:~obj.Addr
+
+ :returns: If addresses conflicts with vhost
+ :rtype: bool
+
+ """
+ for pot_addr in addrs:
+ for addr in self.addrs:
+ if addr.conflicts(pot_addr):
+ return True
+ return False
+
+ def same_server(self, vhost, generic=False):
+ """Determines if the vhost is the same 'server'.
+
+ Used in redirection - indicates whether or not the two virtual hosts
+ serve on the exact same IP combinations, but different ports.
+ The generic flag indicates that that we're trying to match to a
+ default or generic vhost
+
+ .. todo:: Handle _default_
+
+ """
+
+ if not generic:
+ if vhost.get_names() != self.get_names():
+ return False
+
+ # If equal and set is not empty... assume same server
+ if self.name is not None or self.aliases:
+ return True
+ # If we're looking for a generic vhost,
+ # don't return one with a ServerName
+ elif self.name:
+ return False
+
+ # Both sets of names are empty.
+
+ # Make conservative educated guess... this is very restrictive
+ # Consider adding more safety checks.
+ if len(vhost.addrs) != len(self.addrs):
+ return False
+
+ # already_found acts to keep everything very conservative.
+ # Don't allow multiple ip:ports in same set.
+ already_found = set() # type: Set[str]
+
+ for addr in vhost.addrs:
+ for local_addr in self.addrs:
+ if (local_addr.get_addr() == addr.get_addr() and
+ local_addr != addr and
+ local_addr.get_addr() not in already_found):
+
+ # This intends to make sure we aren't double counting...
+ # e.g. 127.0.0.1:* - We require same number of addrs
+ # currently
+ already_found.add(local_addr.get_addr())
+ break
+ else:
+ return False
+
+ return True