All,
This is as far as I have gotten. As I said, I believe I still have some
issues with the certificates because I
believe Tomcat is suppose to populate the HttpRequest object with a series
of "attributes" that we should be able to
use to retrieve things like the X.509 certificates. I found one site that
said we should be able to simply issue
something like:
X509Certificate cert =
request.getAttribute("java.security.cert.X509Certificate");
in order to get the specifics of the user. As configured per the notes
below, the SSL session "appears" to be OK as
the servlet gets dispatched as anticipated; only the HttpRequest object's
atrribute array is EMPTY, the principal is
null, but secure = = true.
If anyone out there in CertificateLand or the Tomcat realm can tell us
what's missing, this list ( not the least of
whom is yours truely) could sure use the help!! I think We have the simple
stuff (Form Login) under control, we
need deep down help on SSL, Certificates, and MutalAuthetication.
********* Mutal Authetication Progress notes follow *********
Since the list doesn't handle enclosures, and I don't have a fixed IP
address server to FTP from, here's a lengthy
series of snaps and notes:
Here's a batch file that will create a Certificate Authority in the /ca
directory that you can use to sign any
number of certs:
rem file: CreateCA.bat
openssl req -config ca.cnf -extensions ca_ext -new -newkey
rsa:1024 -nodes -out ca/ca.csr -keyout ca/ca.key
pause
openssl x509 -trustout -signkey ca/ca.key -days 3650 -req -in ca/ca.csr -out
ca/ca.pem
echo
echo "STOP! 1) Copy ca.pem -> ca.crt; 2)Edit ca.crt "TRUSTED
CERTIFICATE" -> "CERTIFICATE""
echo "Then continue"
pause
Here's a batch file that will create, then sign, then package in a p12
format Client certificate for a browser
import:
rem file: CreateClient.bat
echo "When prompted for common name, provide the users common name, e.g.
"Daniel Puryear"
pause
openssl req -config ca.cnf -extensions user_ext -new -newkey
rsa:1024 -nodes -out client/client1.req -keyout
client/client1.key
pause
openssl x509 -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/ca.ser -req -in
client/client1.req -out client/client1.pem
-days 3650
pause
openssl pkcs12 -export -clcerts -in client/client1.pem -inkey
client/client1.key -out client/client1.p12 -name
"Tomcat_Test_CERT"
pause
Here's a batch file that will create, then sign a server certificate, then
package in a keystore called
"server.keystore"
rem file: CreateServer.bat
echo "You can provide data interactively if you remove the -dname parameter"
pause
keytool -genkey -alias tomcat -keyalg RSA -keysize 1024 -keystore
server/server.keystore -storetype JKS -dname
"CN=localhost, OU=NSIT, O=NGC, L=Columbia, S=MD, C=US" -keypass
changeit -storepass changeit
pause
keytool -certreq -keyalg RSA -alias tomcat -file server/server.csr -keystore
server/server.keystore -keypass
changeit -storepass changeit
echo
echo "STOP! Edit server.csr from 'NEW CERTIFICATE REQUEST' -> 'CERTIFICATE
REQUEST' "
echo "Then continue. When prompted for a EXPORT password, use 'changeit'
also..."
pause
openssl x509 -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/ca.ser -req -in
server/server.csr -out server/server.crt
-days 3650
pause
rem HEADS_UP! SEQUENCE ORDER DEPENDENCY!! CA first, so the tomcat import
can find the CA when needed!!
keytool -import -alias rootCA -keystore
server/server.keystore -trustcacerts -file ca/ca.pem -keypass changeit
-storepass changeit
pause
keytool -import -alias tomcat -keystore
server/server.keystore -trustcacerts -file server/server.crt -keypass
changeit -storepass changeit
pause
Here's a batch (crude) to create a truststore to contain your CA's public
key and save it in a file called
trust.keystore
rem file: CreateTrustStore.bat
keytool -genkey -alias truststore -keyalg RSA -keysize 1024 -keystore
trust/trust.keystore -storetype JKS -dname
"CN=truststore, OU=NSIT, O=NGC, L=Columbia, S=MD, C=US" -keypass
changeit -storepass changeit
pause
rem
rem Cause the TC signed CERT to be trusted by loading into the trusted
keystore(Public key Only )
keytool -import -alias rootCA -keystore
trust/trust.keystore -trustcacerts -file ca/ca.pem -keypass changeit
-storepass changeit
pause
You can find several places on the web that basically contains the above,
but here's an OpenSSL config file that
picks up the details. If you don't want the challenge/response dialog (
which, by the way, only the Foxfire engine gets right! Netscape, the
inventers of SSL, no longer handles the SSL itself, it delegates to you
option of either the Foxfire or MSIE SSL engine), comment out entries in the
req_attributes section.
#
# SSLeay example configuration file as modified by D Puryear.
#
RANDFILE = .rnd
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = . # Where everything is kept
certs = $dir\certs # Where the issued certs are kept
crl_dir = $dir\crl # Where the issued crl are kept
database = $dir\index.txt # database index file.
new_certs_dir = $dir\newcerts # default place for new certs.
certificate = $dir\cacert.pem # The CA certificate
serial = $dir\serial # The current serial number
crl = $dir\crl.pem # The current CRL
private_key = $dir\private\cakey.pem # The private key
RANDFILE = $dir\private\private.rnd # private random number file
# Over-riding to force the use of a "-extensions xyz" on each "req" command
#x509_extensions = x509v3_extensions # The extentions to add to the cert
default_days = 3650 # how long to certify for
default_crl_days= 365 # how long before next CRL
default_md = SHA1 # which md to use.
preserve = no # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 1024
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
input_password = changeit
output_password = changeit
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = MD
localityName = Locality Name (eg, city)
localityName_default = Columbia
organizationName = Organization Name (eg, company)
organizationName_default = NGC
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = NSIT
commonName = Common Name (eg, your website's domain name)
commonName_default = <Enter Real Common Name>
commonName_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_default = changeit
challengePassword_min = 4
challengePassword_max = 20
#
#Invoke for CA certs only
[ ca_ext ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always
basicConstraints = critical, CA:true, pathlen:2
keyUsage = critical, digitalSignature, keyCertSign, cRLSign
[user_ext]
basicConstraints = critical, CA:false
keyUsage = critical, digitalSignature, keyEncipherment
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
[server_cert]
basicConstraints = critical, CA:false
keyUsage = critical, digitalSignature, keyEncipherment
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
##******End of File *******
OpenSSL instructions.
1) Download the Windows binary executable from the OpenSSl site and unpack.
2) CD into the bin dir and create ca, client, server, and trust directories.
3) In the ca directory, creat a text file called "ca.ser". In it, add two
characters '0', and '1'
Its the serial number counter that the CA will use for stamping the certs
it signs.
4) Copy the OpenSSL configuration above into a file called "ca.cnf" and
place it in the OpenSSL bin directory
5) Likewise, create the four batch files and place them in the bin
directory.
6) Execute the CreateCA, CreateClient, CreateServer, CreateTrustStore batch
files in that order.
Tomcat instructions:
1) Track down the Tomcat version your using to find out where it likes to
see the server cert.
In 5.5.12, it likes TOMCAT_HOME (so do I), 5.5.9 requires it in the user's
home dictory of the user account that
launches Tomcat. Copy the server.keystore to that directory.
2) Copy the trust.keystore to the TOMCAT_HOME. Remember why we're doing
this. Without an explicitly assigned trust
store, Tomcat will go to the prevailing JDK/JRE and load the contents of
/lib/cacerts as the only "trusted" signers.
We short-circuit that pathing to specify our trust store until we are
satisfied we have it right. Afterwards, we
could load out "rootCA" trusted CA into the JRE's cacerts if you want.
3) Modify Tomcats server.xml file to add/modify the SSL connector to provide
the correct pathign to the two stores.
I used:
<Connector port="8443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="server.keystore" keystorePass="changeit"
keystoreType="JKS"
truststoreFile="trust.keystore" truststorePass="changeit"
truststoreType="JKS"
/>
4) Add the certificate's CommonName for each client to the tomcat-users.xml
file. My play version is:
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="user"/>
<role rolename="tomcat"/>
<role rolename="role1"/>
<role rolename="manager"/>
<role rolename="admin"/>
<user username="Daniel Puryear danielp" password=""
roles="admin,manager,tomcat,user"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
<user username="admin" password="admin" roles="admin,manager"/>
</tomcat-users>
At this point Tomcat should find a client match and complete the SSL
"session" setup (not the HTTP session)
5) If you want Tomcat to provide user role control on a servlet by servlet
basis, edit the WebApps web.xml file. My
play version is:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" >
<display-name>
HelloWebProj</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>HelloWorld</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<security-constraint>
<display-name>Example Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected H Area</web-resource-name>
<!-- Define the context-relative URL(s) to be protected -->
<url-pattern>/h/*</url-pattern>
<!-- If you list http methods, only those methods are protected -->
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
<auth-constraint>
<!-- Anyone with one of the listed roles may access this area -->
<role-name>tomcat</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>tomcat-users</realm-name>
</login-config>
<!-- Security roles referenced by this web application -->
<security-role>
<role-name>tomcat</role-name>
</security-role>
</web-app>
If you need to watch/debug the SSL protocol handshaking include
the -Djavax.net.debug=all System property. I used a
batch file to launch Tomcat while I was debugging the certificate issues:
java -Dcatalina.home="C:\Program Files\Apache Software Foundation\Tomcat
5.5" -Djava.endorsed.dirs="C:\Program
Files\Apache Software Foundation\Tomcat
5.5\common\endorsed" -Djavax.net.debug=all -cp ./bin/bootstrap.jar
org.apache.catalina.startup.Bootstrap "start"
pause
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]