Class CaldavServerUrlValidator
Why this exists. Once a server is declared, connected users drive requests at that address from the platform, with server-side credentials, over the verbs the relay allows. Every other guard in the relay is client-facing, so before this class the effective trust boundary was whatever an administrator typed — and an address pointing inside the deployment's own network turned eXo into the thing that reaches it. That is a server-side request forgery surface, open by omission rather than by decision.
What it decides. Scheme (https, http only where the deployment opts in), host (loopback, link-local and private ranges refused by default), and shape (no credentials in the URL, no fragment, no port outside the allowed set). It refuses; it never rewrites what it was given, because a sanitised address is an address nobody typed and nobody can reason about.
What it does not close — say it plainly. The host check resolves the name and judges the addresses it gets back at declaration time. A name that resolves inside the allowed set now can resolve to a blocked address a second later, and nothing here would know: that is DNS rebinding, and validating at declaration time reduces the surface without closing it. Closing it needs the check to move to connection time, per connection, on the address actually dialled — which the JDK HTTP client does not offer a hook for. Nothing in this class should be read as claiming otherwise.
The {username} placeholder. A declared URL may carry one; it
is substituted per connecting user. It is refused in the scheme or authority
position, where a substituted value could move the request to another host,
and accepted after it, where it cannot. The rest of the URL is then checked
with the placeholder replaced by a plain sentinel, so the template is
validated in the shape it will actually be used in rather than rejected for
carrying a brace.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringRefused: the URL carries a user name or password in its authority.static final StringRefused: the URL carries a fragment.static final StringRefused: the string is not a usable absolute http(s) URL at all.static final StringRefused: the port is outside the allowed set.static final StringRefused: the host points at a loopback, link-local or private address.static final StringRefused: the scheme is outside the allowed set.static final StringRefused: the host resolves to nothing.static final StringRefused: the{username}placeholder sits in the authority.static final StringThe placeholder a declared URL may carry, substituted per user. -
Constructor Summary
ConstructorsConstructorDescriptionCaldavServerUrlValidator(String allowedSchemes, String allowedPorts, String allowedHosts, boolean allowPrivateAddresses) The validator Spring builds, reading the deployment's configuration and resolving names through the JDK. -
Method Summary
Modifier and TypeMethodDescriptionvoidRefuses a declared CalDAV server address the platform must not be made to connect to, with the message code the REST layer answers 400 with — at declaration time, where an administrator reads the reason, rather than at synchronisation time, where the same refusal is an unexplained sync failure.
-
Field Details
-
MALFORMED_MESSAGE
Refused: the string is not a usable absolute http(s) URL at all.- See Also:
-
SCHEME_NOT_ALLOWED_MESSAGE
Refused: the scheme is outside the allowed set.- See Also:
-
CREDENTIALS_MESSAGE
Refused: the URL carries a user name or password in its authority.- See Also:
-
FRAGMENT_MESSAGE
Refused: the URL carries a fragment.- See Also:
-
PORT_NOT_ALLOWED_MESSAGE
Refused: the port is outside the allowed set.- See Also:
-
USERNAME_IN_AUTHORITY_MESSAGE
Refused: the{username}placeholder sits in the authority.- See Also:
-
PRIVATE_ADDRESS_MESSAGE
Refused: the host points at a loopback, link-local or private address.- See Also:
-
UNRESOLVABLE_MESSAGE
Refused: the host resolves to nothing.- See Also:
-
USERNAME_PLACEHOLDER
The placeholder a declared URL may carry, substituted per user.- See Also:
-
-
Constructor Details
-
CaldavServerUrlValidator
@Autowired public CaldavServerUrlValidator(@Value("${exo.agenda.caldav.server.allowedSchemes:https}") String allowedSchemes, @Value("${exo.agenda.caldav.server.allowedPorts:80,443}") String allowedPorts, @Value("${exo.agenda.caldav.server.allowedHosts:}") String allowedHosts, @Value("${exo.agenda.caldav.server.allowPrivateAddresses:false}") boolean allowPrivateAddresses) The validator Spring builds, reading the deployment's configuration and resolving names through the JDK.- Parameters:
allowedSchemes- comma-separated URL schemes an administrator may declare;httpsalone by default, so a deployment fronting a plain-http CalDAV server has to say soallowedPorts- comma-separated ports a declared URL may reach, implicit default ports included;80,443by defaultallowedHosts- comma-separated hosts exempted from the private-address block — the narrow opt-out, for the deployment whose CalDAV server genuinely is internal; empty by defaultallowPrivateAddresses- whether ANY private, loopback or link-local address may be declared; false by default, and the blunt instrument next to the host list above
-
-
Method Details
-
validate
Refuses a declared CalDAV server address the platform must not be made to connect to, with the message code the REST layer answers 400 with — at declaration time, where an administrator reads the reason, rather than at synchronisation time, where the same refusal is an unexplained sync failure.- Parameters:
declaredUrl- the address as the administrator typed it, placeholder included- Throws:
IllegalArgumentException- carrying a translatable message code when the address is refused
-