<document>
<header>
  <product>resin</product>
  <title>Resin Security</title>
  <description>
  </description>
</header>

<body>

<localtoc/>

<s1 title="Quick Start">

<p>The following sample shows how to protect a section of a web-site
with a password, using a login form.</p>

<example title="WEB-INF/resin-web.xml - Simple Password Protection">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;security-constraint url-pattern="/secure/*">
    &lt;auth-constraint role-name="*"/>

    &lt;login uri="form:login-page=/login.jsp"/>
  &lt;/security-constraint>

  &lt;authenticator uri="properties:password-digest=none">
     &lt;init>
       harry=quidditch,user
     &lt;/init>
  &lt;/authenticator>

&lt;/web-app>
</example>

<ul>
<li>&lt;security-constraint> protects a section of the web-app, i.e.
providing an authorization context.</li>
<li>&lt;url-pattern> matches the URLs to be protected</li>
<li>&lt;auth-constraint> protects the web-app through login (as opposed to
by IP address or by SSL)</li>
<li>&lt;login> specifies the login method</li>
<li>&lt;authenticator> defines the login users and passwords.
The "properties:" authenticator specifies a simple .properties file user definition.</li>
<li>password-digest=none disables the default MD5-digest for the
passwords.  Only recommended for examples.</li>
</ul>

</s1>

<s1 title="Management">

<p>Since all Resin users will want to protect
the <code>/resin-admin</code> pages with an administration password,
and protect any clustered management and deployment, Resin's top-level
&lt;management> tag includes a static, XML-based authentication context.
The authenticator is automatically shared for all hosts and web-apps, so
simple sites can even use this authenticator configuration for their
site-wide authentication.</p>

<example title="resin.xml">
&lt;resin xmlns="http://caucho.com/ns/resin">

  &lt;management">
     &lt;user name="admin" password="MD5HASH=="/>

     ...
  &lt;/management>

  ...

&lt;/resin>
</example>

<p>The password is a hash of the user name, password, and the "resin"
realm.  The <code>/resin-admin</code> page includes a form to easily generate
the MD5 hash.  You can also use the
<a href="http://caucho.com/resin-javadoc/com/caucho/server/security/PasswordDigest.html">PasswordDigest</a> class to generate the digest
programmatically.</p>

</s1>

<s1 title="Authentication">

<p>Resin provides a basic set of authenticators covering the most
common cases.  Applications which need custom authenticators can easily
write their own extensions, described below.</p>

<s2 title="properties: - properties authentication">

<example title="WEB-INF/resin-web.xml - inline properties">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;authenticator uri="properties:password-digest=none">
     &lt;init>
       harry=quidditch,user,admin
       draco=mudblood,disabled,user
     &lt;/init>
  &lt;/authenticator>

&lt;/web-app>
</example>

<example title="WEB-INF/resin-web.xml - file property">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;authenticator uri="properties:path=WEB-INF/users.properties"/>

&lt;/web-app>
</example>
<example title="WEB-INF/users.properties">
harry=MD5HASH==,user,admin
</example>

</s2>

<s2 title="xml: - xml authentication">

<example title="WEB-INF/resin-web.xml - inline xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;authenticator uri="properties:password-digest=none">
     &lt;init>
       &lt;user name="harry" password="quidditch"/>
     &lt;/init>
  &lt;/authenticator>

&lt;/web-app>
</example>

<example title="WEB-INF/resin-web.xml - file xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;authenticator uri="properties:path=WEB-INF/users.xml"/>

&lt;/web-app>
</example>

<example title="WEB-INF/users.xml">
&lt;users>
  &lt;user name="harry password="MD5HASH==" roles="user,admin"/>
&lt;users>
</example>

</s2>

<s2 title="custom authentication">

<example title="WEB-INF/resin-web.xml - custom">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;authenticator class="com.foo.MyAuthenticator">
    &lt;init>
      &lt;foo>bar&lt;/foo>
    &lt;/init>
  &lt;/authenticator>

&lt;/web-app>
</example>

<example title="MyAuthenticator.java">
package com.foo;

import com.caucho.server.security;

public class MyAuthenticator extends AbstractPasswordAuthenticator {
  private PasswordUser _user;

  public MyAuthenticator()
  {
    _user = new PasswordUser("harry", "quidditch",
                             new String[] { "user" });
  }
192
  public PasswordUser getUser(String userName)
  {
    if (userName.equals(_user.getName()))
      return _user;
    else
      return null;
  }
}
</example>

<p>It's also possible to register your custom authenticatr with Resin's
uri-based configuration.  You'll add a file in the 
<code>META-INF/services/com.caucho.config.uri</code> named
<code>com.caucho.server.security.ServletAuthenticator</code> in the
.jar file with the following contents:</p>

<example title="com.caucho.server.security.ServletAuthenticator">
foo.my=com.foo.MyAuthenticator
</example>

</s2>

<s2 title="Quick Start">
<p>The easiest authenticator to understand is the 
<a href="#XmlAuthenticator">XmlAuthenticator</a>.
It lets you put users and passwords directly in the configuration
file.  The following example uses "Basic" authentication for login.
Basic authentication asks the browser to pop open a window prompting
for a username and password.  (Basic authentication is discouraged
because it is not secure unless you use it with SSL, but it's the
easiest example.)  The only user defined here is "Harry Potter" and
he has the password "quidditch".  He also plays the
"user" role.</p>

<example title="Using the XmlAuthenticator">
&lt;web-app xmlns="http://caucho.com/ns/resin"&gt;

  ...

  &lt;authenticator type="com.caucho.server.security.XmlAuthenticator"&gt;
    &lt;init&gt;
      &lt;user&gt;Harry Potter:quidditch:user&lt;/user&gt;
      &lt;password-digest&gt;none&lt;/password-digest&gt;
    &lt;/init&gt;
  &lt;/authenticator&gt;

  &lt;login-config auth-method="basic"/&gt;

  &lt;security-constraint url-pattern="/users-only/*" role-name="user"/&gt;

  ...

&lt;/web-app&gt;
</example>

<p>In the above example, the &lt;security-constraint&gt; checks
for authorization.  Only users playing the "user" role can access
the /users-only directory.</p>

<p>Another often used authenticator is the 
<a href="#JdbcAuthenticator">JdbcAuthenticator</a>, 
which uses usernames, passwords, and roles stored in a database.</p>

<example>
&lt;web-app xmlns="http://caucho.com/ns/resin"&gt;

  ...

  &lt;!-- Resin-specific JdbcAuthenticator --&gt;
  &lt;authenticator type='com.caucho.server.security.JdbcAuthenticator'&gt;
    &lt;init&gt;
      &lt;data-source&gt;test&lt;/data-source&gt;
      &lt;password-query&gt;
        SELECT password FROM LOGIN WHERE username=?
      &lt;/password-query&gt;
      &lt;cookie-auth-query&gt;
        SELECT username FROM LOGIN WHERE cookie=?
      &lt;/cookie-auth-query&gt;
      &lt;cookie-auth-update&gt;
        UPDATE LOGIN SET cookie=? WHERE username=?
      &lt;/cookie-auth-update&gt;
      &lt;role-query&gt;
        SELECT role FROM LOGIN WHERE username=?
      &lt;/role-query&gt;
    &lt;/init&gt;
  &lt;/authenticator&gt;

  &lt;login-config auth-method='basic'/&gt;

  &lt;security-constraint url-pattern='/users-only/*' role-name='user'/&gt;

  ...

&lt;/web-app&gt;
</example>

</s2>

<s2 title="login-config" type="defun">

<p>Configures the login class.  The <a href="webapp-tags.xtp#login-config">web.xml configuration</a> describes the
configuration in more detail.</p>

<p>The login can be customized by selecting the <code>com.caucho.server.security.AbstractLogin</code>.  The <var>type</var> attribute will select that
class. More sophisticated applications may want to add their own custom
AbstractLogin class to replace the predefined values.</p>

<p>Typically a custom login would only be necessary if the application
needed a custom way of extracting credentials from the request.</p>

</s2>

<s2 title="auth-method" type="defun">
<p>Selects the authentication method.</p>

<deftable title="auth-method values">
<tr><th>auth-method</th><th>Meaning
</th></tr><tr><td>basic</td><td>HTTP Basic authentication
</td></tr><tr><td>digest</td><td>HTTP Digest authentication
</td></tr><tr><td>form</td><td>Form-based authentication
</td></tr></deftable>

</s2>

<s2 title="form-login-config" type="defun">
<p>Configures authentication for forms.  The login form has
specific parameters that the servlet engine's login form processing
understands.  If the login succeeds, the user will see the original
page.  If it fails, she will see the error page.</p>

<deftable>
<tr><td>form-login-page</td><td>The page to be used to prompt the user login</td><td>none
</td></tr><tr><td>form-error-page</td><td>The error page for unsuccessful login</td><td>none
</td></tr><tr><td>internal-forward</td><td>Use an internal redirect on success or a sendRedirect</td><td>false
</td></tr><tr><td>form-uri-priority</td><td>If true, the form's j_uri will override a stored URI</td><td>false
</td></tr></deftable>

<p>The form itself must have the action <var>j_security_check</var>.  It
must also have the parameters <var>j_username</var> and <var>j_password</var>.
Optionally, it can also have <var>j_uri</var> and
<var>j_use_cookie_auth</var>.  <var>j_uri</var> gives the next page to display
when login succeeds.  <var>j_use_cookie_auth</var> allows Resin to send a
persistent cookie to the user to make following login easier.
</p>

<p><var>j_use_cookie_auth</var> gives control to the user whether to generate
a persistent cookie.  It lets you implement the "remember me" button.  By
default, the authentication only lasts for a single session.
</p>

<deftable title="j_security_check Parameters">
<tr><th>Parameter</th><th>Meaning)
</th></tr><tr><td>j_username</td><td>The user name
</td></tr><tr><td>j_password</td><td>The password
</td></tr><tr><td>j_uri</td><td>Resin extension for the successful display
page (Optional).
</td></tr><tr><td>j_use_cookie_auth</td><td>Resin extension to allow cookie
login (Optional).
</td></tr></deftable>

<p>The following is an example of a servlet-standard login page:</p>

<example>
&lt;form action='j_security_check' method='POST'&gt;
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;User:&lt;td&gt;&lt;input name='j_username'&gt;
&lt;tr&gt;&lt;td&gt;Password:&lt;td&gt;&lt;input name='j_password'&gt;
&lt;tr&gt;&lt;td colspan=2&gt;hint: the password is 'quidditch'
&lt;tr&gt;&lt;td&gt;&lt;input type=submit&gt;
&lt;/table&gt;
&lt;/form&gt;
</example>

</s2>

<s2 title="authenticator" version="Resin 1.1" type="defun">
<p>Specifies a class to authenticate users.  This Resin-specific
option lets you control your authentication.  You can either create your 
own custom authenticator, or use Resin's JdbcAuthenticator.</p>

<p>The authenticator is responsible for taking the username and
password and returning a UserPrincipal if the username and password match.
</p>

<p>Users wanting to implement an authenticator should look at the JavaDoc
for <a href="javadoc|com.caucho.server.security.ServletAuthenticator|"/>
and <a href="javadoc|com.caucho.server.security.AbstractAuthenticator|"/>.
To protect your application from API changes, you should extend
AbstractAuthenticator rather than implementing Authenticator directly.
</p>
</s2>

<s2 title="XmlAuthenticator" version="Resin 2.0.4">
<p>The XmlAuthenticator (com.caucho.serer.security.XmlAuthenticator),
stores the authentication in either an xml file or in the configuration
itself.</p>

<p>When configuring the XmlAuthenticator in the resin.xml
(or web.xml), each <var>user</var> adds a new configured
user.  The value contains the username, password, and the
roles the user plays.</p>

<example title="XmlAuthenticator in resin.xml">
&lt;authenticator type="com.caucho.server.security.XmlAuthenticator"&gt;
  &lt;init&gt;
    &lt;user&gt;Harry Potter:quidditch:user,gryffindor&lt;/user&gt;
    &lt;user&gt;Draco Malfoy:pureblood:user,slytherin&lt;/user&gt;
    &lt;password-digest&gt;none&lt;/password-digest&gt;
  &lt;/init&gt;
&lt;/authenticator&gt;
</example>

<p>Because the plain text passwords in the example
above are a serious security issue, most sites will use
the password-digest attribute described below to protect the
passwords.</p>

<deftable>
<tr><th>attribute</th><th>meaning</th><th>default
</th></tr><tr><td>user</td><td>specifies an allowed user.  May be repeated.</td><td>none
</td></tr><tr><td><a href="#password-digest">password-digest</a></td><td>selects the signature method to protect
the password</td><td>md5-base64
</td></tr><tr><td>path</td><td>specifies a path to an XML file containing the users and passwords.</td><td>none
</td></tr><tr><td>logout-on-session-timeout</td><td>If true, the user will be logged out when the session times out</td><td>true
</td></tr></deftable>

<p>The passwords can be specified in a separate *.xml file.  The password
file looks like:</p>

<example title="password.xml">
&lt;authenticator&gt;
  &lt;user name='Harry Potter' password='quidditch' roles='gryffindor'/&gt;
  &lt;user name='Draco Malfoy' password='pureblood' roles='slytherin'/&gt;
&lt;/authenticator&gt;
</example>

<p>Sites should use <a href="#password-digest">password-digest</a> to protect the passwords.</p>

</s2>

<s2 title="JdbcAuthenticator" version="Resin 2.0">
<p>The JdbcAuthenticator (<a href="javadoc|com.caucho.server.security.JdbcAuthenticator|"/>)
asks a backend database for the password matching the user's name.
It uses the DataSource specified by the <var>pool-name</var> option, or
the JNDI <var>java:comp/env/jdbc/db-pool</var> by default.
<var>pool-name</var> refers to a DataSource configured with
<a href="env-tags.xtp#database">database</a>.</p>

<p>The following are the attributes for the JdbcAuthenticator:</p>

<deftable>
<tr><th>attribute</th><th>meaning</th><th>default
</th></tr><tr><td>data-source</td><td>The database pool.  Looks in the application
attributes first, then in the global database pools.</td><td>none
</td></tr><tr><td>password-query</td><td>A SQL query to get the user's password.  The
default query is given below.</td><td>see below
</td></tr><tr><td>cookie-auth-query</td><td>A SQL query to authenticate the user by a
persistent cookie.</td><td>none
</td></tr><tr><td>cookie-auth-update</td><td>A SQL update to match
a persistent cookie to a user.</td><td>none
</td></tr><tr><td>role-query</td><td>A SQL query to determine the user's role.  By
default, all users are in role "user", but no others.</td><td>none
</td></tr><tr><td><a href="#password-digest">password-digest</a></td><td>Specifies the digest algorithm and format (Resin 2.0.4)</td><td>md5-base64
</td></tr><tr><td>logout-on-session-timeout</td><td>If true, the user will be logged out when the session times out (Resin 2.0.6)</td><td>true
</td></tr></deftable>

<example>
&lt;web-app xmlns="http://caucho.com/ns/resin"&gt;

  ...

  &lt;!-- Resin-specific JdbcAuthenticator --&gt;
  &lt;authenticator type='com.caucho.server.security.JdbcAuthenticator'&gt;
    &lt;init&gt;
      &lt;data-source&gt;test&lt;/data-source&gt;
      &lt;password-query&gt;
        SELECT password FROM LOGIN WHERE username=?
      &lt;/password-query&gt;
      &lt;cookie-auth-query&gt;
        SELECT username FROM LOGIN WHERE cookie=?
      &lt;/cookie-auth-query&gt;
      &lt;cookie-auth-update&gt;
        UPDATE LOGIN SET cookie=? WHERE username=?
      &lt;/cookie-auth-update&gt;
      &lt;role-query&gt;
        SELECT role FROM LOGIN WHERE username=?
      &lt;/role-query&gt;
    &lt;/init&gt;
  &lt;/authenticator&gt;

  &lt;login-config auth-method='basic'/&gt;

  &lt;security-constraint url-pattern='/users-only/*' role-name='user'/&gt;

  ...

&lt;/web-app&gt;
</example>

</s2>

<s2 title="LdapAuthenticator" version="Resin 3.0.19">
<p>
The LdapAuthenticator (<a href="javadoc|com.caucho.server.security.LdapAuthenticator|"/>)
uses jndi to contact an LDAP (or Active Directory) server for authentication purposes.
</p>

<deftable>
<tr><th>attribute</th><th>meaning</th><th>default</th></tr>
<tr><td>dn-prefix</td>
    <td>string to prepend to query before portion selecting user by name</td>
    <td>none</td></tr>
<tr><td>dn-suffix</td>
    <td>string to append to query after portion selecting user by name</td>
    <td>none</td></tr>
<tr><td><a href="#jndi-env">jndi-env</a></td>
    <td>Add a property to the jndi provider used for connecting to the ldap server</td>
    <td>see below</td></tr>
<tr><td>logout-on-session-timeout</td>
    <td>If true, the user will be logged out when the session times out</td>
    <td>true</td></tr>
<tr>
  <td>security-authentication</td>
  <td>Sets the Context.SECURITY_AUTHENTICATION for the ldap environment</td>
  <td></td>
</tr>
<tr>
  <td>security-principal</td>
  <td>Sets the Context.SECURITY_PRINCIPAL for the ldap environment</td>
  <td></td>
</tr>
<tr>
  <td>security-credentials</td>
  <td>Sets the Context.SECURITY_CREDENTIALS for the ldap environment</td>
  <td></td>
</tr>
<tr><td><a href="#password-digest">password-digest</a></td>
     <td>selects the signature method to protect the password</td>
     <td>md5-base64</td></tr>
<tr><td>user-attribute</td>
    <td>the attribute name to use in the query for matching the user</td>
    <td>uid</td></tr>
<tr><td>password-attribute</td>
    <td>the attribute name to use for obtaining the password</td>
    <td>userPassword</td></tr>
<tr><td>url</td>
    <td>the url for the server (since Resin 3.1.1)</td>
    <td>ldap://localhost:389</td></tr>
</deftable>

<example>
&lt;web-app xmlns="http://caucho.com/ns/resin"&gt;

  ...

  &lt;authenticator&gt;
    &lt;type&gt;com.caucho.server.security.LdapAuthenticator&lt;/type&gt;
    &lt;init&gt;
      &lt;url&gt;ldap://localhost:389&lt;/url&gt;
      &lt;dn-suffix&gt;dc=hogwarts,dc=com&lt;/dn-suffix&gt;
      &lt;password-digest&gt;none&lt;/password-digest&gt;
    &lt;/init&gt;
  &lt;/authenticator&gt;

  ...

&lt;/web-app&gt;

</example>

<s3 title="jndi-env">

<p>jndi-env configures properties of the ldap provider implementation.
Prior to 3.1.1, the url of the server is specified with
<code>jndi-env</code> and the <code>java.naming.provider.url</code> property.
</p>

<example title="LdapAuthenticator jndi-env">
  &lt;authenticator&gt;
    &lt;type&gt;com.caucho.server.security.LdapAuthenticator&lt;/type&gt;
    &lt;init&gt;
      &lt;jndi-env java.naming.factory.initial="com.sun.jndi.ldap.LdapCtxFactory"/&gt;
      &lt;jndi-env java.naming.provider.url="ldap://localhost:389"/&gt;

      &lt;dn-suffix&gt;dc=hogwarts,dc=com&lt;/dn-suffix&gt;
      &lt;password-digest&gt;none&lt;/password-digest&gt;
    &lt;/init&gt;
  &lt;/authenticator&gt;
</example>
</s3>
</s2>

<s2 title="JaasAuthenticator" version="Resin 3.0.12">
<p>
The JaasAuthenticator (<a href="javadoc|com.caucho.server.security.JaasAuthenticator|"/>)
uses a JAAS LoginModule for authentication.  The JaasAuthenticator is an
adapter that provides the ability to use the large number of JAAS LoginModule's
included in the JDK for authentication purposes.
</p>

<deftable>
<tr><th>attribute</th><th>meaning</th><th>default</th></tr>
<tr><td><a href="#jaas-init-param">init-param</a></td>
    <td>Add a property to the LoginModule</td>
    <td>none</td></tr>
<tr><td>login-module</td>
    <td>The fully qualified class name of the LoginModule implementation</td>
    <td>required</td></tr>
<tr><td>logout-on-session-timeout</td>
    <td>If true, the user will be logged out when the session times out</td>
    <td>true</td></tr>
<tr><td><a href="#password-digest">password-digest</a></td>
     <td>selects the signature method to protect the password</td>
     <td>md5-base64</td></tr>
</deftable>

<example title="JaasAuthenticator configuration">
&lt;web-app xmlns="http://caucho.com/ns/resin"&gt;

  &lt;authenticator type="com.caucho.server.security.JaasAuthenticator"&gt;
    &lt;init&gt;
      &lt;login-module&gt;com.sun.security.auth.module.Krb5LoginModule&lt;/login-module&gt;
      &lt;init-param&gt;
        &lt;debug&gt;true&lt;/debug&gt;
      &lt;/init-param&gt;
    &lt;/init&gt;
  &lt;/authenticator&gt;

&lt;/web-app&gt;
</example>

<s3 name="jaas-is-user-in-role" title="isUserInRole">
<p>
The isUserInRole method is supported if the LoginModule provides either an
isUserInRole method in the Principal returned by the LoginModule, or a
getRoles() method returning a java.util.Set. (Since 3.0.19).
</p>
</s3> <!-- jaas-is-user-in-role -->

<s3 name="jaas-init-param" title="init-param">

<p>
&lt;init-param&gt; directives are used to configure the properties of the
LoginModule. Existing LoginModules provide documentation of the init-param that
are accepted. Custom LoginModule implementations retrieve the init-param values
in the initialize method.
</p>

</s3> <!-- jaas-init-param -->

<s3 name="jaas-custom" title="Custom LoginModule">

<example title="Custom LoginModule - java code">
import java.util.*;

import javax.security.auth.*;
import javax.security.auth.spi.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;

public class TestLoginModule implements javax.security.auth.spi.LoginModule {
  private Subject _subject;
  private CallbackHandler _handler;
  private Map _state;
 
  private String _userName;
  private String _password;

  public void initialize(Subject subject,
                         CallbackHandler handler,
                         Map sharedState,
                         Map options)
   {
     _subject = subject;
     _handler = handler;
     _state = sharedState;

     _userName = (String) _options.get("user");
     _password = (String) _options.get("password");
   }

   public boolean login()
     throws LoginException
   {
     NameCallback name = new NameCallback("");
     PasswordCallback password = new PasswordCallback("", false);
 
     _handler.handle(new Callback[] { name, password });

     if (_userName.equals(name.getName()) &amp;&amp; 
         _password.equals(password.getPassword()) {
         _subject.getPrincipals().add(new TestPrincipal(_userName));
       return true;
     }
     else
       return false;
   }

   public boolean abort()
   {
     return true;
   }

   public boolean commit()
   {
     return _subject.getPrincipals().size() > 0;
   }

   public boolean logout()
   {
      return true;
   }
}
</example>

<example title="Custom LoginModule - resin-web.xml configuration">
&lt;web-app xmlns="http://caucho.com/ns/resin"&gt;

  &lt;authenticator type="com.caucho.server.security.JaasAuthenticator"&gt;
    &lt;init&gt;
      &lt;login-module&gt;example.TestModule&lt;/login-module&gt;
      &lt;init-param&gt;
        &lt;user&gt;Harry&lt;/user&gt;
        &lt;password&gt;quidditch&lt;/password&gt;
      &lt;/init-param&gt;
    &lt;/init&gt;
  &lt;/authenticator&gt;
&lt;/web-app&gt;
</example>
</s3> <!-- jaas-custom -->

</s2> <!-- JaasAuthenticator -->

<s2 title="AuthenticationList" version="3.0.9">
<p>AuthenticatorList 
(<a href="javadoc|com.caucho.server.security.AuthenticatorList|"/>)
is used to configure more than one authenticator in a list, each
authenticator is tried in turn and if the authentication fails the next
authenticator in the list is attempted.

<example>
  &lt;authenticator type="com.caucho.server.security.AuthenticatorList"&gt;
    &lt;init&gt;
      &lt;authenticator resin:type="com.caucho.server.security.XmlAuthenticator"&gt;
        &lt;user&gt;admin:NIHlOSafJN2H7emQCkOQ2w==:user,admin&lt;/user&gt;
      &lt;/authenticator&gt;

      &lt;authenticator resin:type='com.caucho.server.security.JdbcAuthenticator'&gt;
        &lt;data-source&gt;jdbc/users&lt;/data-source&gt;
        &lt;password-query&gt;
          SELECT password FROM LOGIN WHERE username=?
        &lt;/password-query&gt;
        &lt;cookie-auth-query&gt;
          SELECT username FROM LOGIN WHERE cookie=?
        &lt;/cookie-auth-query&gt;
        &lt;cookie-auth-update&gt;
          UPDATE LOGIN SET cookie=? WHERE username=?
        &lt;/cookie-auth-update&gt;
        &lt;role-query&gt;
          SELECT role FROM LOGIN WHERE username=?
        &lt;/role-query&gt;
      &lt;/authenticator&gt;
    &lt;/init&gt;
  &lt;/authenticator&gt;

  &lt;login-config auth-method='basic'/&gt;

  &lt;security-constraint url-pattern='/users/*' role-name='user'/&gt;
  &lt;security-constraint url-pattern='/admin/*' role-name='admin'/&gt;
</example>

</p></s2>

</s1>

<s1 title="Digest passwords">

<s2 title="Digest protects passwords">

<p>Digest passwords enable an application to avoid storing and even
transmitting the password in a form that someone can read.</p>

<p>A digest of a cleartext password is calculated when it is passed through a
one-way function that consistently produces another series of characters,
<code>digestPassword = digester(username + ":" + realm + ":"
cleartextPassword)</code>.  The function is "one-way" because the
digestPassword cannot be used to reverse-engineer the original password.</p>

<p>Digest passwords can be used in two places: storage and transmission.
Digest passwords in storage means that the password is stored in a digested
form, for example in a database or in a file.
Digest passwords in transmission means that the client (usually a web browser)
creates the digest and submits the digest password to the web server.  
</p>

<p>Storing digest passwords is so important for security purposes that the
Resin <a href="authentication.xtp">authenticators</a> default to assuming
that the passwords are stored in digest form.</p>

<p>The important advantage is that a user's cleartext password is not as easily
compromised. Since the password they use (the "cleartext" password) is not
stored a malicious user cannot determine the password by gaining access to the
database or other backend storage for the passwords.</p>

</s2>

<s2 title="MD5 digest">
<p>Resin's authenticators use "MD5-base64" and a realm "resin" to digest
passwords by default. <var>MD5</var> indicates that the MD5 algorithm is used. <var>base64</var> is an encoding format to apply to the binary result of MD5.</p>


<p>Some examples are:</p>
<deftable>
<tr><th>Username</th><th>Realm</th><th>Password</th><th>digest
</th></tr><tr><td>root</td><td>resin</td><td>changeme</td><td>j/qGVP4C0T7UixSpKJpTdw==
</td></tr><tr><td>harry</td><td>resin</td><td>quidditch</td><td>uTOZTGaB6pooMDvqvl2Lbg==
</td></tr><tr><td>hpotter</td><td>resin</td><td>quidditch</td><td>x8i6aM+zOwDqqKPRO/vkxg==
</td></tr><tr><td>filch</td><td>resin</td><td>mrsnorris</td><td>KmZIq2RKXAHV4BaoNHfupQ==
</td></tr><tr><td>pince</td><td>resin</td><td>quietplease</td><td>Txpd1jQc/xwhISIqodEjfw==
</td></tr><tr><td>snape</td><td>resin</td><td>potion</td><td>I7HdZr7CTM6hZLlSd2o+CA==
</td></tr><tr><td>mcgonagall</td><td>resin</td><td>quidditch</td><td>4slsTREVeTo0sv5hGkZWag==
</td></tr><tr><td>dmalfoy</td><td>resin</td><td>pureblood</td><td>yI2uN1l97Rv5E6mdRnDFwQ==
</td></tr><tr><td>lmalfoy</td><td>resin</td><td>myself</td><td>sj/yhtU1h4LZPw7/Uy9IVA==
</td></tr></deftable>

<p>In the above example the digest of "harry/quidditch" is different than the
digest of "hpotter/quidditch" because even though the password is the same, the
username has changed. The digest is calculated with 
<code>digest(username + ":" + realm + ":" + password)</code>, so if the username
changes the resulting digest is different.</p>

</s2>

<s2 title="Calculating a digest">

<p>Of course, storing the digest password is a bit more work.  When
the user registers, the application needs to compute the
digest to store it.</p>

<!-- a form for calculating an MD5 digest -->
<!--
<jsp:scriptlet>

String digest_user = request.getParameter("digest_user");
String digest_realm = request.getParameter("digest_realm");
String digest_password = request.getParameter("digest_password");
String digest_result = null;

if (digest_realm == null || digest_realm.length() == 0)
  digest_realm = "resin";
pageContext.setAttribute("digest_realm",digest_realm);

if (digest_user != null &amp;&amp; digest_password != null)
{
  String digest_concat = digest_user + ":" + digest_realm + ":" + digest_password;

  com.caucho.http.security.PasswordDigest digest_digest = new com.caucho.http.security.PasswordDigest();

  digest_digest.setRealm(digest_realm);
  digest_result = digest_digest.getPasswordDigest(digest_user, digest_password);

  pageContext.setAttribute("digest_user",digest_user);
  pageContext.setAttribute("digest_password",digest_password);
  pageContext.setAttribute("digest_concat",digest_concat);
  pageContext.setAttribute("digest_result",digest_result);
}

String digest_requestURI = request.getRequestURI();
digest_requestURI = digest_requestURI + "#Calculating-a-digest";

pageContext.setAttribute("digest_requestURI",digest_requestURI);

</jsp:scriptlet>

<form action="${digest_requestURI}">
<jsp:scriptlet>if (digest_result == null || digest_result.length() == 0) {</jsp:scriptlet>
<p>The following form can be used to calculate an MD5-base64 digest:</p>
<jsp:scriptlet>} else {</jsp:scriptlet>
<p>The digest of <var>${digest_concat}</var> is <code><b>${digest_result}</b></code></p>
<jsp:scriptlet>}</jsp:scriptlet>

  <table>
  <tr><td><b>user id:</b>
  </td><td><input name="digest_user" size="50" value="${digest_user}"/>

  </td></tr><tr><td><b>password:</b>
  </td><td><input name="digest_password" size="50" value="${digest_password}"/>

  </td></tr><tr><td><b>realm:</b>
  </td><td><input name="digest_realm" size="50" value="${digest_realm}"/>
  </td></tr><tr><td><input type="submit"/>
  </td></tr></table>
</form>
-->

<p>Unix users can quickly calculate a digest:</p>
<example>
echo -n "user:resin:password" | openssl dgst -md5 -binary | uuencode -m -
</example>

<p>The class <a href="javadoc|com.caucho.http.security.PasswordDigest|"/> can
be used to calculate a digest.</p>

<example title="Calculating a digest - Java example">
  import com.caucho.server.security.PasswordDigest;

  ...

  String username = ...;
  String password = ...;
  String realm = "resin";

  PasswordDigest passwordDigest = PasswordDigest();

  String digest = passwordDigest.getPasswordDigest(username, password, realm);
</example>

<example title="Calculating a digest - PHP example">
  $username = ...;
  $password = ...;
  $realm = "resin";

  $passwordDigest = new Java("com.caucho.server.security.PasswordDigest");

  $digest = $passwordDigest-&gt;getPasswordDigest($username, $password, $realm);
</example>

<p>
The realm for JdbcAuthenticator and XmlAuthenticator defaults to "resin";
the realm can be specified during configuration:
</p>

<example title="Specifying a realm">

&lt;authenticator type='com.caucho.server.security.JdbcAuthenticator'&gt;
  &lt;init&gt;
    &lt;password-digest-realm&gt;hogwarts&lt;/password-digest-realm&gt;

    ...
</example>

</s2>

<s2 title="Using Digest with basic authentication or a form login">

<p>When using the form login method or the HTTP basic authentication login
method, the password submitted is in cleartext.  The Resin authenticator will
digest the password before comparing it to the value retrieved from storage.
The message is transmitted in cleartext but is stored as a digest. This method
provides only half of the protection - the password is not protected in
transmission (although if the form submit is being done over an <a href="ssl.xtp">SSL</a> connection it will be secure).</p>

</s2>


<s2 title="Using HTTP digest authentication">

<p>The HTTP protocol includes a method to indicate to the client that it should
make a digest using the password.  The client submits a digest to Resin instead
of submitting a cleartext password. HTTP digest authentication protects the password in transmission.</p>

<p>When using HTTP digest, Resin will respond to the browser and ask it to
calculcate a digest. The steps involved are:</p>
<ul>
<li>Resin provides the client a realm and some other information 
</li><li>The client obtains a username and password (usually a dialog box with a web browser)
</li><li>The client calculates a digest using the username, realm, pasword, and other information supplied by Resin
</li><li>The client submits the digest to Resin
</li><li>Resin does the same digest calculation as the client did
</li><li>Resin compares the submitted digest and the digest it calculated.  If they match, the user has been authenticated
</li>
</ul>

<p>The advantage of this method is that the cleartext password is protected in
transmission, it cannot be determined from the digest that is submitted by the
client to the server.</p>

<p>HTTP digest authentication is enabled with the <a config-tag="auth-method"/> child of the <a config-tag="login-config"/> configuration tag.</p>

<example title="Using HTTP digest authentication">
&lt;login-config&gt;
  &lt;auth-method&gt;DIGEST&lt;/auth-method&gt;
&lt;/login-config&gt;
</example>

</s2>

<s2 title="Disabling the use of password-digest">

<p>Although it is not advised, Resin's authenticators can be configured to use
passwords that are not in digest form.</p>

<example title="Disabling the use of password-digest">
&lt;authenticator&gt;
  &lt;type&gt;com.caucho.server.security.XmlAuthenticator&lt;/type&gt;
  &lt;init&gt;
     &lt;password-digest&gt;none&lt;/password-digest&gt;
     &lt;user&gt;harry:quidditch:user&lt;/user&gt;
  &lt;/init&gt;
&lt;/authenticator&gt;
</example>

</s2>

<s2 title="Compatibility">

<p>Authenticators are not defined by the 
<a href="http://www.jcp.org/en/jsr/detail?id=154">Servlet Specification</a>, 
so the ability to use passwords stored as a digest depends
upon the implementation of the Authenticator that the application server
provides.  MD5-base64 is the most common form of digest, because it is the
default in <a href="#Using-HTTP-digest-authentication">HTTP digest
authentication</a>.</p>

<p>The use of <code>&lt;auth-method&gt;DIGEST&lt;auth-method&gt;</code> is
defined in the Servlet Specification and implemented in most
application servers.</p>

</s2>
</s1>

<s1 title="Single Signon" version="Resin 3.0.0">

<p>"Single signon" refers to allowing for a single login for more
than one context, for example, logging in to all web-apps in a server at once.
You can implement single signon by configuring the authenticator in
the proper environment: web-app, host, or server.  The login will last for
all the web-apps in that environment.</p>

<p>The authenticator is a resource which is shared across its <a href="env-tags.xtp">environment</a>.
For example, to configure the XML authenticator
for all web-apps in foo.com, you might configure as follows:</p>

<example title="Single Signon for foo.com">
&lt;resin xmlns="http://caucho.com/ns/resin"&gt;
  &lt;cluster id="app-tier&gt;
    &lt;http port="8080"/&gt;

    &lt;host id="foo.com"&gt;
      &lt;root-directory&gt;/opt/foo.com&lt;/root-directory&gt;

      &lt;authenticator type="com.caucho.server.security.XmlAuthenticator"&gt;
        &lt;init&gt;
          &lt;!-- password: quidditch --&gt;
          &lt;user&gt;harry:uTOZTGaB6pooMDvqvl2LBu:user,gryffindor&lt;/user&gt;
          &lt;!-- password: pureblood --&gt;
          &lt;user&gt;dmalfoy:yI2uN1l97Rv5E6mdRnDFDB:user,slytherin&lt;/user&gt;
        &lt;/init&gt;
      &lt;/authenticator&gt;

      &lt;web-app-deploy path="webapps"/&gt;
    &lt;/host&gt;
  &lt;/cluster&gt;
&lt;/resin&gt;
</example>

<p>Any .war in the webapps directory will share the same signon for the
host.  You will still need to implement a
<a href="webapp-tags.xtp#login-config">login-config</a> for each web-app.</p>

<p>
The value of <a config-tag="reuse-session-id">reuse-session-id</a> must be <code>true</code>
for single signon.
</p>


<s2 title="Single signon for virtual hosts">
<p>
The basis for establishing client identity is the JSESSIONID cookie.  If single
signon is desired for virtual hosts, Resin must be configured to notify the
browser of the proper domain name for the cookie so that the same JSESSIONID
cookie is submitted by the browser to each virtual host.
</p>

<p>
The <a href="#authenticator">authenticator</a> is placed at the cluster level
so that it is common to all virtual hosts.  The
<a href="webapp-tags.xtp#session-config">cookie-domain</a> is
placed in a <a href="webapp-tags.xtp#web-app-default">web-app-default</a> at
the cluster level so that it is applied as the default for all webapps in all
virtual hosts.
</p>

<example title="Single Signon for gryffindor.hogwarts.com and slytherin.hogwarts.com">
&lt;resin xmlns="http://caucho.com/ns/resin"&gt;
  &lt;cluster id="app-tier&gt;
    &lt;http port="8080"/&gt;

    &lt;authenticator type="com.caucho.server.security.XmlAuthenticator"&gt;
      ...
    &lt;/authenticator&gt;

    &lt;web-app-default&gt;
      &lt;session-config&gt;
        &lt;enable-url-rewriting&gt;false&lt;/enable-url-rewriting&gt;
        &lt;cookie-domain&gt;.hogwarts.com&lt;/cookie-domain&gt;
      &lt;/session-config&gt;
    &lt;/web-app-default&gt;


    &lt;host id="gryffindor.hogwarts.com"&gt;
      ...
    &lt;/host&gt;

    &lt;host id="slytherin.hogwarts.com"&gt;
      ...
    &lt;/host&gt;
  &lt;/server&gt;
&lt;/resin&gt;
</example>

<p>
Because of the way that browsers are restricted by the HTTP specification from
submitting cookies to servers, it is not possible to have a single signon for
virtual hosts that do not share some portion of their domain name.  For example,
"gryffindor.com" and "slytherin.com" cannot share a common authentication.
</p>
</s2>

</s1>

<s1 title="Custom Login">
<p>The Login is primarily responsible for extracting the credentials
from the request (typically username and password) and passing those
to the ServletAuthenticator.</p>

<p>The Servlet API calls the Login in two contexts: directly from
<code>ServletRequest.getUserPrincipal()</code>, and during 
security checking.   When called from the Servlet API, the login class
can't change the response.  In other words, if an application
calls getUserPrincipal(), the Login class can't return a forbidden
error page.  When the servlet engine calls authenticate(), the login class
can return an error page (or forward internally.)</p>

<p>Normally, Login implementations will defer the actual authentication
to a ServletAuthenticator class.  That way, both "basic" and "form" login
can use the same JdbcAuthenticator.  Some applications, like SSL
client certificate login, may want to combine the Login and authentication
into one class.</p>

 <p>Login instances are configured through bean introspection.  Adding
 a public <code>setFoo(String foo)</code> method will be configured with
 the following login-config:</p>

<example>
&lt;login-config type="test.CustomLogin"&gt;
  &lt;init&gt;
    &lt;foo&gt;bar&lt;/bar&gt;
  &lt;/init&gt;
&lt;/login-config&gt;
</example>

</s1>

<s1 title="Security Constraints">

<s2 title="security-constraint" type="defun">
<parents>web-app</parents>

<p>Selects protected areas of the web site.  Sites using
authentication as an optional personalization feature will typically
not use any security constraints.  Sites using authentication to limit
access to certain sections of the website to certain users will use
security constraints.</p>

<p>Security constraints can also be custom classes.</p>

<example title="Protecting all pages for logged-in users">
&lt;web-app&gt;
  ...
&lt;security-constraint&gt;
  &lt;web-resource-collection&gt;
    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  &lt;/web-resource-collection&gt;
  &lt;auth-constraint role-name='user'/&gt;
&lt;/security-constraint&gt;
  ...
&lt;/web-app&gt;
</example>
</s2>

<s2 title="web-resource-collection" type="defun">
<parents>security-constraint</parents>

<p>Specifies a collection of areas of the web site.</p>

<deftable-childtags>
<tr><td>url-pattern</td><td>url patterns describing the resource
</td></tr><tr><td>http-method</td><td>HTTP methods to be restricted.
</td></tr></deftable-childtags>
</s2>

<s2 title="auth-constraint" type="defun">
<parents>security-constraint</parents>

<p>Requires that authenticated users fill the specified role.
In Resin's JdbcAuthenticator, normal users are in the "user" role.
Think of a role as a group of users.</p>

<deftable-childtags>
<tr><td>role-name</td><td>Roles which are allowed to access the resource.
</td></tr></deftable-childtags>

<example title="Protecting webdav for webdav users">
&lt;security-constraint&gt;
  &lt;auth-constraint role-name='webdav'/&gt;

  &lt;web-resource-collection&gt;
    &lt;url-pattern&gt;/webdav/*&lt;/url-pattern&gt;
  &lt;/web-resource-collection&gt;
&lt;/security-constraint&gt;
</example>

</s2>

<s2 title="ip-constraint" version="Resin 2.0.6" type="defun">
<parents>security-constraint</parents>

<p>Allow or deny requests based on the ip address of the client.
ip-constraint is very useful for protecting administration resources
to an internal network.  It can also be useful for denying service to known
problem ip's.</p>

<example title="Admin pages allowed from 192.168.17.0/24">
&lt;security-constraint&gt;
  &lt;web-resource-collection&gt;
    &lt;url-pattern&gt;/admin/*&lt;/url-pattern&gt;
  &lt;/web-resource-collection&gt;

  &lt;ip-constraint&gt;
    &lt;allow&gt;192.168.17.0/24&lt;/allow&gt;
  &lt;/ip-constraint&gt;
&lt;/security-constraint&gt;
</example>

<p>The <code>/24</code> in the ip <code>192.168.17.0/24</code> means that the
first 24 bits of the ip are matched - any ip address that begins with
<code>192.168.17.</code> will match.  The usage of <var>/bits</var> is
optional.</p> 

<example title="Block out known trouble makers">
&lt;security-constraint&gt;
  &lt;ip-constraint&gt;
    &lt;deny&gt;205.11.12.3&lt;/deny&gt;
    &lt;deny&gt;213.43.62.45&lt;/deny&gt;
    &lt;deny&gt;123.4.45.6&lt;/deny&gt;
    &lt;deny&gt;233.15.25.35&lt;/deny&gt;
    &lt;deny&gt;233.14.87.12&lt;/deny&gt;
  &lt;/ip-constraint&gt;

  &lt;web-resource-collection&gt;
    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  &lt;/web-resource-collection&gt;
&lt;/security-constraint&gt;
</example>

<p>Be careful with deny - some ISP's (like AOL) use proxies and the ip of many
different users may appear to be the same ip to your server.</p>

<deftable-childtags>
<tr><td>allow</td><td>add an ip address to allow</td><td>default is to allow all ip addresses
</td></tr><tr><td>deny</td><td>add an ip address to deny</td><td>default is to deny no ip addresses
</td></tr><tr><td>error-code</td><td>error code to send if request is denied</td><td>403
</td></tr><tr><td>error-message</td><td>error message to send if request is denied</td><td>Forbidden IP Address
</td></tr><tr><td>cache-size</td><td>cache size, the result of applying rules for an ip is cached for subsequent requests</td><td>256
</td></tr></deftable-childtags>

<p>If only <var>deny</var> is used, then all ip's are allowed if they do not match
a <code>deny</code>.  If only <var>allow</var> is used, then an ip is denied unless it
matches an <code>allow</code>. If both are used, then the ip must match both an
<code>allow</code> and a <code>deny</code></p>

</s2>

<s2 title="user-data-constraint" type="defun">
<parents>security-constraint</parents>

<p>Restricts access to secure transports, i.e. SSL.</p>

<deftable-childtags>
<tr><td>transport-guarantee</td><td>Required transport properties.  NONE,
INTEGRAL, and CONFIDENTIAL are allowed values.
</td></tr></deftable-childtags>

<example>
&lt;security-constraint&gt;
  &lt;user-data-constraint&gt;
    &lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;
  &lt;/user-data-constraint&gt;

  &lt;web-resource-collection&gt;
    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  &lt;/web-resource-collection&gt;
&lt;/security-constraint&gt;
</example>

<p>
The default behaviour is for Resin to rewrite any url that starts with
"http:" by replacing the "http:" part with "https:", and then send
redirect to the browser.
</p>

<p>
If the default rewriting of the host is not appropriate, you can set the
<a config-tag="secure-host-name"/> for the host:
</p>

<example>
  &lt;host id='...'&gt;
    &lt;secure-host-name&gt;https://hogwarts.com&lt;/secure-host-name&gt;

 ...
</example>

<example>
  &lt;host id='...'&gt;
    &lt;secure-host-name&gt;https://hogwarts.com:8443&lt;/secure-host-name&gt;

  ...
</example>

</s2>

<s2 title="transport-guarantee" type="defun">
<p>Restricts access to secure transports, i.e. SSL.</p>
</s2>

<s2 title="constraint" version="Resin 2.0.1" type="defun">
<parents>security-constraint</parents>

<p>Defines a custom constraint.  The custom constraint specifies a <var>resin:type</var> which extends <a href="javadoc|com.caucho.server.security.AbstractConstraint|"/>.  
<a href="ioc-bean.xtp">Bean-style initialization</a> is used to
initialize the constraint.</p>

<example>
...
&lt;security-constraint&gt;
  &lt;constraint resin:type="example.CustomConstraint&gt;
    &lt;init&gt;
      &lt;policy&gt;strict&lt;/policy&gt;
    &lt;/init&gt;
  &lt;/constraint&gt;
  &lt;web-resource-collection url-pattern='/*'/&gt;
&lt;/security-constraint&gt;
...
</example>

</s2>

</s1> <!-- Security-Constraints -->


<s1 title="Custom Security Constraints">

<p>Any custom security constraint is checked after any authentication (login)
but before any filters or servlets are applied.  The security constraint will
return true if the request is allowed and false if it's forbidden.  If the
request is forbidden, it's the constraint's responsibility to use response.sendError() or to return an error page.</p>

<example>
package example;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.caucho.server.security.*;

public class CustomSecurity extends AbstractConstraint {
  private String foo = "false";

  public void setFoo(String foo)
  {
    this.foo = foo;
  }

  public boolean needsAuthentication()
    return false;
  }

  public boolean isAuthorized(HttpServletRequest request,
                              HttpServletResponse response,
                              ServletContext application)
    throws ServletException, IOException
  {
    if (foo.equals(request.getParameter("test")))
      return true;

    response.sendError(response.SC_FORBIDDEN);

    return false;
  }
}
</example>

<p>The <code>needsAuthentication</code> method tells Resin that it needs to
log in the user before checking the authorization.  This would allow
the custom authorizer to check user roles or the user principle for
the proper permissions.</p>

<example>
&lt;constraint resin:type="example.CustomSecurity"&gt;
  &lt;foo&gt;test-value&lt;/foo&gt;
&lt;/constraint&gt;
</example>

</s1>

<s1 name="protectall" title="Protecting static files from viewing by anyone">

<p>Sometimes it is necessary to protect files from being viewed by
anyone, such as configuration files used in your code but not meant to
be served to a browser.</p>

<s2 title="Place files in WEB-INF">
<p>Place files in <var>WEB-INF</var> or a subdirectory of <var>WEB-INF</var>.  Any files in
<var>WEB-INF</var> or it's subdirectories will automatically be protected
from viewing.</p>
</s2>

<s2 title="Security constraint requiring role nobody">
<p>Use a security constraint that requires a <var>role</var> that nobody
will ever have.</p>

<example title="security-constraint to protect static files">
&lt;web-app&gt;
  ...
  &lt;!-- protect all .properties files --&gt;
  &lt;security-constraint&gt;
    &lt;web-resource-collection&gt;
      &lt;url-pattern&gt;*.properties&lt;/url-pattern&gt;
    &lt;/web-resource-collection&gt;
    &lt;auth-constraint role-name='nobody'/&gt;
  &lt;/security-constraint&gt;

  &lt;!-- protect the config/ subdirectory --&gt;
  &lt;security-constraint&gt;
    &lt;web-resource-collection&gt;
      &lt;url-pattern&gt;/config/*&lt;/url-pattern&gt;
    &lt;/web-resource-collection&gt;
    &lt;auth-constraint role-name='nobody'/&gt;
  &lt;/security-constraint&gt;
  ...
&lt;/web-app&gt;
</example>
</s2>

<s2 title="A servlet that returns a 403 error">
<p>Use a simple servlet that returns a 403 error, which means
"Forbidden".  Resin provides the servlet <a href="javadoc|com.caucho.servlets.ErrorStatusServlet|"/> which is useful for
this:</p>

<example title="Using ErrorStatusServlet to protect static files">
&lt;web-app&gt;
  ...
  &lt;servlet&gt;
    &lt;servlet-name&gt;forbidden&lt;/servlet-name&gt;
    &lt;servlet-class&gt;com.caucho.servlets.ErrorStatusServlet&lt;/servlet-class&gt;
    &lt;init&gt;
      &lt;status-code&gt;403&lt;/status-code&gt;
    &lt;/init&gt;
  &lt;/servlet&gt;

  &lt;servlet-mapping url-pattern="*.properties" servlet-name="forbidden"/&gt;
  &lt;servlet-mapping url-pattern="/config/*" servlet-name="forbidden"/&gt;
  ...
&lt;/web-app&gt;
</example>

<p>Or you could implement your own servlet:</p>

<example title="servlet to protect static files - WEB-INF/classes/example/servlets/Forbidden.java">
package example.servlets;

import javax.servlet.*;
import javax.servlet.http.*;

import java.io.IOException;

/**
 * Respond with a 403 error
 */
public class Forbidden extends GenericServlet {
  public void service(ServletRequest request, ServletResponse response)
    throws ServletException, IOException
  {
    HttpServletResponse res = (HttpServletResponse) response;
    res.sendError(403);
  }
}
</example>
</s2>

</s1>

<s1 name="aboutssl" title="What SSL provides">

<p>SSL provides two kinds of protection, <var>encryption</var> and <var>server
authentication</var>.</p>

<s2 title="Encryption">

<glossary title="public key">
A set of bytes used to <var>encrypt</var> data and <var>verify signatures</var>.
The key is public because it can be made available without a loss of security.
The public key can only be used for encryption; it cannot decrypt
anything.  A public key always has a corresponding <var>private key</var>.
</glossary>


<p>SSL provides encryption of the data traffic betweeen a client and a server.
When the traffic is encrypted, an interception of that traffic will not reveal
the contents because they have been encrypted - it will be unusable
nonsense.</p>

<glossary title="private key" type="sidebar-left">
A set of bytes used to <var>decrypt</var> data and <var>generate signatures</var>.
The key is private because it must be kept secret or there will be a loss of
security.  The private key is used for decryption of data that has been
encrypted with the corresponding <var>public key</var>.
</glossary>

<p>
SSL uses public key cryptography.  Public key cryptography is based upon a
pair of keys, the public key and the private key.  The public key is used to
encrypt the data.  Only the corresponding private key can successfully decrypt
the data.  
</p>

<p>
For example, when a browser connects to Resin, Resin provides the browser a
public key.  The browser uses the public key to encrypt the data, and Resin
uses the private key to decrypt the data.  For this reason, it is important that
you never allow anyone access to the private key, if the private key is
obtained by someone then they can use it to decrypt the data traffic. 
</p>

<p>Encryption is arguably the more important of the security meausures that SSL
provides.</p>

</s2> <!-- aboutssl/Encryption -->

<s2 title="Server Authentication">

<glossary title="certificate">
A combination of a <var>private key</var>, identity information (such as company
name), and a <var>signature</var> generated by a <var>signing authority</var>.
<var>private key</var>.
</glossary>

<p>
SSL also provides the ability for a client to verify the identity of a server.
This is used to protect against identity theft, where for example a malicious
person imitates your server or redirects client traffic to a different server
while pretending to be you.
</p>

<glossary title="signing authority" type="sidebar-left">
A company that is trusted to sign certificates.  Browsers include
certificates of signing authorities that they trust.
</glossary>

<p>
Server authentication uses the signature aspect of public key cryptography.
The private key is used to sign messages, and the public key is used to verify
the signature.  With SSL, the validity of signatures depends upon signing
authorities.  Signing authorites (also called certificate authorities) are
companies who have generated public keys that are included with browser
software.  The browser knows it can trust the signing authority, and the
signing authority signs your SSL certificate, putting its stamp of approval on
the information in your certificate.
</p>

<glossary title="certificate authority">
Another name for <var>signing authority</var>.  A company that is trusted to
sign certificates.  Browsers include certificates of signing authorities that
they trust.
</glossary>

<p>For example, after you generate your public and private key, you then
generate a signing request and send it to a signing authority.  This signing
request contains information about your identity, this identity information is
confirmed by the signing authority and ultimately displayed to the user of the
browser.  The signing authority validates the identity information you have
provided and uses their private key to sign, and then returns a
<var>certificate</var> to you.  This certificate contains the identity information
and your public key, verified by the signing authority, and is provided to the
browser. Since the browser has the public key of the signing authority, it can
recognize the signature and know that the identity information has been
provided by someone that can be trusted.</p>


</s2> <!-- aboutssl/Server Authentication -->

</s1> <!-- aboutssl -->

<s1 name="openssl" title="OpenSSL">

<p>OpenSSL is the same SSL implementation that Apache's mod_ssl
uses. Since OpenSSL uses the same certificate as Apache, you can get
signed certificates using the same method as for Apache's mod_ssl or
following the OpenSSL instructions.</p>

<s2 title="Linking to the OpenSSL Libraries on Unix">

<p>On Unix systems, Resin's libexec/libresinssl.so JNI library
supports SSL using the
<a href="http://www.openssl.org">OpenSSL</a> libraries.
Although the ./configure script will detect many configurations,
you can specify the openssl location directly:</p>

<example>
resin&gt; ./configure --with-openssl=/usr/local/ssl
</example>
</s2>

<s2 title="Obtaining the OpenSSL Libraries on Windows">

<p>On Windows systems, the resinssl.dll includes JNI code to use
OpenSSL libraries (it was in resin.dll in versions before 3.0).  All
you need to do is to obtain an OpenSSL binary distribution and install
it. </p>
  
<p>Resin on Windows 32 is compiled against the Win32 binary, you can obtain an
installation package 
<a href="http://www.slproweb.com">http://www.slproweb.com (Shining Light Productions)</a>.
</p>
  
<p>Resin on Windows 64 is compiled against a Win64 binary, you can obtain an
installation package 
<a href="http://www.deanlee.cn?p=60&amp;cp=1">Dean Lee: /dev/blog</a>.
</p>

<p>Once you have run the installation package, you can copy the necessary
dll libraries into <code>$RESIN_HOME</code>:</p>

<example title="Copying the Windows SSL libraries into $RESIN_HOME">
C:\&gt; cd %RESIN_HOME%
C:\resin-3.0&gt; copy "C:\Program Files\GnuWin32\bin\libssl32.dll" .\libssl32.dll
C:\resin-3.0&gt; copy "C:\Program Files\GnuWin32\bin\libeay32.dll" .\libeay32.dll
</example>


</s2>

<s2 title="Preparing to use OpenSSL for making keys">
<p>You can make a <code>keys/</code> subdirectory of $RESIN_HOME to do
your work from and as a place to store your generated keys.</p>

<example title="$RESIN_HOME/keys">
unix&gt; cd $RESIN_HOME
unix&gt; mkdir keys
unix&gt; cd keys

win&gt; cd %RESIN_HOME%
win&gt; mkdir keys
win&gt; cd keys
</example>

<p>Using OpenSSL requires a configuration file.  Unix users might find
the default configuration file in <code>/usr/ssl/openssl.cnf</code>
or <code>/usr/share/ssl/openssl.cnf</code>.  Windows users may not
have received one with their package.</p>

<p>Either way, it can be valuable to make your own
<code>openssl.cnf</code> that is used just for generating the keys to
use with Resin.  You can use the following as a template for a file
<code>$RESIN_HOME/keys/openssl.cnf</code>.  You may want to fill in
the <code>_default</code> values so you don't have to type them in
every time.</p>

<example title="$RESIN_HOME/keys/openssl.cnf">
[ req ]
 default_bits            = 1024
 distinguished_name      = req_distinguished_name

[ req_distinguished_name ]
 C                      = 2 letter Country Code, for example US
 C_default              =
 ST                     = State or Province
 ST_default             =
 L                      = City
 L_default              =
 O                      = Organization Name
 O_default              =
 OU                     = Organizational Unit Name, for example 'Marketing'
 OU_default             =
 CN                     = your domain name, for example www.hogwarts.com
 CN_default             =
 emailAddress           = an email address
 emailAddress_default   =

</example>
</s2>

<s2 title="Creating a private key">

<p>Create a private key for the server.  You will be asked for a
password - don't forget it!  You will need this password anytime you
want to do anything with this private key.  But don't pick something
you need to keep secret, you will need to put this password in the
Resin configuration file.</p>

<example title="creating the private key gryffindor.key">
unix&gt; openssl genrsa -des3 -out gryffindor.key 1024
win&gt;  "C:\Program Files\GnuWin32\bin\openssl.exe" \
         genrsa -des3 -out gryffindor.key 1024
</example>

</s2>

<s2 title="Creating a certificate">
<p>OpenSSL works by having a signed public key that corresponds to your
private key.  This signed public key is called a <var>certificate</var>.  A
certificate is what is sent to the browser.</p>

<p>You can create a self-signed certificate, or get a certificate that
is signed by a certificate signer (CA).</p>

<s3 title="Creating a self-signed certificate">

<p>You can create a certificate that is self-signed, which is good for
testing or for saving you money.  Since it is self-signed, browsers will not
recognize the signature and will pop up a warning to browser users.  Other than
this warning, self-signed certificates work well. The browser cannot confirm
that the server is who it says it is, but the data between the browser and the
client is still encrypted.</p>

<example title="creating a self-signed certificate gryffindor.crt">
unix&gt; openssl req -config ./openssl.cnf -new -key gryffindor.key \
        -x509 -out gryffindor.crt
win&gt; "C:\Program Files\GnuWin32\bin\openssl.exe" req -config ./openssl.cnf \
         -new -key gryffindor.key -x509 -out gryffindor.crt
</example>

<p>You will be asked to provide some information about the identity of
your server, such as the name of your Organization etc.  Common Name
(CN) is your domain name, like: "www.gryffindor.com".</p>

</s3>

<s3 title="Creating a certificate request">

<p>To get a certificate that is signed by a CA, first you generate a
<var>certificate signing request</var> (CSR).</p>

<example title="creating a certificate request gryffindor.csr">
unix&gt; openssl req -new -config ./openssl.cnf -key gryffindor.key \
      -out gryffindor.csr
win&gt; "C:\Program Files\GnuWin32\bin\openssl.exe" req -new \
      -config ./openssl.cnf  -key gryffindor.key -out gryffindor.csr
</example>

<p>You will be asked to provide some information about the identity of
your server, such as the name of your Organization etc.  Common Name
(CN) is your domain name, like: "www.gryffindor.com".</p>

<p>Send the CSR to a certificate signer (CA).  You'll use the CA's
instructions for Apache because the certificates are identical.  Some
commercial signers include:</p>

<ul>
<li><a href="http://digitalid.verisign.com/server/apacheNotice.htm">Verisign</a>
</li><li><a href="http://www.thawte.com/certs/server/request.html">Thawte Consulting</a>
</li></ul>
<p>You'll receive a <em>gryffindor.crt</em> file.</p>

<p>Most browsers are configured to recognize the signature of signing
authorities.  Since they recognize the signature, they will not pop up a
warning message the way they will with self-signed certificates.  The browser
can confirm that the server is who it says it is, and the data between the
browser and the client is encrypted.</p>

</s3>
</s2>

<s2 title="resin.xml - Configuring Resin to use your private key and certificate">

<p>The OpenSSL configuration has two tags <a config-tag="certificate-file"/> and
<a config-tag="certificate-key-file"/>.  These correspond exactly to mod_ssl's
SSLCertificateFile and SSLCertificateKeyFile.  So you can use the same
certificates (and documentation) from mod_ssl for Resin.</p>

<p>The full set of parameters is in the port configuration.</p> 

<example>
...
&lt;http port="443"&gt;
  &lt;openssl&gt;
    &lt;certificate-file&gt;keys/gryffindor.crt&lt;/certificate-file&gt;
    &lt;certificate-key-file&gt;keys/gryffindor.key&lt;/certificate-key-file&gt;
    &lt;password&gt;my-password&lt;/password&gt;
  &lt;/openssl&gt;
&lt;/http&gt;
</example>

</s2>

<s2 title="Testing">

<s3 title="Testing with the browser">
<!--
<p><jsp:scriptlet>if (request.isSecure()) {</jsp:scriptlet>
</p><p><code>request.isSecure()</code> is reporting true, so it looks like
you have SSL working and are viewing this page over an SSL encrypted
connection.</p>
<jsp:scriptlet>} else {</jsp:scriptlet>
<p>Once you have SSL configured, you can come back to this page using
an <code>https://</code> style URL instead of an <code>http://</code>
url and you will get a message telling that SSL is working.
<jsp:scriptlet>}</jsp:scriptlet>

</p>
-->

<p>A quick test is the following JSP.</p>

<example>
Secure? &lt;%= request.isSecure() %&gt;
</example>
</s3>

<s3 title="Using openssl to test the server">
<p>
The openssl tool can be used as a client, showing some interesting information
about the conversation between the client and the server:
</p>

<example>
unix$ openssl s_client -connect www.some.host:443 -prexit
</example>
</s3>
</s2> <!-- testing -->

<s2 title="Certificate Chains">

<p>A <var>certificate chain</var> is used when the signing authority is not an
authority trusted by the browser.  In this case, the signing authority uses a
certificate which is in turn signed by a trusted authority, giving a chain of
<code>[your certificate] &lt;--- signed by ---- [untrusted signer] &lt;---- signed by ---- [trusted signer]</code>.

</p><p>
The Resin config parameter <a config-tag="certificate-chain-file"/> is used to
specify a certificate chain.  It is used to reference a file that is a
concatenation of:
</p>

<ol>
<li>your certificate file
</li><li>the intermediate (untrusted) certificate
</li><li>the root (trusted) certificate.
</li></ol>

<p>
The certificates must be in that order, and must be in PEM format.
</p>

<s3 title="Example certificate chain for Instant SSL">

<p>
<a href="http://instantssl.com">Comodo (http://instantssl.com)</a> is a signing
authority that is untrusted by most browsers.  Comodo has their certificate
signed by GTECyberTrust.
</p>

<p>
Comodo gives you three certificates:
</p>

<ol>
<li><code>your_domain.crt</code>   (signed by Comodo)
</li><li><code>ComodoSecurityServicesCA.crt</code>   (signed by GTE CyberTrust)
</li><li><code>GTECyberTrustRoot.crt</code>  (universally known root)
</li></ol>

<p>
In addition to this, you have your key, <code>your_domain.key</code>.
The contents of the file referred to by <a config-tag="certificate-chain-file"/> is a concatenation of the three
certificates, in the correct order.
</p>

<example title="Creating a certificate chain file">
$ cat your_domain.crt ComodoSecurityServicesCA.crt GTECyberTrustRoot.crt &gt; chain.txt
</example>

<example title="resin.xml using a certificate chain file">
&lt;http port="443"&gt;
  &lt;openssl&gt;
    &lt;certificate-key-file&gt;keys/your_domain.key&lt;/certificate-key-file&gt;
    &lt;certificate-file&gt;keys/your_domain.crt&lt;/certificate-file&gt;        
    &lt;certificate-chain-file&gt;keys/chain.txt&lt;/certificate-chain-file&gt;
    &lt;password&gt;test123&lt;/password&gt;
  &lt;/openssl&gt;
&lt;/http&gt;
</example>

</s3> <!-- example certificate chain -->

</s2> <!-- certificate chain -->

</s1> <!-- OpenSSL -->


<s1 name="jsse" title="JSSE">

<p>We recommend avoiding JSSE if possible. It is slower than using
Resin's OpenSSL support and does not appear to be as stable as Apache
or IIS (or Netscape/Zeus) for SSL support. In addition, JSSE is far
more complicated to configure. While we've never received any problems
with Resin using OpenSSL, or SSL from Apache or IIS, JSSE issues are
fairly frequent.</p>

<s2 title="Install JSSE from Sun">

<p>This section gives a quick guide to installing a test SSL
configuration using Sun's JSSE.  It avoids as many complications as
possible and uses Sun's keytool to create a server certificate.</p>

<p>Resin's SSL support is provided by Sun's
<a href="http://java.sun.com/products/jsse">JSSE</a>.  Because of
export restrictions, patents, etc, you'll need to download the JSSE
distribution from Sun or get a commercial JSSE implementation.</p>

<p>More complete JSSE installation instructions for JSSE are at
<a href="http://java.sun.com/products/jsse/install.html">http://java.sun.com/products/jsse/install.html</a>.
</p>
<ol>
<li>First download Sun's <a href="http://java.sun.com/products/jsse">JSSE</a>.
</li><li>Uncompress and extract the downloaded file.
</li><li>Install the JSSE jar files: jsse.jar, jnet.jar, and jcert.jar.  You can
either put them into the CLASSPATH or you can put them into $JAVA_HOME/jre/lib/ext.  Since you will use "keytool" with the new jars, you need to make them
visible to keytool.  Just adding them to resin/lib is not enough.
</li><li>Register the JSSE provider (com.sun.net.ssl.internal.ssl.Provider).
Modify $JAVA_HOME/jre/lib/security/java.security so it contains something like:
<example>
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
</example>
Adding the JSSE provider allows "keytool" to create a key using the RSA
algorithm.
</li></ol>

</s2>

<s2 title="Create a test server certificate">

<p>The server certificate is the core of SSL.  It will identify your server and
contain the secret key to make encryption work.</p>

<ul>
<li>Sun's keytool
</li><li>A self-signed certificate using open_ssl
</li><li>A test certificate from Thawte
</li><li>A production certificate from one of the certificate authorities (Verisign, Thawte, etc)
</li></ul>

<p>In this case, we're using Sun's <var>keytool</var> to generate the
server certificate.  Here's how:</p>

<example>
resin1.2.b2&gt; <var>mkdir keys</var>
resin1.2.b2&gt; <var>keytool -genkey -keyalg RSA -keystore keys/server.keystore</var>
Enter keystore password:  <var>changeit</var>
What is your first and last name?
  [Unknown]:  <var>www.caucho.com</var>
What is the name of your organizational unit?
  [Unknown]:  <var>Resin Engineering</var>
What is the name of your organization?
  [Unknown]:  <var>Caucho Technology, Inc.</var>
What is the name of your City or Locality?
  [Unknown]:  <var>San Francisco</var>
What is the name of your State or Province?
  [Unknown]:  <var>California</var>
What is the two-letter country code for this unit?
  [Unknown]:  <var>US</var>
Is &lt;CN=www.caucho.com, OU=Resin Engineering,
  O="Caucho Technology, Inc.", L=San Francisco, ST=California, C=US&gt; correct?
  [no]:  <var>yes</var>

Enter key password for &lt;mykey&gt;
        (RETURN if same as keystore password):  <var>changeit</var>
</example>

<p>Currently, the key password and the keystore password must be the same.</p>

</s2>

<s2 title="resin.xml">

<p>The Resin SSL configuration extends the http configuration with a few new
elements.</p>

<example>
&lt;resin xmlns="http://caucho.com/ns/resin"&gt;
  &lt;server&gt;

    &lt;http port="8443"&gt;
     &lt;jsse-ssl&gt;
       &lt;key-store-type&gt;jks&lt;/key-store-type&gt;
       &lt;key-store-file&gt;keys/server.keystore&lt;/key-store-file&gt;
       &lt;password&gt;changeit&lt;/password&gt;
     &lt;/jsse-ssl&gt;
    &lt;/http&gt;

    ...

  &lt;/http-server&gt;
&lt;/caucho.com&gt;
</example>

</s2>

<s2 title="Testing JSSE">

<p>With the above configuration, you can test SSL with https://localhost:8443.
A quick test is the following JSP.</p>

<example>
Secure? &lt;%= request.isSecure() %&gt;
</example>

</s2>

        
<s2 title="User Experiences with JSSE">

<s3 title="How do I configure Resin with SSL using JSSE?">

<p>Nicholas Lehuen writes:</p>

<p>Here is a short step-by-step installation guide for SSL on Resin.</p>
 
<p>The purpose : to install SSL support on Resin</p>

<s4 title="Requirements">
<ul>
<li>The latest Resin 1.2 snapshot (I used the 08/04/2000 snapshot with success)
    http://www.caucho.com/download/index.xtp
</li><li>JSSE 1.0.1
    http://java.sun.com/products/jsse/
</li><li>Optional : a certificate authority (CA) such as Verisign, Thawte, or your own. Thawte is providing a free test certificate authority
service which enables you to check the certification process before buying your own certificate. Of course, you can also skip the CA by
providing self-signed public key certificate. This will be explained later.

<a href="https://www.thawte.com/cgi/server/test.exe">https://www.thawte.com/cgi/server/test.exe</a>
</li></ul>
</s4>

 
<s4 title="JSSE setup">

<ol>
<li>Follow the installation instructions
<a href="http://java.sun.com/products/jsse/install.html">http://java.sun.com/products/jsse/install.html</a>
</li><li>Even if Resin has its own provider registration system (we'll see it on next step), I suggest that you statically register the SunJSSE
by editing the &lt;java-home&gt;/lib/security/java.security as explained in the installation guide. This will ease the use of keytool.
</li></ol>
</s4>
 
<s4 title="Keystore initialization">
<ol>
<li>Create a directory named 'keys' somewhere in your Resin installation. I suggest you place it in the Resin home directory.
</li><li>Copy the file &lt;java-home&gt;/lib/security/cacerts into the 'keys' directory
</li><li>Rename the cacerts file as you want. I'll suppose you name it 'private.keystore'.
</li></ol>

</s4>
<s4 title="Keystore protection">
<p>Your private.keystore file is for the moment a copy of the cacerts keystore, which contains the CA public key certificates (very
important for client HTTPS connections). We will insert your own private key in this file, thus it'll have to be password-protected, so
that anyone stealing it will have difficulties in forging certificates on your behalf.</p>

<ol>
<li>Go into the 'keys' directory
</li><li>type the following command :
keytool -storepasswd -storepass changeit -new YourPasswordHere \
        -keystore private.keystore
</li></ol>
 
<p>(the default password for the cacerts keystore is 'changeit')</p>
 
</s4>

<s4 title="Private key generation">

<p>We'll now generate your key pair, which is composed of a private (the one which MUST remain secret !) and a public key. The point here is
to use the RSA key pair generator, and NOT the default one, which is DSA. This is were the JSSE security provider is used.</p>
 
<p>type the following command :</p>
<example>
M:\keys&gt;keytool -genkey -keyalg RSA -alias myserverkeypair \
                -storepass YourPasswordHere -keystore private.keystore
What is your first and last name?
  [Unknown]:  www.myserver.com
What is the name of your organizational unit?
  [Unknown]:  Foo Dept
What is the name of your organization?
  [Unknown]:  Bar
What is the name of your City or Locality?
  [Unknown]:  Paris
What is the name of your State or Province?
  [Unknown]:  France
What is the two-letter country code for this unit?
  [Unknown]:  FR
Is &lt;CN=www.myserver.com, OU=Foo Dept, O=Bar, L=Paris,
                ST=France, C=FR&gt; correct?
  [no]:  yes
 
Enter key password for &lt;myserverkeypair&gt;
        (RETURN if same as keystore password):
</example>
 
<p>You MUST mention your HTTP server name as the CN of the certificate (thus the reply to 'first and last name'). Browsers would emit
warnings to your users if you didn't. Any other informations are at your choice, however the process of key pair generation and
attributes definitions is very strict for "real-life" cryptography, i.e. Verisign will double-check your identity, address and so on.</p>
 
<p>Another important point : DON'T AFFECT A PASSWORD to your key pair. It must remain the same as the keystore, at least until Resin
provides a means of configuring the key pair password.</p>
</s4>

<s4 title="Public Key Certificate (optional)">

<p>Request a public key certificate and insert the public key certificate into your keystore.</p>

<p>For users to trust your server, you'll have to have your public key
certificate (PKC) signed by a Certificate Authority (CA) (Verisign,
Thawte, Certplus...). This is done by sending a certificate signature
request (CSR) to the CA, coping with all the legal stuff and
getting a signed PKC in return. This step is mandatory for production server, unless you have some means to convince your users that your
PKC is valid without a CA signature, which is possible in intranet environment for example. However, for testing purpose, you can start
by using your self-signed PKC without any CA signature. An intermediary solution is to use a test CA so that you can check that your CSR
is correctly emitted, that the Certificate Chain is correctly checked, and so on. Thawte provides a test CA at the address mentioned
above.</p>

<ol>
<li>Generate a CSR by typing the following command :

<example>

M:\keys&gt;keytool -certreq -alias myserverkeypair -storepass YourPasswordHere \
                -keystore private.keystore
-----BEGIN NEW CERTIFICATE REQUEST-----
MIIBqjCCARMCAQAwajELMAkGA1UEBhMCRlIxDzANBgNVBAgTBkZyYW5jZTEOMAwGA1UEBxMFUGFy
... cut ...
KDYZTklbg1NOiXTdXIhPHb3+YOgZ+HoeDTxOx/rRhA==
-----END NEW CERTIFICATE REQUEST-----
</example>
 
</li><li>Copy/Paste the CSR into the text box at the following address. Leave all options with their default value.
    https://www.thawte.com/cgi/server/test.exe
 
</li><li>You'll get a certificate looking like :
<example>
-----BEGIN CERTIFICATE-----
MIICjzCCAfigAwIBAgIDBp8SMA0GCSqGSIb3DQEBBAUAMIGHMQswCQYDVQQGEwJa
... cut ...
/93Q58iI4fgQ/kc+l8ogpVwh/IJw1Ujmszd19Jf+pxyySMM=
-----END CERTIFICATE-----
</example>
</li><li>Copy/Paste this certificate into a file named 'myserver.cer' . If you have Microsoft Internet Explorer 5.0 (maybe 4.0) installed, you
can open this .cer file and see the certificate as your user will when they ask the security properties of pages served securely by your
server. A warning should be emitted, stating that you can't trust the certificate as it does not point to a trusted root CA. You can keep
going with this warning or download and trust the test root CA (available on https://www.thawte.com/servertest.crt ). Be ware though that
the final user should not and surely won't accept to trust this test root CA.
 
</li><li>Anyway, to be able to import your signed certificate, you'll have to import the test root CA certificate. Download it and import it
using the following command :
<example>
M:\keys&gt;keytool -import -alias servertest -storepass YourPasswordHere \
                -keystore private.keystore -file servertest.crt
Owner: CN=Thawte Test CA Root, OU=TEST, O=Thawte, ST=FOR TESTING, C=ZA
Issuer: CN=Thawte Test CA Root, OU=TEST, O=Thawte, ST=FOR TESTING, C=ZA
Serial number: 0
Valid from: Thu Aug 01 02:00:00 CEST 1996 until: Thu Dec 31 22:59:59 CET 2020
Certificate fingerprints:
         MD5:  5E:E0:0E:1D:17:B7:CA:A5:7D:36:D6:02:DF:4D:26:A4
         SHA1: 39:C6:9D:27:AF:DC:EB:47:D6:33:36:6A:B2:05:F1:47:A9:B4:DA:EA
Trust this certificate? [no]:  yes
Certificate was added to keystore
</example>
 
</li><li>Import the certificate and attach it to your server key pair by typing the command :
<example>
M:\keys&gt;keytool -import -alias myserverkeypair -storepass YourPasswordHere \
                -keystore private.keystore -file myserver.cer
Certificate reply was installed in keystore
</example>
</li></ol>
</s4>

<s4 title="Key pair verification">

<p>Issue the following command :</p>
<example>
M:\keys&gt;keytool -list -v -alias myserverkeypair -storepass YourPasswordHere \
                -keystore private.keystore
Alias name: myserverkeypair
Creation date: Fri Aug 11 23:07:53 CEST 2000
Entry type: keyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=www.myserver.com, OU=Foo Dept, O=Bar, L=Paris, ST=France, C=FR
Issuer: CN=Thawte Test CA Root, OU=TEST, O=Thawte, ST=FOR TESTING, C=ZA
Serial number: 69f12
Valid from: Fri Aug 11 23:00:07 CEST 2000 until: Mon Sep 11 23:00:07 CEST 2000
Certificate fingerprints:
         MD5:  41:84:55:8C:A1:85:28:DA:B0:5A:47:D6:5B:D2:ED:41
         SHA1: 61:DE:DB:E6:7C:3C:AD:90:63:9B:20:E0:FF:3B:02:3A:60:EB:B4:82
Certificate[2]:
Owner: CN=Thawte Test CA Root, OU=TEST, O=Thawte, ST=FOR TESTING, C=ZA
Issuer: CN=Thawte Test CA Root, OU=TEST, O=Thawte, ST=FOR TESTING, C=ZA
Serial number: 0
Valid from: Thu Aug 01 02:00:00 CEST 1996 until: Thu Dec 31 22:59:59 CET 2020
Certificate fingerprints:
         MD5:  5E:E0:0E:1D:17:B7:CA:A5:7D:36:D6:02:DF:4D:26:A4
         SHA1: 39:C6:9D:27:AF:DC:EB:47:D6:33:36:6A:B2:05:F1:47:A9:B4:DA:EA
</example>
 
<p>As you can see the alias myserverkeypair points to a keyEntry type entry, its certificate chain has 2 certificate, the first being your
own certificate, signed by the Thawte Test CA Root, and the other being the Thawte Test CA Root own.</p>
 
</s4>

<s4 title="Resin configuration (resin.xml)">

<p>add the support for the SunJSSE security provider :</p>

<example>
&lt;resin xmlns="http://caucho.com/ns/resin"&gt;
    &lt;security-provider id='com.sun.net.ssl.internal.ssl.Provider'/&gt;
 
&lt;!-- declare a new HTTP server on port 443 (standard port for HTTPS),
      - with SSL enabled --&gt;
 
&lt;server&gt;
  &lt;!-- the http port --&gt;
  &lt;http port="80"/&gt;

  &lt;!-- the srun port, read by both JVM and plugin --&gt;
  &lt;cluster&gt;
    &lt;srun host='localhost' port='6802'/&gt;
  &lt;/cluster&gt;
 
  &lt;http port=443&gt;
    &lt;jsse-ssl&gt;
      &lt;key-store-type&gt;jks&lt;/key-store-type&gt;
      &lt;key-store-file&gt;file://m:/keys/private.keystore&lt;/key-store-file&gt;
      &lt;password&gt;YourPasswordHere&lt;/password&gt;
    &lt;/jsse-ssl&gt;
  &lt;/http&gt;
</example>
</s4>

<s4 title="Test !">
<p>Try connecting to your server with https instead of http !</p>
 
<p>I've been running successfully SSL on Resin with JDK 1.3 on Windows NT 4 SP6 and JDK 1.2.2 on Solaris 7.</p>
 
<p>And the fun begins when mixing HTTPS and WAP... !</p>

</s4>

</s3> <!-- how do I ...-->

</s2> <!-- user experiences -->

</s1> <!-- JSSE -->

<s1 title="Security Manager">

<p>In ISP environments, it's important that each user have 
restricted permissions to use the server.  Normally, the
web server will be run as a non-root user so the users can't
read system files, but that user will still have read access.  The use of RMI
also requires a security manager.</p>

<p>Don't use a security manager if you're not in an ISP environment or
using RMI.  There's no need for it and the security manager does slow the
server down somewhat.</p>

<p>Adding a Java security manager puts each web-app into a
"sandbox" where Java limits the things that can be done from code
within th web-app.</p>

<p>The security manager is enabled by adding a <a config-tag="security-manager"/> tag in the resin.xml.</p>

<example title="enabling security-manager in resin.xml">
&lt;resin xmlns="http://caucho.com/ns/resin"
       xmlns:resin="http://caucho.com/ns/resin/core"&gt;

  &lt;security-manager/&gt;

  ...
</example>

<s2 title="java.policy">
<p>The security manager determines a <var>policy</var> that applies to the current
virtual machine.  The security manager is controlled by policy file's.</p>

<p>
The simplest way to change the policy  is to change one of the default 
policy file's.  There are two default policy files that are used by the JDK:
</p>

<def>
${java.home}/lib/security/java.policy
${user.home}/.java.policy
</def>

<p>
An additional policy file can be set using the <code>java.security.policy</code>
system property at the command line: 
</p>

<example>
unix$ bin/resin.sh -Djava.security.policy=<i>file:/path/to/java.policy</i>
win$ bin/resin.exe -Djava.security.policy=<i>file:/path/to/java.policy</i>
</example>

<p>
The resulting policy for the virtual machine is the union of all granted
permissions in all policy files. 
</p>

</s2>

<s2 title="java.policy syntax">

<p>A useful resource is
Sun's <a href="http://java.sun.com/j2se/1.4/docs/guide/security/index.html">documentation
about security</a>, in particular the <a href="http://java.sun.com/j2se/1.4/docs/guide/security/permissions.html">policy permissions</a> and
<a href="http://java.sun.com/j2se/1.4/docs/guide/security/PolicyFiles.html">policy file syntax</a> files are
useful.</p>

<p>Each web-app automatically has permissions to read, write and
delete any file under the web-app's directory, including WEB-INF.  It
also has read permission for the classpath, including &lt;classpath&gt;
from the &lt;host&gt; and &lt;server&gt; contexts.</p>

<example title="sample java.policy">
#
# Permissions allowed for everyone.
#
grant {
  permission java.util.PropertyPermission "*", "read";
  permission java.lang.RuntimePermission "accessClassInPackage.*";
  permission java.net.SocketPermission "mysql.myhost.com:3306" "connect";
  permission java.io.FilePermission "/opt/resin/xsl/*", "read";
};

#
# Give the system and Resin classes all permissions
#
grant codeBase "file:${'${'}resin.home}/lib/-" {
	permission java.security.AllPermission;
};

grant codeBase "file:${'${'}java.home}/lib/-" {
	permission java.security.AllPermission;
};

grant codeBase "file:${'${'}java.home}/jre/lib/-" {
	permission java.security.AllPermission;
};

#
# Give a specific web-app additional permissions.
#
grant codeBase "file:/opt/web/webapps/ejb/WEB-INF/-" {
	permission java.io.FilePermission "/opt/web/doc/*", "read";
};
</example>
</s2>
</s1>

</body>
</document>
