directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Directory Server v1.5 > 3.3. How to enable SSL
Date Wed, 28 Oct 2009 20:17:00 GMT
<html>
<head>
    <base href="http://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1519/1/1/_/styles/combined.css?spaceKey=DIRxSRVx11&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background-color: white" bgcolor="white">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
     <h2><a href="http://cwiki.apache.org/confluence/display/DIRxSRVx11/3.3.+How+to+enable+SSL">3.3.
How to enable SSL</a></h2>
     <h4>Page <b>edited</b> by             <a href="http://cwiki.apache.org/confluence/display/~seelmann">Stefan
Seelmann</a>
    </h4>
     
          <br/>
     <div class="notificationGreySide">
         <div class='panelMacro'><table class='warningMacro'><colgroup><col
width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/forbidden.gif"
width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>COMING
SOON !!!</b><br /><p>This part represent the configuration in the upcomming
1.5.5 version.</p></td></tr></table></div>
<style type='text/css'>/*<![CDATA[*/
table.ScrollbarTable  {border: none;padding: 3px;width: 100%;padding: 3px;margin: 0px;background-color:
#f0f0f0}
table.ScrollbarTable td.ScrollbarPrevIcon {text-align: center;width: 16px;border: none;}
table.ScrollbarTable td.ScrollbarPrevName {text-align: left;border: none;}
table.ScrollbarTable td.ScrollbarParent {text-align: center;border: none;}
table.ScrollbarTable td.ScrollbarNextName {text-align: right;border: none;}
table.ScrollbarTable td.ScrollbarNextIcon {text-align: center;width: 16px;border: none;}

/*]]>*/</style><div class="Scrollbar"><table class='ScrollbarTable'><tr><td
class='ScrollbarPrevIcon'><a href="/confluence/display/DIRxSRVx11/3.2.+Basic+authorization"><img
border='0' align='middle' src='/confluence/images/icons/back_16.gif' width='16' height='16'></a></td><td
width='33%' class='ScrollbarPrevName'><a href="/confluence/display/DIRxSRVx11/3.2.+Basic+authorization">3.2.
Basic authorization</a>&nbsp;</td><td width='33%' class='ScrollbarParent'><sup><a
href="/confluence/display/DIRxSRVx11/3.+Basic+Security"><img border='0' align='middle'
src='/confluence/images/icons/up_16.gif' width='8' height='8'></a></sup><a
href="/confluence/display/DIRxSRVx11/3.+Basic+Security">3. Basic Security</a></td><td
width='33%' class='ScrollbarNextName'>&nbsp;</td></tr></table></div>

<h1><a name="3.3.HowtoenableSSL-HowtoenableSSL"></a>How to enable SSL</h1>

<p>This section describes the transport layer security options for LDAP, and especially
how to enable LDAPS on ApacheDS.</p>

<div>
<ul>
    <li><a href='#3.3.HowtoenableSSL-TransportlayersecurityandLDAP'>Transport
layer security and LDAP</a></li>
    <li><a href='#3.3.HowtoenableSSL-Serverconfiguration'>Server configuration</a></li>
    <li><a href='#3.3.HowtoenableSSL-Verification%2CClients'>Verification, Clients</a></li>
    <li><a href='#3.3.HowtoenableSSL-Resources'>Resources</a></li>
</ul></div>

<h2><a name="3.3.HowtoenableSSL-TransportlayersecurityandLDAP"></a>Transport
layer security and LDAP</h2>

<p>Several requirements related to security can be easily accomplished with the help
of <b>SSL</b> technology (Secure Socket Layer) or its standardized successor <b>TLS</b>
(Transport Layer Security, RFC 2246). Among these are the protection of data against eavesdropping
and modification, when on transit between client and server (data integrity), and the authentication
of a server toward a client with the help of a certificate.</p>

<p>There are two approaches to utilize these technologies in the LDAP world. </p>

<ol>
	<li>ldaps (LDAP over SSL/TLS, port 636)</li>
	<li>StartTLS (extended operation)</li>
</ol>


<p>The first option is comparable to HTTPS and inserts an SSL/TLS layer between the
TCP/IP protocol and LDAP. Establishing a connection like this is normally provided via a different
server port (port 636 is common, it is a well-known port, like port 389 is for LDAP). In URIs
the schema "ldaps" is specified  (for instance <em>ldaps://zanzibar:636/</em>)
instead of "ldap". It is possible to write programs which switch between ldap and ldaps without
changes in the source, if the connection data is configured external.</p>

<p>In the second option a client establishes at first a "normal" LDAP connection. With
a special request (extended operation StartTLS) it tries to switch to secure communication
afterwards. It is not necessary to change the port for this, the communication continues on
the established connection. The client may go back to the original connection state ("TLS
Closure Alert"), in doing so protecting only selected parts of the communication.</p>

<p>Both ways to utilize SSL/TLS within LDAP require the configuration of the server
with an appropriate certificate.</p>

<h2><a name="3.3.HowtoenableSSL-Serverconfiguration"></a>Server configuration</h2>

<p>ApacheDS 1.5.5 supports both options and requires a JDK 1.5 or above. The feature
is enabled by default, but you may need to configure it. There are some steps to follow in
order to obtain a SSL enabled server.</p>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/warning.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td><p>In order to keep it simple
for beginners, you don't need any certificate to get LDAPS working. The latest version generates
its own self signed certificate. From the user point of view, it's just a matter of enabling
the ldaps service to get it working.</p>

<p>However, if one wants to use a signed certificate, another configuration is needed,
where you tell the server about the keystore to use, and the certificate password to use.</p></td></tr></table></div>

<h3><a name="3.3.HowtoenableSSL-IncaseyouwantADStogeneratethecertificate"></a>In
case you want ADS to generate the certificate</h3>

<p>There is nothing to do but enabling SSL and specifying the port to use in the <em>server.xml</em>
configuration file :</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
  ...
  &lt;ldapServer id=<span class="code-quote">"ldapServer"</span>
            ...&gt;
    <span class="code-tag">&lt;transports&gt;</span>
      ...
      <span class="code-tag">&lt;tcpTransport address=<span class="code-quote">"localhost"</span>
port=<span class="code-quote">"10636"</span> enableSSL=<span class="code-quote">"true"</span>/&gt;</span>
    <span class="code-tag">&lt;/transports&gt;</span>
    ...
  <span class="code-tag">&lt;/ldapServer&gt;</span>
  ...
</pre>
</div></div>

<p>That's it, the server is LDAPS capable !</p>

<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/warning.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td>The default <em>server.xml</em>
configuration file contains an typo, by default the port is set to 10686.</td></tr></table></div>

<h3><a name="3.3.HowtoenableSSL-Incaseyouwanttouseanexternalkeystore"></a>In
case you want to use an external keystore</h3>

<p>A certificate is a signed public key (signed normally by a third party, a certificate
authority, CA).</p>

<p>There are different options</p>
<ul class="alternate" type="square">
	<li>either you buy a certificate from a Certificate Authority (like Verisign, etc.),
or you obtain one from your enterprise CA, if available</li>
	<li>or you ask for a free certificate from <a href="http://www.cacert.org/" title="www.cacert.org"
rel="nofollow">CACERT organisation</a></li>
	<li>or you create your own certificate, self-signed or signed by your private CA, which
will not be trusted.</li>
</ul>


<p>We will do it the last way (self-signed), primarily because it's easy and fast (you
won't have to pay nor to wait to obtain your certificate)</p>

<h4><a name="3.3.HowtoenableSSL-Keycreation"></a>Key creation</h4>

<p>First it is necessary to create a key pair (public/private key) for your server,
<em>zanzibar</em> in our case.  One option is to use the JDK tool <em>keytool</em>
for this task. In the following example, we use these options</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Option </th>
<th class='confluenceTh'> value </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> -genkey </td>
<td class='confluenceTd'>&nbsp;</td>
<td class='confluenceTd'> command to generate a key pair </td>
</tr>
<tr>
<td class='confluenceTd'> -keyalg </td>
<td class='confluenceTd'> "RSA" </td>
<td class='confluenceTd'> algorithm to be used to generate the key pair,  in our case,
default is "DSA" </td>
</tr>
<tr>
<td class='confluenceTd'> -dname </td>
<td class='confluenceTd'> "cn=zanzibar, ou=ApacheDS, o=ASF, c=US" </td>
<td class='confluenceTd'> the X.500 Distinguished Name to be associated with alias,
used as the issuer and subject fields in the self-signed certificate </td>
</tr>
<tr>
<td class='confluenceTd'> -alias </td>
<td class='confluenceTd'> zanzibar </td>
<td class='confluenceTd'> name to refer the entry within the keystore  </td>
</tr>
<tr>
<td class='confluenceTd'> -keystore </td>
<td class='confluenceTd'> zanzibar.ks </td>
<td class='confluenceTd'>  keystore file location </td>
</tr>
<tr>
<td class='confluenceTd'> -storepass </td>
<td class='confluenceTd'> secret </td>
<td class='confluenceTd'>  password used to protect the integrity of the keystore </td>
</tr>
<tr>
<td class='confluenceTd'> -validity </td>
<td class='confluenceTd'> 730 </td>
<td class='confluenceTd'> number of days for which the certificate should be considered
valid, default is 90 </td>
</tr>
</tbody></table>

<p>Learn more about keytool at the <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/keytool.html"
title="java.sun.com" rel="nofollow">manpage</a>.</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>$ keytool -genkey -keyalg "RSA" -dname "cn=zanzibar, ou=ApacheDS, o=ASF, c=US"
\\
    -alias zanzibar -keystore zanzibar.ks -storepass secret -validity 730
Enter key password for &lt;zanzibar&gt;
        (RETURN if same as keystore password):
$ ls -l
total 4
-rw-r--r--   1 stefan   users       1275 Jun 10 20:42 zanzibar.ks
$ keytool -list -keystore zanzibar.ks
Enter keystore password:  secret

Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

zanzibar, Jun 10, 2007, keyEntry,
Certificate fingerprint (MD5): 95:4A:90:3D:69:09:64:84:C7:21:FD:F7:B8:82:11:8C
$
</pre>
</div></div>
<p>Another option is to use graphical tools for key creation like <a href="http://portecle.sourceforge.net/"
title="portecle.sourceforge.net" rel="nofollow">Portecle</a>, which is basically
a user-friendly front-end for keytool with comparable functionality. For a first impression
see a screen shot below.</p>

<p><img src="/confluence/download/attachments/55248/portecle_with_keystore.png" align="absmiddle"
border="0" /></p>

<h4><a name="3.3.HowtoenableSSL-ConfiguringApacheDStousethisexternalkeystore"></a>Configuring
ApacheDS to use this external keystore</h4>

<p>Enabling SSL in Apache Directory Server and using the key pair created as above is
quite easy. Simply put the keystore file in the <em>conf</em> directory of ApacheDS,
and enable ldaps. Here is the fragment from <em>server.xml</em> on how to do so.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
  ...
  &lt;ldapServer id=<span class="code-quote">"ldapServer"</span>
           ...
           keystoreFile=<span class="code-quote">"C:/java/apacheds-1.5.5/conf/zanzibar.ks"</span>
           certificatePassword=<span class="code-quote">"secret"</span>&gt;
    <span class="code-tag">&lt;transports&gt;</span>
      ...
      <span class="code-tag">&lt;tcpTransport address=<span class="code-quote">"localhost"</span>
port=<span class="code-quote">"10636"</span> enableSSL=<span class="code-quote">"true"</span>/&gt;</span>
    <span class="code-tag">&lt;/transports&gt;</span>
    ...
  <span class="code-tag">&lt;/ldapServer&gt;</span>
  ...
</pre>
</div></div>

<p>The following properties were used</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Property</th>
<th class='confluenceTh'> default value </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> keystoreFile </td>
<td class='confluenceTd'> none </td>
<td class='confluenceTd'> path of the X509 (or JKS) certificate file for LDAPS </td>
</tr>
<tr>
<td class='confluenceTd'> certificatePassword </td>
<td class='confluenceTd'> changeit</td>
<td class='confluenceTd'> password which is used to load the LDAPS certificate file
</td>
</tr>
<tr>
<td class='confluenceTd'> port </td>
<td class='confluenceTd'> 10636 </td>
<td class='confluenceTd'> LDAPS TCP/IP port number to listen to </td>
</tr>
<tr>
<td class='confluenceTd'> enableSSL </td>
<td class='confluenceTd'> true </td>
<td class='confluenceTd'> sets if SSL is enabled or not </td>
</tr>
</tbody></table>

<p>After modification of the <em>server.xml</em>, the server has to be restarted
in order to take effect.</p>

<h2><a name="3.3.HowtoenableSSL-Verification%2CClients"></a>Verification,
Clients</h2>

<p>After restarting the server, you should have a server offering both ldap and ldaps.
How to verify whether it works?</p>

<h3><a name="3.3.HowtoenableSSL-UsingApacheDirectoryStudiotoconnect"></a>Using
Apache Directory Studio to connect</h3>

<p>Apache Directory Studio happily supports ldaps connections. Enter the connection
data (hostname and port) and select "Use SSL encryption" from the dropdown, if you create
or modify a connection:</p>

<p><img src="/confluence/download/attachments/55248/studio_ssl.png" align="absmiddle"
border="0" /></p>

<p>Afterwards the connection behaves like LDAP does. No difference in functionality,
but the transmission is secured by SSL. </p>

<p>Because our self-signed certificate is not trustworthy, many tools will present a
warning (as Studio does in version 1.5.0). You will likely be able to view the certificate,
and decide to continue (accepting the certificate always or this session only), like with
web browsers.</p>

<h3><a name="3.3.HowtoenableSSL-Otherclients%2CJavaprogramsusingJNDI"></a>Other
clients, Java programs using JNDI</h3>

<p>If you use other graphical clients, the behavior will be comparable. Sometimes clients
don't allow to connect to a server, if the certificate is not trustworthy. This is for instance
the case for Java clients using JNDI.  </p>

<p>The following simple Java program tries to connect via JNDI/JSSE (Java Secure Socket
Extension) and LDAPS to <em>ldaps://zanzibar:10636</em></p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">import</span> java.util.Hashtable;
<span class="code-keyword">import</span> javax.naming.*;
<span class="code-keyword">import</span> javax.naming.directory.*;

<span class="code-keyword">public</span> class ConnectWithLdaps {

    <span class="code-keyword">public</span> <span class="code-keyword">static</span>
void main(<span class="code-object">String</span>[] args) <span class="code-keyword">throws</span>
NamingException {

        Hashtable env = <span class="code-keyword">new</span> Hashtable();

        <span class="code-comment">// Simple bind
</span>        env.put(Context.SECURITY_AUTHENTICATION, <span class="code-quote">"simple"</span>);
        env.put(Context.SECURITY_PRINCIPAL,
                <span class="code-quote">"cn=Horatio Hornblower,ou=people,o=sevenSeas"</span>);
        env.put(Context.SECURITY_CREDENTIALS, <span class="code-quote">"pass"</span>);

        env.put(Context.INITIAL_CONTEXT_FACTORY,
                <span class="code-quote">"com.sun.jndi.ldap.LdapCtxFactory"</span>);
        env.put(Context.PROVIDER_URL, <span class="code-quote">"ldaps:<span class="code-comment">//zanzibar:636/o=sevenSeas"</span>);
</span>
        DirContext ctx = <span class="code-keyword">new</span> InitialDirContext(env);
        NamingEnumeration enm = ctx.list("");
        <span class="code-keyword">while</span> (enm.hasMore()) {
            <span class="code-object">System</span>.out.println(enm.next());
        }
        ctx.close();
    }
}
</pre>
</div></div>

<p>It causes a <em>CommunicationException</em>, if the certificate is not
trusted:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>$ java ConnectWithLdaps
Exception in thread "main" javax.naming.CommunicationException: 
  simple bind failed: zanzibar:636 
      [Root exception is javax.net.ssl.SSLHandshakeException: 
       sun.security.validator.ValidatorException: PKIX path building failed:    
       sun.security.provider.certpath.SunCertPathBuilderException: 
       unable to find valid certification path to requested target]
at com.sun.jndi.ldap.LdapClient.authenticate(Unknown Source)
...
</pre>
</div></div>

<p>In order to make the client trust our server, one option is to share a self signed
certificate.<br/>
So we export the certificate (DER format) using keytool like this:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>$ keytool -export -keystore zanzibar.ks -alias zanzibar -file zanzibar.cer
Enter keystore password:  secret
Certificate stored in file &lt;zanzibar.cer&gt;
$ ls -l
total 6
-rw-r--r--   1 stefan   users        504 Jun 10 21:51 zanzibar.cer
-rw-r--r--   1 stefan   users       1275 Jun 10 20:42 zanzibar.ks
$ 
</pre>
</div></div>

<p>Please note that you don't want to share the server keystore file itself with arbitrary
clients, because it holds the private key. Instead we create a separate keystore <em>trusted.ks</em>
with the help of <em>keytool</em>. We import the certificate <em>zanzibar.cer</em>
like this:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>$ keytool -import -file zanzibar.cer -alias zanzibar -keystore trusted.ks -storepass
secret
Owner: CN=zanzibar, OU=ApacheDS, O=ASF, C=US
Issuer: CN=zanzibar, OU=ApacheDS, O=ASF, C=US
Serial number: 466c4611
Valid from: Sun Jun 10 20:42:25 CEST 2007 until: Tue Jun 09 20:42:25 CEST 2009
Certificate fingerprints:
         MD5:  95:4A:90:3D:69:09:64:84:C7:21:FD:F7:B8:82:11:8C
         SHA1: C5:63:E0:DA:BB:C8:0E:E8:27:D0:91:1D:28:DD:11:BB:93:21:13:C9
Trust this certificate? [no]:  yes
Certificate was added to keystore
$ keytool -list -keystore trusted.ks -storepass secret                
Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

zanzibar, Jun 11, 2007, trustedCertEntry,
Certificate fingerprint (MD5): 95:4A:90:3D:69:09:64:84:C7:21:FD:F7:B8:82:11:8C
$
</pre>
</div></div>

<p>Instead of using the command line version of keytool, it is also possible to perform
the certificate export and import operations with Portecle or any other graphical frontend.
This is for instance how the <em>trusted.ks</em> files with the imported certificate
looks like in Portecle.  </p>

<p><img src="/confluence/download/attachments/55248/portecle_with_certificate.png"
align="absmiddle" border="0" /></p>

<p>Clients may use this keystore in order to connect to the server. Therefore they can
configure <em>trusted.ks</em> as the trusted store via the environment like this:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>$ java -Djavax.net.ssl.trustStore=trusted.ks ConnectWithLdaps
ou=people: javax.naming.directory.DirContext
ou=groups: javax.naming.directory.DirContext 
</pre>
</div></div>

<p>Another option would be to import the certificate in the default keystore of the
JRE installation (within $JAVA_HOME/jre/lib/security). For a test certificate this proceeding
is not appropriate.</p>

<h4><a name="3.3.HowtoenableSSL-Troubleshooting"></a>Troubleshooting</h4>

<p>In practice connection establishment with LDAP over SSL may lead to various problems.
In order to eliminate the errors it is helpful to see communication-specific debug information.
The system property <em>javax.net.debug</em> is available for this task. The value
"ssl" provides information about the certificates in the used key store, the server certificate,
and the steps during establishing of the SSL connection (handshake):</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>$ java -Djavax.net.ssl.trustStore=trusted.ks -Djavax.net.debug=ssl ConnectWithLdaps
setting up default SSLSocketFactory
use default SunJSSE impl class: com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl
class com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl is loaded
keyStore is : 
keyStore type is : jks
keyStore provider is : 
init keystore
init keymanager of type SunX509
trustStore is: trusted.ks
trustStore type is : jks
trustStore provider is : 
init truststore
adding as trusted cert:
  Subject: CN=zanzibar, OU=ApacheDS, O=ASF, C=US
  Issuer:  CN=zanzibar, OU=ApacheDS, O=ASF, C=US
  Algorithm: RSA; Serial number: 0x466c4611
  Valid from Sun Jun 10 20:42:25 CEST 2007 until Tue Jun 09 20:42:25 CEST 2009

init context
trigger seeding of SecureRandom
done seeding SecureRandom
instantiated an instance of class com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl
%% No cached client session
*** ClientHello, TLSv1
...
</pre>
</div></div>

<p>You should be able to determine any SSL-related configuration problem with the help
of this log.</p>

<p><a name="3.3.HowtoenableSSL-Resources"></a></p>

<h2><a name="3.3.HowtoenableSSL-Resources"></a>Resources</h2>

<ul>
	<li><a href="http://java.sun.com/products/jsse/" title="java.sun.com" rel="nofollow">Java
Secure Socket Extension (JSSE)</a></li>
	<li><a href="http://portecle.sourceforge.net" title="portecle.sourceforge.net" rel="nofollow">Portecle</a>
a free UI application for creating, managing and examining keystores</li>
	<li><a href="http://wp.netscape.com/eng/ssl3/" title="wp.netscape.com" rel="nofollow">SSL
3.0 Specification (Netscape)</a></li>
</ul>

     </div>
     <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;">
            <a href="http://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
       </div>

       <a href="http://cwiki.apache.org/confluence/display/DIRxSRVx11/3.3.+How+to+enable+SSL">View
Online</a>
       |
       <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=55248&revisedVersion=18&originalVersion=17">View
Change</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message