Adding documentation for request validation
diff --git a/pom.xml b/pom.xml
index d8ebc96..6eab34e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>org.apache.archiva</groupId>
     <artifactId>archiva-parent</artifactId>
-    <version>16-SNAPSHOT</version>
+    <version>17-SNAPSHOT</version>
     <relativePath>../parent/pom.xml</relativePath>
   </parent>
   <artifactId>redback-site</artifactId>
diff --git a/src/site/apt/configuration.apt b/src/site/apt/configuration.apt
index 1a4be40..998aa5e 100644
--- a/src/site/apt/configuration.apt
+++ b/src/site/apt/configuration.apt
@@ -56,9 +56,9 @@
 
 ** Application Configuration
 
-  * application.timestamp=EEE d MMM yyyy HH:mm:ss Z
+  * <<<application.timestamp=EEE d MMM yyyy HH:mm:ss Z>>>
 
-  * application.url=http://myurl.mycompany.com
+  * <<<application.url=http://myurl.mycompany.com>>>
   
     * Set the application base URL. The default is to derive it from the HTTP request
 
@@ -67,13 +67,13 @@
   By default Redback uses Apache Derby for persistence of user and role
 information.  This can be configured with the following options.
 
-  * jdbc.driver.name=org.apache.derby.jdbc.EmbeddedDriver
+  * <<<jdbc.driver.name=org.apache.derby.jdbc.EmbeddedDriver>>>
 
-  * jdbc.url=jdbc:derby:${plexus.home}/database;create=true
+  * <<<jdbc.url=jdbc:derby:${plexus.home}/database;create=true>>>
 
-  * jdbc.username=sa
+  * <<<jdbc.username=sa>>>
 
-  * jdbc.password=
+  * <<<jdbc.password=>>>
 
   []
 
@@ -85,39 +85,39 @@
 
 ** Email Settings
 
-  * email.jndiSessionName=java:comp/env/mail/Session
+  * <<<email.jndiSessionName=java:comp/env/mail/Session>>>
   
-  * email.smtp.host=localhost
+  * <<<email.smtp.host=localhost>>>
 
-  * email.smtp.port=25
+  * <<<email.smtp.port=25>>>
 
-  * email.smtp.ssl.enabled=false
+  * <<<email.smtp.ssl.enabled=false>>>
 
-  * email.smtp.tls.enabled=false
+  * <<<email.smtp.tls.enabled=false>>>
  
-  * email.smtp.username=
+  * <<<email.smtp.username=>>>
 
-  * email.smtp.password=
+  * <<<email.smtp.password=>>>
 
-  * email.from.address=${user.name}@localhost
+  * <<<email.from.address=${user.name}@localhost>>>
   
     * All emails sent by the system will be from the following address
 
-  * email.from.name=Unconfigured Username
+  * <<<email.from.name=Unconfigured Username>>>
 
-  * email.validation.required=true
+  * <<<email.validation.required=true>>>
 
     * If all email addresses (from new user registration) require an account validation email. 
 
-  * email.validation.timeout=2880
+  * <<<email.validation.timeout=2880>>>
 
     * Timeout (in minutes) for the key generated for an email validation to remain valid.
 
     * 2880 minutes = 48 hours
 
-  * email.validation.subject=Welcome
+  * <<<email.validation.subject=Welcome>>>
 
-  * email.feedback.path=/feedback.action
+  * <<<email.feedback.path=/feedback.action>>>
 
     * Get the Feedback to use for any outgoing emails.
 
@@ -127,13 +127,13 @@
 
 ** Auto Login Settings
 
-  * security.rememberme.enabled=true
+  * <<<security.rememberme.enabled=true>>>
 
-  * security.rememberme.timeout=365
+  * <<<security.rememberme.timeout=365>>>
 
     * Timeout in days
 
-  * security.signon.timeout=30
+  * <<<security.signon.timeout=30>>>
 
     * Single Sign On
     
@@ -141,11 +141,11 @@
 
 ** Default Username Values
 
-  * redback.default.admin=admin
+  * <<<redback.default.admin=admin>>>
 
     * name for the admin user, by default this is 'admin' and can not easily be changed after the fact at this point.  However any number of people may be assigned full administrator roles.
 
-  * redback.default.guest=guest (currently guest is an hardcoded value so not possible to configure it)
+  * <<<redback.default.guest=guest>>> (currently guest is an hardcoded value so not possible to configure it)
 
     * name of the guest user
 
@@ -153,23 +153,23 @@
 
 ** Security Policies
 
-  * security.policy.password.encoder=
+  * <<<security.policy.password.encoder=>>>
 
-  * security.policy.password.previous.count=6
+  * <<<security.policy.password.previous.count=6>>>
 
-  * security.policy.password.expiration.enabled=true
+  * <<<security.policy.password.expiration.enabled=true>>>
 
-  * security.policy.password.expiration.days=90
+  * <<<security.policy.password.expiration.days=90>>>
 
-  * security.policy.password.expiration.notify.days=10
+  * <<<security.policy.password.expiration.notify.days=10>>>
 
-  * security.policy.allowed.login.attempt=10
+  * <<<security.policy.allowed.login.attempt=10>>>
 
-  * security.policy.strict.enforcement.enabled=true
+  * <<<security.policy.strict.enforcement.enabled=true>>>
   
     * turn off the perclick enforcement of various security policies, slightly more heavyweight since it will ensure that the User object on each click is up to date
 
-  * security.policy.strict.force.password.change.enabled=true
+  * <<<security.policy.strict.force.password.change.enabled=true>>>
 
     * forces the user to change their password immediately should their account be flagged for a password change.
 
@@ -179,73 +179,98 @@
 
 ** Password Rules
 
-  * security.policy.password.rule.alphanumeric.enabled=false
+  * <<<security.policy.password.rule.alphanumeric.enabled=false>>>
 
-  * security.policy.password.rule.alphacount.enabled=true
+  * <<<security.policy.password.rule.alphacount.enabled=true>>>
 
-  * security.policy.password.rule.alphacount.minimum=1
+  * <<<security.policy.password.rule.alphacount.minimum=1>>>
 
-  * security.policy.password.rule.characterlength.enabled=true
+  * <<<security.policy.password.rule.characterlength.enabled=true>>>
 
-  * security.policy.password.rule.characterlength.minimum=1
+  * <<<security.policy.password.rule.characterlength.minimum=1>>>
 
-  * security.policy.password.rule.characterlength.maximum=24
+  * <<<security.policy.password.rule.characterlength.maximum=24>>>
 
-  * security.policy.password.rule.musthave.enabled=true
+  * <<<security.policy.password.rule.musthave.enabled=true>>>
 
-  * security.policy.password.rule.numericalcount.enabled=true
+  * <<<security.policy.password.rule.numericalcount.enabled=true>>>
 
-  * security.policy.password.rule.numericalcount.minimum=1
+  * <<<security.policy.password.rule.numericalcount.minimum=1>>>
 
-  * security.policy.password.rule.reuse.enabled=true
+  * <<<security.policy.password.rule.reuse.enabled=true>>>
 
-  * security.policy.password.rule.nowhitespace.enabled=true
+  * <<<security.policy.password.rule.nowhitespace.enabled=true>>>
 
 ** LDAP settings
 
   Ldap can be used as a readonly user manager, however the role assignment is still managed entirely within the given database store.  This should be fixed in the future sometime but likely not before ldap is switched over as the default user and role store entirely.
 
-  * ldap.user.store.enabled=false
+  * <<<ldap.user.store.enabled=false>>>
 
-  * ldap.bind.authenticator.enabled=false
+  * <<<ldap.bind.authenticator.enabled=false>>>
 
 *** ldap options for configuration via properties file
 
-  * ldap.config.hostname=
+  * <<<ldap.config.hostname=>>>
 
-  * ldap.config.port=
+  * <<<ldap.config.port=>>>
 
-  * ldap.config.base.dn=
+  * <<<ldap.config.base.dn=>>>
 
-  * ldap.config.context.factory=
+  * <<<ldap.config.context.factory=>>>
 
-  * ldap.config.bind.dn=
+  * <<<ldap.config.bind.dn=>>>
 
-  * ldap.config.password=
+  * <<<ldap.config.password=>>>
  
-  * ldap.config.authentication.method=
+  * <<<ldap.config.authentication.method=>>>
 
-  * ldap.config.groups.class= object class for groups (default: groupOfUniqueNames)
+  * <<<ldap.config.groups.class=>>> object class for groups (default: groupOfUniqueNames)
 
-  * ldap.config.groups.base.dn= basedn for groups, dn with list of groups ( dc=archiva,dc=apache,dc=org ) (if empty default will be ldap.config.base.dn)
+  * <<<ldap.config.groups.base.dn= basedn>>> for groups, dn with list of groups ( dc=archiva,dc=apache,dc=org ) (if empty default will be ldap.config.base.dn)
 
-  * ldap.config.groups.role.*(ldap group)=*(roles) (mapping ldap group <-> redback roles comma separated) (example: ldap.config.groups.role.archiva-admin=Archiva System Administrator, Foo)
+  * <<<ldap.config.groups.role.*(ldap group)=*(roles)>>> (mapping ldap group <-> redback roles comma separated) (example: ldap.config.groups.role.archiva-admin=Archiva System Administrator, Foo)
 
-  * ldap.config.writable=true/false will write datas to ldap (default false)
+  * <<<ldap.config.writable=true/false>>> will write datas to ldap (default false)
 
-  * ldap.config.groups.use.rolename=true/false will create/use groups in ldap with default role if no group<->role mapping found (default false)
+  * <<<ldap.config.groups.use.rolename=true/false>>> will create/use groups in ldap with default role if no group<->role mapping found (default false)
 
-  * ldap.config.user.attribute= attribute name to use for user (default uid=)
+  * <<<ldap.config.user.attribute=>>> attribute name to use for user (default uid=)
 
 ** User Manager Implementation(s) to use
 
-  * user.manager.impl=cached (since 1.4-M4: Archiva support more than one value comma separated)
+  * <<<user.manager.impl=cached>>> (since 1.4-M4: Archiva support more than one value comma separated)
   
     * valid values for realistic usage are 'cached' and then further configuring the cached instance to use another underlying user manager like ldap or the jdo one which is used by default.  Placing 'ldap' here will check with the ldap system for a fair amount of checks and would likely be a performance issue
 
 ** RBAC Manager Implementation(s) to use
 
-    * rbac.manager.impl=cached (since 1.4-M4: Archiva support more than one value comma separated)
+    * <<<rbac.manager.impl=cached>>> (since 1.4-M4: Archiva support more than one value comma separated)
 
+** REST security settings
 
+*** Cross Site Request Forgery (CSRF) Prevention
+
+  There are multiple checks implemented to prevent CSRF attacks from other sides that are opened in the same browser.
+  If you use the REST services from non-Browser clients or very old Browser versions you may need to deactivate some
+  of these checks. If you deactivate these checks your archiva site will be more vulnerable to these attacks.
+
+  * <<<rest.csrffilter.enabled=true>>>
+
+    * Enable/disable the filter for CSRF prevention. Possible values: true, false
+
+  * <<<rest.baseUrl=>>>
+
+    * Set the base URL to which the Origin/Referer header are matched against. If it's empty, the URL is determined dynamically.
+
+  * <<<rest.csrffilter.absentorigin.deny=true>>>
+
+    * Defines what happens, if the client request does not contain a Origin or Referer header. This may happen with
+      native REST clients. Browsers normally add these headers to the request, if it is initiated from another site.
+      Possible values: true, false
+
+  * <<<rest.csrffilter.disableTokenValidation=false>>>
+
+    * Token validation means, that each REST request must send a validation token that is returned during the first login.
+      If you have REST clients that cannot send this token you may have to disable this feature. Possible values: true, false
   
diff --git a/src/site/apt/integration/rest.apt.vm b/src/site/apt/integration/rest.apt.vm
index 168eb6a..484e2c4 100644
--- a/src/site/apt/integration/rest.apt.vm
+++ b/src/site/apt/integration/rest.apt.vm
@@ -28,9 +28,46 @@
 
 Redback Rest Support
 
-  Prior to 1.3 version some redback services are available trough rest request.
+  Starting with version 1.3 some redback services are available trough rest request.
 
-  We use jaxrs annotations and authz/karma are verified through cxf interceptors.
+  Starting with version 2.5 we added some filters to prevent CSRF attacks.
+
+  We use JAXRS annotations and authz/karma are verified through cxf interceptors.
+
+%{toc}
+
+* Cross Site Request Forgery ({CSRF}) prevention
+
+  Starting with version 2.5 there has been added an interceptor that tries to check for CSRF attacks. CSRF can be initiated
+  by malicious sites that let your browser execute HTTP requests or JavaScript-Code aimed to your redback site. Without
+  CSRF prevention only the login cookie is checked for proper authorization and which is sent automatically from your
+  browser after login. The redback REST services are not checking if the request is from the same origin as the login request.
+
+  For more information see https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
+
+  Redback uses two mechanisms for checking cross site requests: Header validation and a validation token.
+
+  The behaviour of the filter can be configured, see {{{../configuration.html#REST_security_settings}REST configuration}}
+
+** Header validation
+
+  The header validation uses a base URL where the incoming requests are checked against. Per default the base URL is
+  determined dynamically, but can be configured.
+
+  Each client request is checked for the HTTP headers 'Origin' and 'Referer' header.
+  If the Origin header is existent and the base URL does not match the header value the request will be denied.
+  After that the Referer header is checked and matched against the base URL. If the header is existent and does
+  not the base URL the request is denied.
+  If neither Origin nor Referer header are presented, the request is denied (can be configured).
+
+** Validation Token
+
+  If the header validation was successful, the request is checked for the X-XSRF-TOKEN header.
+  This header must contain a token that is returned from the login REST service together with the user information.
+  The token is encrypted by a key that is generated dynamically during startup of the redback service. That means
+  that after restart of the redback services all tokens generated before will be invalid.
+  Validation tokens have a lifetime of 3 hours. After that you have to login again.
+
 
 * Maven Module
 
@@ -117,6 +154,10 @@
 
 +--------------------------------------+
 
+** RequestValidationIntercepter
+
+  This is the interceptor used for CSRF prevention. See info {{{CSRF}above}}.
+
 * Client Usage
 
   Dependencies to add in order to use those REST Services