Class CalendarAddressGuard

java.lang.Object
org.exoplatform.agenda.util.CalendarAddressGuard

public class CalendarAddressGuard extends Object
Decides which calendar links the platform may be made to read (EXO-90278).

Why. A subscription makes the server fetch a URL a user typed, again and again. Unguarded, that turns eXo into a client of whatever sits on its own network — an administration console on loopback, a database's HTTP port on a private address, the cloud metadata endpoint handing out credentials.

What it decides. The URL's shape — http or https (webcal:// is read as https), no credentials in it, a port in the allowed set — and the addresses its host resolves to: loopback, link-local (the metadata address 169.254.169.254 among them), private, carrier-grade NAT, multicast, broadcast and reserved, unspecified, IPv6 unique-local and site-local, and each of those spelled as an IPv4 address inside an IPv6 one (mapped, compatible, NAT64, 6to4) are refused unless the deployment allows internal addresses. The rules are caldav-integration's CaldavServerUrlValidator#isBlocked, copied rather than depended on — caldav-integration depends on agenda — and extended with the reserved range, 198.18.0.0/15 and the NAT64 and 6to4 forms.

Where the address is checked. resolveAllowed(java.lang.String) is the resolver of the HTTP client's connection manager, so it judges the very addresses the client then connects to, for every connection it opens — every redirect hop included. A name that resolved to a public address when the user typed it and to a private one when the job refreshes it (DNS rebinding) is refused at that connection, not trusted from an earlier answer. What stays outside its reach: a public server that itself relays the request inward, and the time a refused or unreachable answer takes, which says something about a public host.

  • Field Details

    • MAX_URL_LENGTH

      public static final int MAX_URL_LENGTH
      Longest URL accepted.
      See Also:
  • Constructor Details

    • CalendarAddressGuard

      public CalendarAddressGuard(boolean allowInternalAddresses, Set<Integer> allowedPorts)
      The guard of a deployment.
      Parameters:
      allowInternalAddresses - whether internal addresses may be read at all
      allowedPorts - the ports a URL may reach, implicit default ports included
  • Method Details

    • normalize

      public URI normalize(String url) throws CalendarFeedException
      Reads a URL as the user typed it: trimmed, webcal:// and webcals:// read as https://, the fragment dropped, then checked by checkTarget(java.net.URI). Nothing is resolved here.
      Parameters:
      url - the URL as typed
      Returns:
      the URL to read
      Throws:
      CalendarFeedException - with the reason it is refused
    • checkTarget

      public URI checkTarget(URI uri) throws CalendarFeedException
      Checks the shape of a URL about to be read — the one typed, or the target of a redirect: absolute, http or https, no credentials, a host, a port in the allowed set.
      Parameters:
      uri - the URL
      Returns:
      the URL with its scheme lower-cased
      Throws:
      CalendarFeedException - with the reason it is refused
    • resolveAllowed

      public InetAddress[] resolveAllowed(String host) throws UnknownHostException
      Resolves a host and refuses it when ANY of its addresses is one the platform must not reach — a name answering one public and one loopback address is a name reaching loopback. This is the HTTP client's resolver: its answer is what the client connects to.
      Parameters:
      host - the host, brackets of an IPv6 literal allowed
      Returns:
      the addresses, every one allowed
      Throws:
      CalendarAddressGuard.RefusedAddressException - when an address is refused
      UnknownHostException - when the host resolves to nothing
    • isBlocked

      public static boolean isBlocked(InetAddress address)
      Whether one address is outside what a calendar link may point at.

      The JDK predicates cover the any-local, loopback, link-local, site-local (RFC 1918 in IPv4, fec0::/10 in IPv6) and multicast addresses; the byte inspection covers the rest, and the IPv4 address an IPv6 address may carry, which is how ::ffff:127.0.0.1 or 64:ff9b::a9fe:a9fe would otherwise walk past a loopback or metadata check.

      Parameters:
      address - one resolved address
      Returns:
      true when the platform must not reach it