diff -urN ../ejbca_4_0_6/build.xml ./build.xml --- ../ejbca_4_0_6/build.xml 2011-11-18 12:33:42.000000000 +0100 +++ ./build.xml 2011-12-25 12:00:48.000000000 +0100 @@ -25,6 +25,9 @@ + + + @@ -170,23 +173,138 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + - - - + + @@ -414,6 +533,7 @@ + diff -urN ../ejbca_4_0_6/Changelog.txt ./Changelog.txt --- ../ejbca_4_0_6/Changelog.txt 2011-11-18 12:33:42.000000000 +0100 +++ ./Changelog.txt 2011-12-25 12:00:48.000000000 +0100 @@ -1,10 +1,23 @@ -Ejbca 4.0.6, 2011-11-17 +EJBCA 4.0.7, 2011-12-25 --- +New Feature + [ECA-2410] - Document EJBCA Djigzo intregration + [ECA-2430] - Plugin build system + [ECA-2434] - Add CMP KeyUpdate stress test in clientToolBox + +Bug + [ECA-2197] - VA build fails sometimes + [ECA-2396] - More XSS issues + [ECA-2429] - Inconsistency in VA health-check properties comment and used URL + [ECA-2435] - Chinese charaters doesn't work in "Edit End Entity Profles" for DN attributes + [ECA-2436] - Reading OCSP messages over http1.1 with chunked encoding can fail + [ECA-2444] - CMP Revoke Response Message is unprotected sometimes +EJBCA 4.0.6, 2011-11-17 +--- New Feature [ECA-2368] - CMP, Implement message type KeyUpdateRequest - Bug [ECA-2369] - NestedMessageContentTest does not clean up the test certificates it creates [ECA-2380] - Minor XSS issue @@ -12,7 +25,6 @@ EJBCA 4.0.5, 2011-11-02 --- - New Feature [ECA-2332] - Admin GUI ServletFilter for client certificate emulation diff -urN ../ejbca_4_0_6/conf/plugin.properties.sample ./conf/plugin.properties.sample --- ../ejbca_4_0_6/conf/plugin.properties.sample 2011-11-18 12:33:10.000000000 +0100 +++ ./conf/plugin.properties.sample 1970-01-01 01:00:00.000000000 +0100 @@ -1,13 +0,0 @@ -# plugin.properties -# -# if defined the EJBCA build will invoke the plugin ANT file with the following -# properties defined: -# -# ejbca.total.plugin.classpath Holds a path to all .jar files - -# Mandatory: where the ANT file is -plugin.ejbca.ant.file /home/demo/waterfall-publisher/waterfall-publisher/build.xml - -# Optional: where plugin's LIB (jar) distribution is -plugin.ejbca.lib.dir /home/demo/waterfall-publisher/waterfall-publisher/dist - diff -urN ../ejbca_4_0_6/conf/plugins/plugin.properties.sample ./conf/plugins/plugin.properties.sample --- ../ejbca_4_0_6/conf/plugins/plugin.properties.sample 1970-01-01 01:00:00.000000000 +0100 +++ ./conf/plugins/plugin.properties.sample 2011-12-25 11:59:46.000000000 +0100 @@ -0,0 +1,72 @@ +# plugin.properties +# +# In the EJBCA sub-directory "conf/plugins" you may place any number of files +# ending with ".properties". Each of these files will be processed by the +# standard EJBCA build ANT script and the result will be merged in the +# "ejbca.ear" file. +# +# The purpose of this is to enable simple extensions of EJBCA which +# typically would be RA web applications that hooks into the EJBCA "bean" +# and utility libraries as well as in the AppServer. The plugin mechanism +# also makes it easy to extend the EJBCA database schema without bothering +# about JDBC drivers, login IDs etc. +# +# To get this to work there is a "contract" between the plugin and EJBCA +# which must be honored by the plugin. +# +############################################################################################## +# +# EJBCA provides the following properties to the plugin's build script: +# +# +# ejbca.classpath Holds a path to all EJBCA & AppServer .jar files +# +# ejbca.app.xml Holds the path to the EJBCA "application.xml" file +# +# ejbca.dbtype Holds the type of the EJBCA database (e.g. "mysql") +# which can be used to create DB-specific ORM files +# or exploiting DB-specific SQL extensions +# +# ejbca.hibernate Holds the hibernate dialect class matching dbtype +# which can be used for creating "persistence.xml" +# +# ejbca.datasource Holds the JNDI datasource of the EJBCA database +# (e.g. "java:/EjbcaDS") which can be used for creating +# "persistence.xml" +# +# ejbca.gen.path Holds the path to a directory to which plugin binaries +# must be written according to the following: +# Module level .war and ejb .jar: $[ejbca.gen.path} +# Library (utility) .jar : $[ejbca.gen.path}/lib +# +# ejbca.tmp.path Holds the path to a freshly created ("clean") temporary +# directory which a plugin may use during its build process +# +# ejbca.home Holds the path to the EJBCA install directory which may be +# used to access resources that are not available through the +# other properties +# +############################################################################################## +# +# A plugin must through its property file in "conf/plugins" provide the following data: + +# Mandatory: Path to the ANT build file +plugin.ejbca.ant.file /home/demo/myplugin/build.xml + +# Optional: ANT build "target" +plugin.ejbca.ant.target every-feature-you-can-imagine + +# Optional: Custom properties starting with the prefix "plugin.ejbca.ant.custom." +# which will be supplied "as is" to the ANT build +plugin.ejbca.ant.custom.home.sweet.home http://127.0.0.1 +plugin.ejbca.ant.custom.want-warp-speed yes + +# Note: In case you want to configure plugins somewhere outside of the EJBCA source +# tree you can do that by suppling the following definition to the ANT command-line: +# +# -Dejbca.plugin.conf.path=my_config_path + +#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$# +# Note: Improperly designed plugins can introduce security holes in EJBCA!!! # +# Always review the existing code-base when you need access to internal CA resources. # +#$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$# diff -urN ../ejbca_4_0_6/conf/va.properties.sample ./conf/va.properties.sample --- ../ejbca_4_0_6/conf/va.properties.sample 2011-11-18 12:33:10.000000000 +0100 +++ ./conf/va.properties.sample 2011-12-25 11:59:46.000000000 +0100 @@ -1,7 +1,7 @@ #------------------- Validation Authority (VA) Healthcheck settings ------------- # Specifies the basic settings of the VA healthcheck # (i.e. health check servlet that is running on the VA). -# for more detailed configuration edit the file src/publicweb/healthcheck/WEB-INF/web.xml +# for more detailed configuration edit the file modules/healthcheck-war/resources/WEB-INF/web-ocsp.xml # # The url for the external OCSP healthcheck is: # http://127.0.0.1:8080/ejbca/publicweb/vahealthcheck/vahealth diff -urN ../ejbca_4_0_6/doc/RELEASE_NOTES ./doc/RELEASE_NOTES --- ../ejbca_4_0_6/doc/RELEASE_NOTES 2011-11-18 12:33:18.000000000 +0100 +++ ./doc/RELEASE_NOTES 2011-12-25 12:00:02.000000000 +0100 @@ -1,3 +1,19 @@ +EJBCA 4.0.7 +----------- +This is a maintenance release with a few bug fixes and a new feature. In all X issues have been resolved. + +* Noteworthy changes: +- Fixed a bug reading large OCSP requests over HTTP 1.1 using chunked encoding. +- Fixed a few minor XSS issues. +- Fixed an issue where building the Validation Authority (VA) failed on specific platforms. +- The VA health-check URL is now what it is claimed to be in the property file. You will need to reconfigure devices monitoring this URL. +- Documented EJBCA integration with Djigzo +- Added a plug-in build system. +- Improved support for Chinese in the admin GUI. + +Read the full Changelog for details. +For upgrade instructions, please see UPGRADE + EJBCA 4.0.6 ----------- This is a maintenance release with a few bug fixes and a new feature. In all 4 issues have been resolved. diff -urN ../ejbca_4_0_6/doc/UPGRADE ./doc/UPGRADE --- ../ejbca_4_0_6/doc/UPGRADE 2011-11-18 12:33:18.000000000 +0100 +++ ./doc/UPGRADE 2011-12-25 12:00:02.000000000 +0100 @@ -1,4 +1,4 @@ -$Id: UPGRADE 12033 2011-05-19 09:25:31Z anatom $ +$Id: UPGRADE 13473 2011-12-22 11:46:21Z anatom $ UPGRADE ======= @@ -40,6 +40,9 @@ If you get a "java.lang.NoSuchMethodError" in the admin GUI it is because JBoss does not clean temporary files very good. Delete the directories JBOSS_HOME/server/default/tmp and JBOSS_HOME/server/default/work and restart JBoss to get it working. +NOTE: In 4.0.7 the healthcheck URL for the VA, was changed. See conf/va.properties.sample for details how to reconfigure +your healthcheck URL. + EJBCA 4.0alpha1 NOTE -------------------- There is no guarantee that there will be an upgrade path between the alpha release and EJBCA 4.0.0. diff -urN ../ejbca_4_0_6/doc/xdocs/adminguide.xml ./doc/xdocs/adminguide.xml --- ../ejbca_4_0_6/doc/xdocs/adminguide.xml 2011-11-18 12:33:18.000000000 +0100 +++ ./doc/xdocs/adminguide.xml 2011-12-25 11:59:54.000000000 +0100 @@ -945,7 +945,7 @@

You can then use cmpclient (as an RA):

-./cmpclient --server localhost --port 8080 --path ejbca/publicweb/cmp --cacert AdminCA1.der --ir --user mykeyid --password password --clcert clcert.der --key key.pem --subject "CN=User Name;O=My Organization;C=SE" +./cmpclient --server localhost --port 8080 --path ejbca/publicweb/cmp --cacert AdminCA1.der --ir --user mykeyid --password password --newclcert clcert.der --newkey key.pem --subject "CN=User Name;O=My Organization;C=SE"

This requests a certificate, defining the subject DN that will be used. The CA used to sign the certificate is specified in the EJBCA cmp configuration, and can be taken from the keyid. EJBCA authenticated the request using the HMAC protection with the password, and accepts any request upon correct authentication. See the CMP documentation above for more advanced configuration. @@ -965,7 +965,7 @@

You can then use cmpclient (as a client):

-./cmpclient --server localhost --port 8080 --path ejbca/publicweb/cmp --cacert AdminCA1.der --ir --user mykeyid --password password --clcert clcert.der --key key.pem --subject "CN=user1;O=My Organization;C=SE" +./cmpclient --server localhost --port 8080 --path ejbca/publicweb/cmp --cacert AdminCA1.der --ir --user mykeyid --password password --newclcert clcert.der --newkey key.pem --subject "CN=user1;O=My Organization;C=SE"

This requests a certificate, and the requested subject DN must match the registered subject DN. EJBCA authenticates the request using the HMAC protection with the password of the registered user. See the CMP documentation above for more advanced configuration.

@@ -4632,6 +4632,49 @@ +
+

In EJBCA there exists a health check service that can be used for health monitoring. +It is also useful for cluster, as it can be checked by load balancers to determine if a node should be active in the cluster (healthy) +or taken out of the cluster (unhealthy). +

+The servlet is located in the URL: http://localhost:8080/ejbca/publicweb/healthcheck/ejbcahealth +and is configured using conf/ejbca.properties. +

+The following configuration parameters may be set to configure authorization and what the service checks: +

+
    +
  • healthcheck.amountfreemem, default: '1' - The number of Mb of memory that must be free.
  • +
  • healthcheck.dbquery, default: 'select 1' - Parameter indicating the string that should be used to do a minimal check that the database is working.
  • +
  • healthcheck.authorizedips, default: '127.0.0.1' - Specifies which remote IPs that may call this healthcheck servlet. Use ';' between multiple IPs.
  • +
  • healthcheck.catokensigntest; default: 'false' - if the check of CA tokens should actually perform a signature test on the CA token, or it should only see if the token status is active.
  • +
  • healthcheck.publisherconnections, default: 'false' - Defines if test connections agains all configured publisers should be performed.
  • +
+

By editing a maintenance file on the server, you can make the service return an error message stating that the server is down for mainenance. +This is very useful in a cluster when you can take cluster nodes in and out of rotation by editing a simple text file. +

+
    +
  • healthcheck.maintenancefile, default: not set - location of file containing information about maintenance.
  • +
  • healthcheck.maintenancepropertyname, default: DOWN_FOR_MAINTENANCE - the healthcheck.maintenancefile should contain a single line like this 'DOWN_FOR_MAINTENANCE=true'.
  • +
+

The following parameters confiugure what message or HTTP error code the health service returns. +

+
    +
  • healthcheck.okmessage, default: 'ALLOK' - Text string used to say that every thing is ok with this node.
  • +
  • healthcheck.sendservererror, default: 'true' - if a HTTP errorcode 500 should be sent in case of error.
  • +
  • healthcheck.customerrormessage, default: null - Set this parameter if you want a static error message instead of one generated by the HealthChecker.
  • +
+

+If an error is detected one or several of the following error messages is reported. +

+
    +
  • "MEM: Error Virtual Memory is about to run out, currently free memory : number" - The JVM is about to run out of memory.
  • +
  • "DB: Error creating connection to database" - JDBC Connection to the database failed, this might occur if DB craches or network is down.
  • +
  • "CA: Error CA Token is disconnected: CAName" - This is a sign of hardware problems with one or several of the hard ca tokens in the node.
  • +
  • "MAINT: DOWN_FOR_MAINTENANCE" - This is reported when the healthcheck.maintenancefile is used and the node is set to be off line.
  • +
  • "Error when testing the connection with publisher: PublisherName" - This is reported when a test connection to one of the publishers failed.
  • +
+
+

All configuration options, JNDI names etc is configured through the use of properties files in conf/*.properties file. @@ -4830,6 +4873,17 @@

+
+

+In case you (for example) want to extend the RA functionality considerably, possibly including additional +database tables as well, you may consider using the EJBCA plugin scheme which provides custom +applications with the core EJBCA environment data. In the directory src/samples/plugins you will find +a couple of complete demo plugins that can be added to an existing EJBCA installation +without any configuration. See the src/samples/plugins/README file for details. +

+

Plugins are built and packaged together with the rest of the EJBCA components into the "ejbca.ear" file.

+
+

It is a demo servlet that will accept any incoming post, create a user with a unique username, and instantly diff -urN ../ejbca_4_0_6/doc/xdocs/download.xml ./doc/xdocs/download.xml --- ../ejbca_4_0_6/doc/xdocs/download.xml 2011-11-18 12:33:18.000000000 +0100 +++ ./doc/xdocs/download.xml 2011-12-25 12:00:02.000000000 +0100 @@ -10,10 +10,10 @@ If you have problems with any of the download links below, try to download through the Sourceforge download page.

- EJBCA 4.0.5 is now available for download. + EJBCA 4.0.7 is now available for download.
- SHA1 checksum: 92afce3655fec2c845f223a8c22ab07cf9ba2336 + SHA1 checksum: 3ea3e5b71ef4ffe43f4977d761180a90c170a6fa

Cert-cvc library 1.2.13 with full RSA and ECC support is now available for download. diff -urN ../ejbca_4_0_6/doc/xdocs/guides.xml ./doc/xdocs/guides.xml --- ../ejbca_4_0_6/doc/xdocs/guides.xml 1970-01-01 01:00:00.000000000 +0100 +++ ./doc/xdocs/guides.xml 2011-12-25 12:00:02.000000000 +0100 @@ -0,0 +1,1537 @@ + + + + + Howto + + + +

+

+ A number of other, mostly outdated, HOWTO documents are available in the doc/howto directory in the source distribution. +

+
+ +
+

+ Usage of EJBCA for a complete PKI for CVC CAs are explained in this document. +

+
+ +
+

+ This guide explains how to configure a Djigzo gateway to make the gateway request certificates from an external EJBCA server. + Djigzo Email Encryption Gateway is a standards based centrally managed email server (MTA) that encrypts and decrypts your incoming and outgoing email at the gateway level. +

+

+ This is an extract from the complete guide, Djigzo EJBCA Setup Guide. +

+

+ By using the Djigzo-EJBCA integration Djigzo can automatically request certificates from EJBCA for a transparent email encryption experience. +

+ Setting up Djigzo to work with EJBCA contains of a few simple steps: +

+ +

Djigzo communicates with EJBCA using the WebService interface. This means that Djigzo needs an administrator + certificate from EJBCA before is can connect to EJBCA. +

+

+ Create a new administrator keystore for Djigzo in EJBCA. +

+
    +
  • Create a P12 keystore for administrator.
  • +
  • Add the administrator certificate to an administrator group in EJBCA with RA provileges, i.e. privileges to add/edit end entities.
  • +
+
+ +
    +
  • Configure the EJBCA certificate request handler in conf/spring/certificate-request-handlers.xml.
  • +
  • Configure properties as described in the Djigzo EJBCA Setup Guide.
  • +
+
+ +
    +
  • Create a Certificate Profile with.
  • +
      +
    • Key Usage: Digital Signature and Key encipherment.
    • +
    • Extended Key Usage: Any Extended Key Usage or Email Protection (but not both).
    • +
    +
  • Create an End Entity Profile with.
  • +
      +
    • RFC 822 Name as Subject Alternative Name.
    • +
    +
+
+ +

+ When the setup is done you can select the EJBCA Certificate Request Handler in the CA configuration of Djigzo. +

+
+ +
+

+ PrimeKey has made a detailed guide how you set up and configure Windows and EJBCA for Windows SmartCard Logon. + The guide is divided in three section, introduction, Windows configuration and PKI configuration. + The reason for this division is that you can give the Windows guide to the windows administrator, who can easily + follow this guide on the Windows servers, while the PKI can be a hosted service or operated by another department. +

+

+

+

+

+ The scripts and profiles can be fetched here. +

+ +
+ +
+ + +

This article is written for an older version of EJBCA. Now there is a command to import a PKCS#12 file, also in the Admin-GUI under "Edit Certificate Authorities->Import CA keystore". +

The cli command to import a PKCS#12 file is now called bin/ejbca.sh ca importca .... +
The cli command to import user certificates is now called bin/ejbca.sh ca importcert .... +

+ Read the howto at Csita. +

+
+ + +

This document describes how to migrate an RSA Keon CA using nCipher HSM to EJBCA. + The migration guide goes through migrating the CA signing keys, importing the CAs to EJBCA and importing + issued certificates to EJBCA. The result is a setup in EJBCA that can continue operation transparently. +
+ Download EJBCA migration guide (pdf). +

+ +
+ +
+
+

+You can enroll certificates for the iOS directly with EJBCA using SCEP. There is a SCEP profile in the iPhone that you can use for this. +PrimeKey has created a detailed howto if you need this type of support. It works according to the same principals as the examples below. +

+
+ +
+

This howto is contributed by Bruno Bonfils.

+

+ There is a Cisco emulator available. +

+

Here is the IOS config related to the CA: +

+ +! +crypto ca trustpoint FMSCA +enrollment url http://your.ca.host.name:8080/ejbca/publicweb/apply/scep +serial-number +source interface Ethernet0 +auto-enroll regenerate +! + +

+

    +
  • The enrollment line tell how (the method, here an http url) to contact the PKI software. Note: you must omit the pkiclient.exe filename at the end which is automagically add by IOS.
  • +
  • The serial-number tells IOS to include the serial number in the request.
  • +
  • The name of the trustpoint you use MUST MATCH exactly the shortname of your CA in EJBCA (here FMSCA).
  • +
+ Once you have that, use the command: +

+ +# crypto ca authenticate FMSCA + +

+ to fetch the CA certificate. +

+

+ Then, login to EJBCA, and create a new entity profile that looks like: +

+

+ End Entity profile for IOS +

+

+ Then, do the password enrollment with the command: +

+ +# crypto ca enroll FMSCA + +

+ Check your ejbca logs, you shoud see something like: +

+ +ERROR [PKCS10RequestMessage] No CN in DN: SN=12013150+unstructuredName=your.ciscobox.hosts.name +ERROR [Log4jLogDevice] October 19, 2005 9:48:33 AM CEST, CAId : 0, CA, EVENT_ERROR_USERAUTHENTICATION, Administrator : \ +PUBLICWEBUSER, IP Address : 192.168.134.1, User : 12013150, Certificate : No Certificate Involved, Comment : \ +Got request for nonexisting user: 12013150 + +

+ So, you know you must add an entity using the serial number as username, the password you define in IOS, and serialNumber/unstructuredNamed as subject DN fields. +

+

+ After adding the end entity, do the password enrollment again. If you see this you have enrolled succesfully: +

+ +saroumane#sh crypto ca cert +Certificate + Status: Available + Certificate Serial Number: 426FA96340F5D2CA + Certificate Usage: General Purpose + Issuer: + c=FR + o=Fimasys + cn=Fimasys Security CA + Subject: + Name: your.ciscobox.hosts.name + Serial Number: 12013150 + serialNumber=12013150 + hostname=your.ciscobox.hosts.name + Validity Date: + start date: 08:58:28 CET Oct 19 2005 + end date: 09:08:28 CET Oct 19 2007 + Associated Trustpoints: FMSCA + +CA Certificate + Status: Available + Certificate Serial Number: 7AA2B9942CD0D362 + Certificate Usage: Signature + Issuer: + c=FR + o=Fimasys + cn=Fimasys Security CA + Subject: + c=FR + o=Fimasys + cn=Fimasys Security CA + Validity Date: + start date: 07:29:35 CET Oct 17 2005 + end date: 07:39:35 CET Oct 15 2015 + Associated Trustpoints: FMSCA + + + +

+ There is a Cisco 7200 emulator called dynamips available + and a graphical front end GNS3. +

+

Below is a short run through how to configure and enroll directly with EJBCA using GNS3 on Ubuntu 8.10. +

+ +sudo apt-get install gns3 uml-utilities bridge-utils + +

Now you have to configure the host and gns3 to be able to communicate with each other, so the router can connect to EJBCA on the host computer. + This is taken from http://www.blindhog.net/linux-bridging-for-gns3-lan-communications/". +

+ +1. Create a tap interface + sudo tunctl -t tap0 +2. Remove ip addressing and set eth0 and tap0 to promiscuous mode + sudo ifconfig tap0 0.0.0.0 promisc up + sudo ifconfig eth0 0.0.0.0 promisc up +3. Create a new bridge interface + sudo brctl addbr br0 +4. Add tap0 and eth0 to the bridge group + sudo brctl addif br0 tap0 + sudo brctl addif br0 eth0 +5. Enable the bridge interface and give it an ip address + sudo ifconfig br0 up + sudo ifconfig br0 10.10.10.99/24 +6. Configure the default route + sudo route add default gw 10.10.10.254 + +

Now start gns3.

+ +sudo gns3 + +

Configure with IOS image, for example c7200-jk9s-mz.124-13b.bin (an image with crypto commands), it's available on the net. + Also configure a simple topology: +

    +
  • drag cloud to topology window
  • +
  • drag c7200 to topology window
  • +
  • configure cloud and add tap0 interface
  • +
  • add manual link from cloud to c7200
  • +
  • start c7200
  • +
  • open console on c7200
  • +
  • enter configuration and configure FastEthernet0/0 with ip 10.10.10.98/255.255.255.0
  • +
+ Now you should be able to ping the host computer, where EJBCA is running. + It is now time to do the actual enrollment as described above. Below are sample commands I have used. +

+ +Router>enable +Router#configure terminal +Router(config)# +Router(config)#crypto ca trustpoint ScepCA + +Router(ca-trustpoint)#enrollment url http://10.10.10.99:8080/ejbca/publicweb/apply/scep +Router(ca-trustpoint)#serial-number +Router(ca-trustpoint)#ip-address none +Router(ca-trustpoint)#subject-name OU=Network Management, O=PrimeKey Solutions AB, C=SE +Router(ca-trustpoint)#revocation-check none +Router(ca-trustpoint)#exit + +Router(config)#crypto ca authenticate ScepCA +Router(config)#crypto ca enroll ScepCA + +

+ You will see in the log what the username of the user you must create is called. + create end entity profile and user with DN containing SN=FFFFFF and unstructuredName=Router, as seen in the log file (FFFFFF and Router are the default values in the simulator). +

+ +Router(config)#crypto ca enroll ScepCA +Router(config)#exit +Router#show crypto ca certificate + +

+You can always look at the defined trustpoints using the command: +

+ +Router#show crypto ca trustpoints + +

+If you are enrolling towards an RA instead (see External RA documentation for information how to set up an external RA for SCEP) you issue the following commands: +

+ +Router>enable +Router#configure terminal +Router(config)# +Router(config)#crypto ca trustpoint ScepRA + +Router(ca-trustpoint)#enrollment url http://10.10.10.99:8080/scepraserver/scep +Router(ca-trustpoint)#enrollment mode ra +Router(ca-trustpoint)#serial-number +Router(ca-trustpoint)#ip-address none +Router(ca-trustpoint)#subject-name OU=Network Management, O=PrimeKey Solutions AB, C=SE +Router(ca-trustpoint)#revocation-check none +Router(ca-trustpoint)#exit + +Router(config)#crypto ca authenticate ScepRA +Router(config)#crypto ca enroll ScepRA + +

+Note! This would only have a chance to work in EJBCA 3.8.1 and later, and actually it does not work due to the following +error in Cisco. If you have any ideas, please contact us. +

+ +Router#debug crypto pki API +Router#debug crypto pki messages +Router#debug crypto pki server +Router#debug crypto pki transactions +Router#debug crypto pki validation + +... + +*Jan 16 21:47:32.546: CRYPTO_PKI: make trustedCerts list for ScepRA +*Jan 16 21:47:32.550: CRYPTO_PKI: subject="c=SE,o=Foo,cn=Scep RA" serial number= 3A 46 2F B4 5B AC 06 47 + +*Jan 16 21:47:32.554: CRYPTO_PKI: subject="c=SE,o=EJBCA Sample,cn=ScepCA" serial number= 19 A6 7D 78 AF 9D 3B 27 + +*Jan 16 21:47:32.566: E ../cert-c/source/p7digdat.c(377) : Error #703h +*Jan 16 21:47:32.566: E ../cert-c/source/p7spprt.c(589) : Error #703h +*Jan 16 21:47:32.582: pkcs7 verify data returned status 0x703 +*Jan 16 21:47:32.582: CRYPTO_PKI: status = 1795: failed to verify +*Jan 16 21:47:32.582: %PKI-6-CERTFAIL: Certificate enrollment failed. +*Jan 16 21:47:32.582: CRYPTO_PKI: All enrollment requests completed for trustpoint ScepRA. + + +
+ +
+ + +
+

Bruno Bonfils has written this excellent howto on using SSH with certificates from EJBCA:

+

+ OpenSSH and X509 authentication. +

+

+ Another interesting link is this one: +
+ PKCS#11 support in OpenSSH. +

+
+ +
+

EJBCA can issue certificates to be used when protecting sites using OpenSSO (Sun's Access Manager). + EJBCA will then be configured to publish issued certificates to the AM LDAP server. +

+

The configuration is really simple and after installing EJBCA consists of only these steps: +

    +
  • Create a Publisher, AMPublisher with the following properties: +
      +
    • Publisher Type: LDAP V3 Search Publisher
    • +
    • Base DN: The Base DN in the AM LDAP, for example dc=company,dc=com
    • +
    • Login parameters to the AM LDAP server
    • +
    • Create Nonexisting Users: false
    • +
    • Modify Existing Users: true
    • +
    • Add multiple certificates per user: false
    • +
    • Remove certificates when revoked: true
    • +
    • Remove ldap user when certificate revoked: false
    • +
    • LDAP location fields from cert DN: CN, Common Name (not really used)
    • +
    • Suffix base DN of the LDAP Search: same as Base DN, for example dc=company,dc=com
    • +
    • LDAP filter of the search: uid=$USERNAME
    • +
    +
  • +
  • Create a Certificate Profile, AMUser: +
      +
    • Use ENDUSER as template when creating the profile
    • +
    • Extended Key Usage: Client Authentication
    • +
    • Publishers: AMPublisher
    • +
    +
  • +
  • Create an End Entity Profile, AMUser: +
      +
    • Subject DN Fields: UID, CN, O, C is sufficient
    • +
    • Default Certificate Profile: AMUser
    • +
    • Available Certificate Profiles: AMUser
    • +
    +
  • +
+ The procedure when adding a new user is now simple: +
    +
  • Create a new user in AM
  • +
  • Create a new user in EJBCA with the same username and UID as the username in AM
  • +
  • Get the certificate for the user, for example with the user's browser on the public web pages of EJBCA
  • +
+ When the users certificate is created, the certificate is published to the AM LDAP server and certificate authentication can be configured and used in AM. +

+ + +

+ A really good article and description about EJBCA and OpenSSO is written by Bruno Bonfils. +

+

This paper also describes easy integration between EJBCA and OpenSSO, where EJBCA is used for user provisioning. +

+
+
+ +
+

+ This section will show you how to use an Apache Web Server Proxy in front of EJBCA. + The resulting server will +

+
    +
  • Display EJBCA public web at https://ca-server.company.local/
  • +
  • Redirect all HTTP-requests to HTTPS, except for OCSP and CRL.
  • +
  • Require a client SSL certificate when accessing https://ca-server.company.local/adminweb/
  • +
  • Be able to loadbalance requests
  • +
  • Still answer to requests on https://ca-server.company.local/ejbca/*
  • +
+

+ This example was created on Ubuntu 64-bit Server 7.10 using the Apache Web Server 2.2 package, + but should be easy to adapt to any system able to run Apache. +

+

+ Start by installing EJBCA as normal. If you intend to have the CA on the same machine as + the proxy you should modify $EJBCA_HOME/conf/web.properties to only listen to localhost +

+ + httpsserver.bindaddress.pubhttp=127.0.0.1 + httpsserver.bindaddress.pubhttps=127.0.0.1 + httpsserver.bindaddress.privhttps=127.0.0.1 + +

+ Install the Apache web server and enable required modules: +

+ + $sudo su + #apt-get install apache2 + #cd /etc/apache2/mods-enabled/ + #ln -s ../mods-available/proxy.load proxy.load + #ln -s ../mods-available/proxy_http.load proxy_http.load + #ln -s ../mods-available/proxy_ajp.load proxy_ajp.load + #ln -s ../mods-available/proxy_balancer.load proxy_balancer.load + #ln -s ../mods-available/rewrite.load rewrite.load + #ln -s ../mods-available/ssl.load ssl.load + +

+ Generate the SSL-certificate for Apache. This should be issued by the same CA that issued the Tomcat SSL + certificate (AdminCA1 in the default configuration). This can be done with the EJBCA CLI: +

+ + $ cd $EJBCA_HOME + $ bin/ejbca.sh ra adduser apache-ssl foo123 "CN=ca-server.company.local,O=EJBCA Sample,C=SE" "" AdminCA1 "" 1 PEM SERVER + $ bin/ejbca.sh ra setclearpwd apache-ssl foo123 + $ bin/ejbca.sh batch + $ ls p12/pem/ca-server.company.local* + p12/pem/ca-server.company.local-CA.pem p12/pem/ca-server.company.local-Key.pem p12/pem/ca-server.company.local.pem + +

+ Configure the default virtual host-file /etc/apache2/sites-enabled/000-default +

+ + Note that this configuration with SSLVerifyClient inside a Location directtive is not safe with the newly (2009-11-15) discovered + vulnerability in SSL/TLS. You should only use SSLVerifyClient and SSLCipherSuite on whole virtualhosts. You can create the same effect + as below by using a separate subdomain for EJBCA administration (i.e. admin.ca.youdomain.com). +
See for example the Debian advisory. +
+ +NameVirtualHost *:80 +<VirtualHost *:80> + DocumentRoot /var/www/ + + # Proxy requests to EJBCA instances (only one on local machine configured) + <Proxy balancer://mycluster-kerb> + BalancerMember ajp://localhost:8009/ejbca/ + </Proxy> + ProxyPass / balancer://mycluster-kerb/ + + RewriteEngine On + # Redirect all but the CRL Distribution Point, OCSP and Helthcheck to HTTPS + RewriteCond %{THE_REQUEST} !(/publicweb/webdist/certdist.*cmd=crl|/publicweb/status/) + RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R] + # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web. + RewriteCond %{THE_REQUEST} /ejbca/ + RewriteRule ^/ejbca/(.*)$ /$1 [PT] + + # Configure log + LogLevel warn + ErrorLog /var/log/apache2/error.log + CustomLog /var/log/apache2/access.log combined +</VirtualHost> + +NameVirtualHost *:443 +<VirtualHost *:443> + DocumentRoot /var/www/ + + RewriteEngine On + # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web. + RewriteCond %{THE_REQUEST} /ejbca/ + RewriteRule ^/ejbca/(.*)$ /$1 [PT] + + # Configure secure SSL for this server using SSL certificate generated by EJBCA + SSLEngine on + SSLCipherSuite HIGH + SSLProtocol all -SSLv2 + SSLCertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local.pem + SSLCertificateKeyFile /home/jboss/ejbca/p12/pem/ca-server.company.local-Key.pem + + # Require Client SSL certificate for the Admin GUI + <Location /adminweb> + SSLVerifyClient require + SSLVerifyDepth 1 + SSLCACertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local-CA.pem + </Location> + + # Proxy requests to EJBCA instances (only one on local machine configured) + <Proxy balancer://mycluster-kerb> + BalancerMember ajp://localhost:8009/ejbca/ + </Proxy> + ProxyPass / balancer://mycluster-kerb/ + + # Configure log + LogLevel warn + ErrorLog /var/log/apache2/error.log + CustomLog /var/log/apache2/access.log combined +</VirtualHost> + +

+ Reload the apache configuration and verify that only port 80, 443 and other desired services + (e.g. a ssh-daemon) are listening on all or external interfaces +

+ + $sudo /etc/init.d/apache2 reload + $sudo netstat -nap | grep LISTEN | grep -v 127.0.0.1 + tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 7612/apache2 + tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 7612/apache2 + tcp6 0 0 :::22 :::* LISTEN 3746/sshd + +

+ Even though this looks secure, it is still a good idea to use a firewall as an extra layer of security (e.g. drop malformed packages and + prevent future services from being exploited). +

+ + +

+ A sample configuration how to fix up nice URLs for OCSP so that you can point your OCSP service locator to http://ocsp.company.com/ instead of http://ocsp.company.com:8080/ejbca/publicweb/status/ocsp + (some info left out for brevity). +

+ +<VirtualHost ocsp.company.com:80> + <Proxy *> + Order deny,allow + Allow from all + </Proxy> + ProxyPass / http://127.0.0.1:8080/ejbca/publicweb/status/ocsp + ProxyPassReverse / http://127.0.0.1:8080/ejbca/publicweb/status/ocsp +</VirtualHost> + +

You can easily do the same for CRL distribution points. +

+
+ +
+ +
+

+ Instead of using a proxy you can use mod_jk which uses a JK connector between apache and tomcat. I think this have some benefits. + You can easily combine it with mod_rewrite to have any type of external URLs, for OCSP, CRLs etc, and mapping them to other URLs in EJBCA. +

+

+ This section will show you how to use an Apache with mod_jk in front of EJBCA. + The resulting server will +

+
    +
  • Display EJBCA public web at http://demo.primekey.se/
  • +
  • Require a client SSL certificate when accessing https://demo.primekey.se/, which works for the admin-GUI.
  • +
+ mod_jk have many features and by using it you can virtually do anything you want with hosts, ports and URLs. +

+ This example was created on Ubuntu 64-bit Server 8.10 using the Apache Web Server 2.2 package, + but should be easy to adapt to any system able to run Apache. +

+ +# sudo apt-get install apache2 libapache2-mod-jk +# vim /etc/libapache2-mod-jk/workers.properties +----- +worker.list=jboss + +# Define a worker using ajp13 +worker.jboss.port=8009 +worker.jboss.host=127.0.0.1 +worker.jboss.type=ajp13 +----- + + +# vim /etc/apache2/sites-available/demo.primekey.se +----- +<VirtualHost demo.primekey.se:80> + # We must disable default charset or everything will be ISO-8859-1, + AddDefaultCharset off + ServerAdmin webmaster@primekey.se + ServerName demo.primekey.se + ServerAlias demo.primekey.se + + JkLogFile /var/log/apache2/mod_jk.log + JkLogLevel debug + + JkMount /* jboss + JkMount / jboss +</VirtualHost> + +<VirtualHost demo.primekey.se:443>> + # We must disable default charset or everything will be ISO-8859-1, + AddDefaultCharset off + ServerAdmin webmaster@primekey.se + ServerName demo.primekey.se + ServerAlias demo.primekey.se + + SSLEngine on + + JkLogFile /var/log/apache2/mod_jk.log + JkLogLevel debug + + JkMount /* jboss + JkMount / jboss + + # JkExtractSSL is On by default + # JkExtractSSL On +</VirtualHost> +----- + +Enable demo.primekey.se in /etc/apache2/sites-enabled + + +# vim /etc/apache2/mods-available/ssl.conf +----- +SSLVerifyClient require +SSLVerifyDepth 3 + +SSLCACertificateFile /etc/apache2/ssl/apache-CA.pem +SSLCertificateFile /etc/apache2/ssl/apache.pem + +SSLOptions +StdEnvVars +ExportCertData +----- + + + +# vim /etc/apache2/mods-available/jk.load +----- +LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so +JkWorkersFile /etc/libapache2-mod-jk/workers.properties +----- + + +

+ Now enable ssl.load and ssl.conf in /etc/apache2/mods-enabled. +

+

Finally restart apache and go to http://demo.primekey.se/ (or https). Same security considerations as for using proxy applies.

+

+ If you are using the external OCSP responder then you also got to ensure you got this line in the file apache2.conf: +

KeepAlive Off

+ If not apache will hang. +

+

+ Also an external OCSP responder it could be good to add these lines to the 'Virtual Host' configuration: +

+ RewriteEngine on + RewriteRule .* /ejbca/publicweb/status/ocsp [PT] + + JkMount /ejbca/publicweb/status/ocsp/* ocsp_worker + JkMount /ejbca/publicweb/status/ocsp ocsp_worker +

+ By doing this you don't have to bother about typing the last part of the URL. Just right server name will do. +

+
+ +
+

+ This section will show you how to set up automatic certificate enroll of + machines and users in an Windows environment with EJBCA. +

+ General idea +

+
    +
  • Use mod_auth_kerb on a Apache2 web server proxy to validate the requesters identity using Kerberos.
  • +
  • A login VBS-Script creates a certificate request that is sent to the proxy using IE-components.
  • +
  • A Servlet protected by the proxy receives the requests and creates a new cert.
  • +
  • The new certificate will use information from the request (UPN and CertificateTemplate) and read.
  • +
  • information from active directory (CN,DC etc).
  • +
  • Autoenrollment should be configurable in the Admin GUI.
  • +
+ +

+ Current status +

+
    +
  • Machine enroll on Domain Controller: WORKING
  • +
  • DomainController enroll on Domain Controller: WORKING
  • +
  • User enroll (Administrator) on Domain Controller: NOT WORKING (Does not trusts ca-server as Intranet, despite GP)
  • +
  • Machine enroll on other WS2K3 client: WORKING (not checked in a while)
  • +
  • User enroll (Administrator) on other WS2K3 client: NOT WORKING (Does not trusts ca-server as Intranet, despite GP, also complains about untrusted VBS if ran manually)
  • +
  • Machine enroll on WinXP client: WORKING
  • +
  • User enroll (Administrator) on WinXP client: WORKING
  • +
+

+ Known issues +

+
    +
  • SECURITY: The Servlet should verify that e.g. only Users can request User certificates, DCs only DC certs etc.. and other permissions if possible.
  • +
  • The enroll scripts always fetches new certificates. They should use the command=status first to see if a new cert is needed.
  • +
  • AdminWeb cannot verify admin certificates if non-"/ejbca/" path is used in URL.
  • +
  • Autoenroll Servlet doesn't get X-Remote-User if "/ejbca/" path is used in URL.
  • +
  • Order of Subject DNs is wrong compared with MS certs..
  • +
  • SSL connection to AD has not been tested.
  • +
  • Certificates don't have the CertificateTemplate attrib yet.. looks nicer in Certificate MMC snapin..
  • +
  • JavaScript "onchange" behaves strangely in IE6. Only activated when the table is clicked, not the checkbox..
  • +
  • Creation of EEPs is inefficient due to attempted removal of EEP before each new request.. (Debug-code)
  • +
+

+ ... +

+
+ +

+ Domain Controller: dc1.company.local +

+
    +
  • Windows Server 2003 EE patched to SP2
  • +
  • Active Directory
  • +
  • DNS Server
  • +
+

+ CA Server: ca-server.company.local +

+
    +
  • Ubuntu 64 Server 7.10
  • +
  • Apache2 with modules
  • +
  • Kerberos 5
  • +
  • Java 1.6u4
  • +
  • JBoss 4.2.2.GA
  • +
  • EJBCA 3.6 Alpha
  • +
  • Apache Ant 1.7.0
  • +
+

+ Desktop client: client-01.company.local +

+
    +
  • Windows XP Pro SP1 patched to SP2
  • +
+
+ +

+ Configure EJBCA not to respond to external web-requests by editing $EJBCA_HOME/conf/web.properties +

+ +... +httpsserver.bindaddress.pubhttp=127.0.0.1 +httpsserver.bindaddress.pubhttps=127.0.0.1 +httpsserver.bindaddress.privhttps=127.0.0.1 +... + +

+ After installation, go to EJBCA Admin GUI -> System Configuration and + configure the autoenrollment settings. +

+
+ +

+ This could probably be done on a Windows server as well, since Apache + and Kerberos is supposed to work on that platform too.. +

+ +$sudo su +#apt-get update +#apt-get install krb5-user apache2 libapache2-mod-auth-kerb + ** Skip kerberos config.. we will configure this later ** +#cd /etc/apache2/mods-enabled/ +#ln -s ../mods-available/proxy.load proxy.load +#ln -s ../mods-available/proxy_ajp.load proxy_ajp.load +#ln -s ../mods-available/proxy_balancer.load proxy_balancer.load +#ln -s ../mods-available/rewrite.load rewrite.load +#ln -s ../mods-available/ssl.load ssl.load +#ln -s ../mods-available/headers.load headers.load + +

+ Edit /etc/krb5.conf where dc1.company.local is the DNS-name of the Domain Controller and COMPANY.LOCAL is our domain. +

+ +[libdefaults] +default_realm = COMPANY.LOCAL + +[realms] +COMPANY.LOCAL = { + kdc = dc1.company.local:88 + admin_server = dc1.company.local:88 +} + +[domain_realm] + .company.local = COMPANY.LOCAL + company.local = COMPANY.LOCAL + +[logging] +default = FILE:/var/log/apache2/krb5.log + +

+ Edit /etc/network/interfaces and set a static IP address +

+ +... +#iface eth0 inet dhcp +iface eth0 inet static + address 192.168.0.102 # Address of this machine + netmask 255.255.255.0 + gateway 192.168.0.101 # In our local network this is the Domain Controller + +

+ Use the DC as DNS server in /etc/resolv.conf +

+ +search localdomain +nameserver 192.168.0.101 + +

+ and restart networking (sudo /etc/init.d/networking restart). +

+

+ Add "ntdpdate dc1.company.local" to /etc/rc.local or a cron job to make sure the + ca-server is syncronized with the Domain Controller. +

+

+ Create the SSL certificates for the Apache proxy using the same CA as our EJBCA installation and the same subject DN. +

+ +$cd $EJBCA_HOME +$bin/ejbca.sh ra adduser apache-ssl foo123 "CN=ca-server.company.local,O=EJBCA Sample,C=SE" "" AdminCA1 "" 1 PEM SERVER +$bin/ejbca.sh ra setclearpwd apache-ssl foo123 +$bin/ejbca.sh batch +$ls p12/pem/ca-server.company.local* +p12/pem/ca-server.company.local-CA.pem p12/pem/ca-server.company.local-Key.pem p12/pem/ca-server.company.local.pem + +

+ Edit /etc/apache2/sites-enabled/000-default to display an apache proxy front for EJBCA +

+ +NameVirtualHost *:80 +<VirtualHost *:80> + DocumentRoot /var/www/ + + # Proxy requests to EJBCA instances (only one on local machine configured) + <Proxy balancer://mycluster-kerb> + BalancerMember ajp://localhost:8009/ejbca/ + </Proxy> + ProxyPass / balancer://mycluster-kerb/ + + RewriteEngine On + # Redirect all but the CRL Distribution Point, OCSP and Helthcheck to HTTPS + RewriteCond %{THE_REQUEST} !(/publicweb/webdist/certdist.*cmd=crl|/publicweb/status/) + RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R] + # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web. + RewriteCond %{THE_REQUEST} /ejbca/ + RewriteRule ^/ejbca/(.*)$ /$1 [PT] + + # Configure log + LogLevel warn + ErrorLog /var/log/apache2/error.log + CustomLog /var/log/apache2/access.log combined +</VirtualHost> + +NameVirtualHost *:443 +<VirtualHost *:443> + DocumentRoot /var/www/ + + RewriteEngine On + # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web. + RewriteCond %{THE_REQUEST} /ejbca/ + RewriteRule ^/ejbca/(.*)$ /$1 [PT] + + # Configure secure SSL for this server using SSL certificate generated by EJBCA + SSLEngine on + SSLCipherSuite HIGH + SSLProtocol all -SSLv2 + SSLCertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local.pem + SSLCertificateKeyFile /home/jboss/ejbca/p12/pem/ca-server.company.local-Key.pem + + # Require Client SSL certificate for the Admin GUI + <Location /adminweb> + SSLVerifyClient require + SSLVerifyDepth 1 + SSLCACertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local-CA.pem + </Location> + + # Require Kerberos authentication for the Autoenroll Servlet + <Location /autoenroll> + AuthType Kerberos + Krb5Keytab /etc/apache2/http.keytab + KrbAuthRealms COMPANY.LOCAL + KrbServiceName HTTP + KrbMethodNegotiate on + KrbMethodK5Passwd off + Require valid-user + </Location> + + # Forward the UPN as variable X-Remote-User + RewriteCond %{IS_SUBREQ} ^false$ + RewriteCond %{LA-U:REMOTE_USER} (.+) + RewriteRule .* - [E=RU:%1] + RequestHeader set X-Remote-User %{RU}e + + # Proxy requests to EJBCA instances (only one on local machine configured) + <Proxy balancer://mycluster-kerb> + BalancerMember ajp://localhost:8009/ejbca/ + </Proxy> + ProxyPass / balancer://mycluster-kerb/ + + # Configure log + LogLevel warn + ErrorLog /var/log/apache2/error.log + CustomLog /var/log/apache2/access.log combined +</VirtualHost> + +

+ Restart apache with "sudo /etc/init.d/apache2 restart" +

+

+ Install Windows support tools on the Domain Controller (found in %WIN2k3CD%\SUPPORT\TOOLS\SUPTOOLS.msi) to get ktpass.exe. + Create a new user "ca-server@company.local" and a strong password e.g not FooBar123 used here. + Create a keytab-file "http.keytab" on the Domain Controller: +

+ +ktpass.exe -princ HTTP/ca-server.company.local@COMPANY.LOCAL -mapuser ca-server -crypto DES-CBC-MD5 -ptype KRB5_NT_PRINCIPAL -mapop set +desonly -pass FooBar123 -out http.keytab + ... + keysize 55 HTTP/ca-server.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype + 0x3 (DES-CBC-MD5) keylength 8 (0x64614c9d256bcd6d) + ... + +

+ And move the file to ca-server.company.local:/etc/apache2/http.keytab change permissions to be + readable only by the apache-process. +

+ +$chown root:root /etc/apace2/http.keytab + +

+ Verify that the keytab is correct: +

+ +$kinit Administrator +$kvno HTTP/ca-server.company.local +$klist -e +** Output here should match the one from ktpass.exe ** + +

+ Verify that the keytab can be used: +

+ +$kdestroy +$sudo kinit -k -t /etc/apache2/http.keytab HTTP/ca-server.company.local +$sudo klist +(You should have received a ticket here if everything is working.) +$sudo kdestroy + +

+ Add ca-server.company.local (192.168.1.2) to your Domain Controllers DNS server as a "Host (A)" record. +

+
+ +

+ Create a Shared directory on the Domain Controller, C:\Shared with read and exec rights by Everyone +

+ +copy %SYSTEMROOT%\system32\certreq.exe C:\Shared\Autoenroll\ +copy %SYSTEMROOT%\system32\certcli.dll C:\Shared\Autoenroll\ +copy %SYSTEMROOT%\system32\certadm.dll C:\Shared\Autoenroll\ +(copy %SYSTEMROOT%\system32\certutil.exe C:\Shared\Autoenroll\ This is used by EnrollDomainController and is already available at all DCs.) + +

+ Edit or create C:\Shared\Autoenroll\autoenroll.conf +

+ +# This is a primitive config file that does not allow spaces + +# The request URL is built from the following properties +# https://[requestpath]?request=... +# + +# Standard SSL-port and using URL rewrite from /ejbca/* to /* +requestpath=ca-server.company.local/autoenroll + +# Non-standard SSL-port and not using URL rewrite +#requestpath=ca-server.company.local:4443/ejbca/autoenroll + +# Debug setting, use only for manual testing +#debug=true +debug=false + +

+ Edit or create C:\Shared\Autoenroll\RequestAndInstall.vbs +

+ + Set oArgs = WScript.Arguments + if oArgs.Count < 1 then + WScript.Echo "Usage: thisscript.vbs fullpathnameofrequest.inf" + WScript.Quit 1 + else + sRequestInfo = Trim(oArgs(0)) + end if + + Set WS = CreateObject("WScript.Shell") + + sRequest = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.req" + sResult = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.p7b" + + Set oFilesystem = CreateObject("Scripting.FileSystemObject") + On Error Resume Next ' Ignore if we try to delete a file that does not exist + oFilesystem.DeleteFile(sRequest) + Err.Clear + On Error GoTo 0 + sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\" + + Set iFile = oFilesystem.OpenTextFile(sSharedDir & "autoenroll.conf") + Do While iFile.AtEndOfStream <> True + sLine = iFile.Readline + If InStr(Left(sLine,1), "#") = 0 then + If InStr(sLine, "requestpath=") <> 0 then + sRequestPath = Trim(Right(sLine, Len(sLine)-Len("requestpath="))) + end if + If InStr(sLine, "debug=") <> 0 then + sDebug = Trim(Right(sLine, Len(sLine)-Len("debug="))) + end if + End if + Loop + iFile.Close + + WS.Run sSharedDir & "certreq.exe -f -new " & sRequestInfo & " " & sRequest, 0, True + + sRequestData = "" + Set objFile = oFilesystem.OpenTextFile(sRequest, 1) + Do Until objFile.AtEndOfStream + sRequestData = sRequestData & objFile.ReadLine + Loop + objFile.Close + + set oIE = CreateObject("InternetExplorer.Application") + + oIE.navigate2("https://" & sRequestPath & "?debug=" & sDebug & "&request=" & sRequestData) + + If sDebug = "true" Then + oIE.visible = true + End If + + 'Wait max 30 seconds + wscript.sleep 1000 + counter = 0 + While oIE.Busy = true And counter < 30 + counter = counter + 1 + wscript.sleep 1000 + Wend + + sResultData = oIE.Document.Body.innerHTML + sResultData = Mid(sResultData, 6, Len(sResultData)-11) + + Set oFile = oFilesystem.CreateTextFile(sResult, True) + oFile.WriteLine sResultData + oFile.Close + + on error resume next ' in case the Task Manager is used to close IE. + If sDebug <> "true" Then + oIE.quit ' Close the window + WS.Run sSharedDir & "certreq.exe -accept " & Chr(34) & sResult & Chr(34), 0, True + End If + +

+ Edit or create C:\Shared\Autoenroll\EnrollDomainController.vbs +

+ + ' This Script is based on the script found at http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/security/advcert.mspx#EURAE + + iRole = GetLastDomainRole() + If iRole <> 4 And iRole <> 5 Then + WScript.Echo "This script should only run on a Domain Controller." + WScript.Quit 1 + End If + + Set WS = CreateObject("WScript.Shell") + + Set objDC = GetObject("LDAP://" & CreateObject("ADSystemInfo").ComputerName) + sGUID = objDC.GUID + sDNShostname = objDC.DNShostname + + Set oFilesystem = CreateObject("Scripting.FileSystemObject") + sTempfilePrefix = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled" + sRequestInfo = sTempFilePrefix & ".inf" + sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\" + + 'Create b64 encoded extension + Dim aASNsubstring(2, 5) + Const HEX_DATA_LENGTH = 1 + Const ASCIIDATA = 2 + Const HEXDATA = 3 + Const HEX_BLOB_LENGTH = 4 + Const HEX_TYPE = 5 + ' Encode DNS + aASNsubstring(0, ASCIIDATA) = sDNShostname + aASNsubstring(0, HEX_TYPE) = "82" + For i = 1 to Len(aASNsubstring(0, ASCIIDATA)) + aASNsubstring(0, HEXDATA) = aASNsubstring(0, HEXDATA) & Hex(Asc(Mid(aASNsubstring(0, ASCIIDATA), i, 1))) + Next + aASNsubstring(0, HEX_DATA_LENGTH) = ComputeASN1 (Len(aASNsubstring(0, HEXDATA)) / 2) + sASN = aASNsubstring(0, HEX_TYPE) & aASNsubstring(0, HEX_DATA_LENGTH) & aASNsubstring(0, HEXDATA) + ' Encode GUID + aASNsubstring(1, HEXDATA) = sGUID + aASNsubstring(1, HEX_TYPE) = "A0" + aASNsubstring(1, HEX_DATA_LENGTH) = ComputeASN1 (Len(aASNsubstring(1, HEXDATA)) / 2) + sASN = sASN & "A01F06092B0601040182371901" & aASNsubstring(1, HEX_TYPE) & "120410" & aASNsubstring(1, HEXDATA) + + Set oFile = oFilesystem.CreateTextFile(sTempfilePrefix & ".asn") + oFile.WriteLine "30" & ComputeASN1 (Len(sASN) / 2) & sASN + oFile.Close + WS.Run "certutil -f -decodehex " & sTempfilePrefix & ".asn " & sTempfilePrefix & ".bin", 0, True + WS.Run "certutil -f -encode " & sTempfilePrefix & ".bin " & sTempfilePrefix & ".b64", 0, True + + Set iFile = oFilesystem.OpenTextFile(sTempfilePrefix & ".b64") + Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True) + oFile.WriteLine "[Version]" + oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) + oFile.WriteLine "" + oFile.WriteLine "[NewRequest]" + oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34) + oFile.WriteLine "KeySpec = 1" + oFile.WriteLine "KeyLength = 2048" + oFile.WriteLine "Exportable = TRUE" + oFile.WriteLine "MachineKeySet = TRUE" + oFile.WriteLine "SMIME = FALSE" + oFile.WriteLine "PrivateKeyArchive = FALSE" + oFile.WriteLine "UserProtected = FALSE" + oFile.WriteLine "UseExistingKeySet = FALSE" + oFile.WriteLine "ProviderName = " & Chr(34) & "Microsoft RSA SChannel Cryptographic Provider" & Chr(34) + oFile.WriteLine "ProviderType = 12" + oFile.WriteLine "RequestType = PKCS10" + oFile.WriteLine "KeyUsage = 0xa0" + oFile.WriteLine "" + oFile.WriteLine "[EnhancedKeyUsageExtension]" + oFile.WriteLine "OID=1.3.6.1.5.5.7.3.1" + oFile.WriteLine "OID=1.3.6.1.5.5.7.3.2" + oFile.WriteLine "" + oFile.WriteLine "[Extensions]" + iLine = 0 + Do While iFile.AtEndOfStream <> True + sLine = iFile.Readline + If sLine = "-----END CERTIFICATE-----" then + Exit Do + end if + if sLine <> "-----BEGIN CERTIFICATE-----" then + if iLine = 0 then + oFile.WriteLine "2.5.29.17=" & sLine + else + oFile.WriteLine "_continue_=" & sLine + end if + iLine = iLine + 1 + end if + Loop + oFile.WriteLine "Critical=2.5.29.17" + oFile.WriteLine "" + oFile.WriteLine "[RequestAttributes]" + oFile.WriteLine "CertificateTemplate = DomainController" + oFile.Close + iFile.Close + + WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True + + ' Sub + Function ComputeASN1 (iStrLen) + If Len(Hex(iStrLen)) Mod 2 = 0 then + sLength = Hex(iStrLen) + else + sLength = "0" & Hex(iStrLen) + end if + if iStrLen > 127 then + ComputeASN1 = Hex (128 + (Len(sLength) / 2)) & sLength + else + ComputeASN1 = sLength + End If + End Function + + 'Return the domain role number where: + '-1 Error + '0 Standalone Workstation + '1 Member Workstation + '2 Standalone Server + '3 Member Server + '4 Backup Domain Controller + '5 Primary Domain Controller + Function GetLastDomainRole () + On Error Resume Next + strComputer = "." + Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") + Set colItems = objWMIService.ExecQuery("Select DomainRole from Win32_ComputerSystem",,48) + For Each objItem in colItems + iReturn = objItem.DomainRole + Next + On Error Goto 0 + GetLastDomainRole = iReturn + End Function + +

+ Edit or create C:\Shared\Autoenroll\EnrollMachine.vbs +

+ + Set WS = CreateObject("WScript.Shell") + Set oFilesystem = CreateObject("Scripting.FileSystemObject") + sRequestInfo = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.inf" + Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True) + oFile.WriteLine "[Version]" + oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) + oFile.WriteLine "" + oFile.WriteLine "[NewRequest]" + oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34) + oFile.WriteLine "KeyLength = 2048" + oFile.WriteLine "MachineKeySet = TRUE" + oFile.WriteLine "RequestType = PKCS10" + oFile.WriteLine "" + oFile.WriteLine "[RequestAttributes]" + oFile.WriteLine "CertificateTemplate = Machine" + oFile.Close + + sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\" + WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True + +

+ Edit or create C:\Shared\Autoenroll\EnrollUser.vbs +

+ + Set WS = CreateObject("WScript.Shell") + Set oFilesystem = CreateObject("Scripting.FileSystemObject") + sRequestInfo = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.inf" + Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True) + oFile.WriteLine "[Version]" + oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) + oFile.WriteLine "" + oFile.WriteLine "[NewRequest]" + oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34) + oFile.WriteLine "KeyLength = 2048" + oFile.WriteLine "RequestType = PKCS10" + oFile.WriteLine "" + oFile.WriteLine "[RequestAttributes]" + oFile.WriteLine "CertificateTemplate = User" + oFile.Close + + sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\" + WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True + +

+ Verify that all the file in Shared\Autoenroll directory has read end exec right for Everyone. +

+ Install Certificate Templates by adding the corresponding Snap-in i the MMC console. +

+ Install the root CA-certificate(s) in the NTAuthStore, so windows can verify all cerificates produced by EJBCA. + Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> + Edit Default Domain Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Public Key Policies -> + Trusted Root Certificate Authorities -> Import -> import the root ca certificate and run "gpupdate /force" on + machines that are used for testing. + (You can fetch the CA certificate using the EJCBA CLI with "$EJBCA_HOME/bin/ejbca.sh ca getrootcert AdminCA1 ~/AdminCA1.crt -der".) +

+ Add Startup Scripts in + Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> + Edit Default Domain Policy -> Computer Configuration -> Windows Settings -> Scripts -> Startup -> + Add the machine-related scripts from the shared directory. +

+ Add Login Scripts in + Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> + Edit Default Domain Policy -> User Configuration -> Windows Settings -> Scripts -> Logon -> + Add the user-related scripts from the shared directory. +

+ Add the ca-server and shared directory to the Intranet + Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> + Edit Default Domain Policy -> Computer Configuration | User Configuration (do both!!) -> Administrative Templates -> + Windows Components -> Internet Explorer -> Internet Control Page -> Security Page -> + Site to Zone assignement list -> Enabled and added "https://ca-server.company.local" to zone "1", "\\Dc1\Shared" to zone "1" +

+ Configure clients to synchronize time using NTP: + Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> + Edit Default Domain Policy -> Computer Configuration -> Administrative Templates -> + System -> Windows Time Service -> Time Providers -> Configure Windows NTP Client (Add "dc1.company.local" as an NTP server.) + and Enable Windows NTP Client. +

+ Use "gpupdate /force" on clients before running tests or wait 8h.. =) +

+
+ +

+ Well, good luck with Windows error messages.. but you can enable debug + ("debug=true" in autoenroll.conf) to see the response from the Servlet. +

+ Test the machine-cert-retreival script by starting a Console as "LocalSystem". C:\Shared\Autoenroll\ConsoleAsLocalSystem.vbs: +

+ + Set WS = CreateObject("WScript.Shell") + WS.Run "sc.exe delete lsc", 0, True + WS.Run "sc.exe create lsc binpath= " & Chr(34) & "cmd /K start" & Chr(34) & " type= own type= interact", 0, True + WS.Run "sc.exe start lsc", 0, True + +

+ Test the machine-cert-retreival script by starting a Console as "LocalSystem". C:\Shared\ConsoleAsLocalSystem.vbs: +

+ + Set WS = CreateObject("WScript.Shell") + WS.Run "sc.exe delete lsc", 0, True + WS.Run "sc.exe create lsc binpath= " & Chr(34) & "cmd /K start" & Chr(34) & " type= own type= interact", 0, True + WS.Run "sc.exe start lsc", 0, True + +

+ Adding a custom Administrative template can be done as in this example if needed: + Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> + Edit Default Domain Policy -> Computer Configuration -> Administrative Templates -> Add/Remove Templates -> Add Autoenroll.adm +

+

+ This is just a sample, but shows how a custom GP can be configured.. (Use the intructions above instead of this template. + The example Administrative Template "Autoenroll Related" can be used to force ca-server.company.local + into the Intranet zone or add a NTP syncronizing policy. C:\Shared\Autoenroll\Autoenroll.adm: +

+ +CLASS MACHINE + +CATEGORY "Autoenroll Related" + CATEGORY "NTP Synch for clients with AD" + POLICY "Enable NTP synch" + SUPPORTED "This is a hack to get WinXP clients working" + EXPLAIN ".." + KEYNAME "Software\Policies\Microsoft\W32Time\TimeProviders" + VALUENAME "NtpServer" + VALUEON NUMERIC 1 + VALUEOFF NUMERIC 0 + + ACTIONLISTON + KEYNAME "Software\Policies\Microsoft\W32Time\Parameters" + VALUENAME "Type" + VALUE "NTP" + + KEYNAME "Software\Policies\Microsoft\W32Time\Config" + VALUENAME "AnnounceFlags" + VALUE NUMERIC 5 + + KEYNAME "Software\Policies\Microsoft\W32Time\Config" + VALUENAME "MaxPosPhaseCorrection" + VALUE NUMERIC 1099511627775 + + KEYNAME "Software\Policies\Microsoft\W32Time\Config" + VALUENAME "MaxNegPhaseCorrection" + VALUE NUMERIC 1099511627775 + END ACTIONLISTON + + PART "NTP Servers in the form ntp.server1.com,0x1 ntp.server2.com,0x1 ntp.server3.com,0x1" EDITTEXT + KEYNAME "Software\Policies\Microsoft\W32Time\Parameters" + VALUENAME "NtpServer" + MAXLEN 4096 + END PART + + PART "Poll interval in seconds" NUMERIC + KEYNAME "Software\Policies\Microsoft\W32Time\TimeProviders\NtpClient" + VALUENAME "SpecialPollInterval" + DEFAULT 900 + END PART + END POLICY + END CATEGORY + + CATEGORY "Required trust" + POLICY "Trust ca-server.company.local" + SUPPORTED "Might need IE6 for this to work.." + EXPLAIN "This adds the ca-server.company.local to the list of intranet-sites.." + KEYNAME "Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\company.local\ca-server" + VALUENAME "https" + VALUEON NUMERIC 1 + VALUEOFF NUMERIC 0 + END POLICY + END CATEGORY +END CATEGORY + +CLASS USER + +CATEGORY "Autoenroll Related" + CATEGORY "Required trust" + POLICY "Trust ca-server.company.local" + SUPPORTED "Might need IE6 for this to work.." + EXPLAIN "This adds the ca-server.company.local to the list of intranet-sites.." + KEYNAME "Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\company.local\ca-server" + VALUENAME "https" + VALUEON NUMERIC 1 + VALUEOFF NUMERIC 0 + END POLICY + END CATEGORY +END CATEGORY + +

+ Useful reg-for VMwares with runaway clocks if GP mod didn't work or you just want to modify a single client. +

+ +Windows Registry Editor Version 5.00 + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config] +"AnnounceFlags"=dword:00000005 +"MaxPosPhaseCorrection"=dword:ffffffff +"MaxNegPhaseCorrection"=dword:ffffffff + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters] +"Type"="NTP" +"NtpServer"="dc1.company.local,0x1" + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters\NtpServer] +"NtpServer"="dc1.company.local,0x1" + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient] +"SpecialPollInterval"=dword:00000030 + +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer] +"Enabled"=dword:00000001 + +
+ + +

Other auto enroll references

+ +
+
+ +
+

+ This is a very thorough guide with screen-shots of how to setup EJBCA 3.6.0 + with GemSAFE Toolbox in a windows environment for smartcard logon, email signing, + email encryption and SSL services. +

+

+ The guide is divided into three PDF-files: +

+

+
+ +
+

+ A fully working RA Admin sample program, written using Java and EJBCA web services, may be downloaded from + the WebServiceRA project on SourceForge. +

+

+ This Java program provides a simple UI for creating and querying end entities. + All communications with the appserver are via EJBCA web services. +

+

+ It includes wizard dialogs that prompt the user for the type of certificate to create, that prompt the user to enter values that define the subject DN, + that allow the user to receive an email notification containing the password for the new end entity, + that allow the user to choose between adding the new end entity to the EJBCA database and actually generating the certificate (as a P12 or JKS file). +

+

+ Further information on this application can be found in the project's README.txt (building and running the application), + its troubleshooting.txt (further tips on running the application), and todo.txt (notes and issues for developers). +

+

+ A short movie demonstrating the program may be downloaded from + SourceForge + or + YouTube. +

+
+ + +
+

+ This excellent HOWTO on PKI in general, LDAP, email and server setup has been kindly contributed by SensorNet. Please read this notice! +

+ +These pages were created by the SensorNet Project at Oak Ridge National +Laboratory (ORNL), Oak Ridge, Tennessee, USA to provide help for their +instance of EJBCA. You are welcome to modify these pages for your own +use, but please remove any links to the SensorNetCA web pages so that we +do not get excess traffic. Please tell your users not to use the URLs in +the screen shots, and please credit Oak Ridge National Laboratory. ORNL +is operated by UT-Battelle for the U.S. Department Of Energy. + +

+

+

+ + +

+

+

+
+ + +

+

+

+
+ + +

+

+

+
+ +
+ +
+

Bruno Bonfils have written some documentation in french

+
+ + + diff -urN ../ejbca_4_0_6/doc/xdocs/howto.xml ./doc/xdocs/howto.xml --- ../ejbca_4_0_6/doc/xdocs/howto.xml 2011-11-18 12:33:18.000000000 +0100 +++ ./doc/xdocs/howto.xml 1970-01-01 01:00:00.000000000 +0100 @@ -1,1486 +0,0 @@ - - - - - Howto - - - -
-

- A number of other, mostly outdated, HOWTO documents are available in the doc/howto directory in the source distribution. -

-
- -
-

- Usage of EJBCA for a complete PKI for CVC CAs are explained in this document. -

-
- -
-

- This excellent HOWTO on PKI in general, LDAP, email and server setup has been kindly contributed by SensorNet. Please read this notice! -

- -These pages were created by the SensorNet Project at Oak Ridge National -Laboratory (ORNL), Oak Ridge, Tennessee, USA to provide help for their -instance of EJBCA. You are welcome to modify these pages for your own -use, but please remove any links to the SensorNetCA web pages so that we -do not get excess traffic. Please tell your users not to use the URLs in -the screen shots, and please credit Oak Ridge National Laboratory. ORNL -is operated by UT-Battelle for the U.S. Department Of Energy. - -

-

-

- - -

-

-

-
- - -

-

-

-
- - -

-

-

-
- -
- -
-

- PrimeKey has made a detailed guide how you set up and configure Windows and EJBCA for Windows SmartCard Logon. - The guide is divided in three section, introduction, Windows configuration and PKI configuration. - The reason for this division is that you can give the Windows guide to the windows administrator, who can easily - follow this guide on the Windows servers, while the PKI can be a hosted service or operated by another department. -

-

-

-

-

- The scripts and profiles can be fetched here. -

- -
- -
- - -

This article is written for an older version of EJBCA. Now there is a command to import a PKCS#12 file, also in the Admin-GUI under "Edit Certificate Authorities->Import CA keystore". -

The cli command to import a PKCS#12 file is now called bin/ejbca.sh ca importca .... -
The cli command to import user certificates is now called bin/ejbca.sh ca importcert .... -

- Read the howto at Csita. -

-
- - -

This document describes how to migrate an RSA Keon CA using nCipher HSM to EJBCA. - The migration guide goes through migrating the CA signing keys, importing the CAs to EJBCA and importing - issued certificates to EJBCA. The result is a setup in EJBCA that can continue operation transparently. -
- Download EJBCA migration guide (pdf). -

- -
- -
-
-

-You can enroll certificates for the iOS directly with EJBCA using SCEP. There is a SCEP profile in the iPhone that you can use for this. -PrimeKey has created a detailed howto if you need this type of support. It works according to the same principals as the examples below. -

-
- -
-

This howto is contributed by Bruno Bonfils.

-

- There is a Cisco emulator available. -

-

Here is the IOS config related to the CA: -

- -! -crypto ca trustpoint FMSCA -enrollment url http://your.ca.host.name:8080/ejbca/publicweb/apply/scep -serial-number -source interface Ethernet0 -auto-enroll regenerate -! - -

-

    -
  • The enrollment line tell how (the method, here an http url) to contact the PKI software. Note: you must omit the pkiclient.exe filename at the end which is automagically add by IOS.
  • -
  • The serial-number tells IOS to include the serial number in the request.
  • -
  • The name of the trustpoint you use MUST MATCH exactly the shortname of your CA in EJBCA (here FMSCA).
  • -
- Once you have that, use the command: -

- -# crypto ca authenticate FMSCA - -

- to fetch the CA certificate. -

-

- Then, login to EJBCA, and create a new entity profile that looks like: -

-

- End Entity profile for IOS -

-

- Then, do the password enrollment with the command: -

- -# crypto ca enroll FMSCA - -

- Check your ejbca logs, you shoud see something like: -

- -ERROR [PKCS10RequestMessage] No CN in DN: SN=12013150+unstructuredName=your.ciscobox.hosts.name -ERROR [Log4jLogDevice] October 19, 2005 9:48:33 AM CEST, CAId : 0, CA, EVENT_ERROR_USERAUTHENTICATION, Administrator : \ -PUBLICWEBUSER, IP Address : 192.168.134.1, User : 12013150, Certificate : No Certificate Involved, Comment : \ -Got request for nonexisting user: 12013150 - -

- So, you know you must add an entity using the serial number as username, the password you define in IOS, and serialNumber/unstructuredNamed as subject DN fields. -

-

- After adding the end entity, do the password enrollment again. If you see this you have enrolled succesfully: -

- -saroumane#sh crypto ca cert -Certificate - Status: Available - Certificate Serial Number: 426FA96340F5D2CA - Certificate Usage: General Purpose - Issuer: - c=FR - o=Fimasys - cn=Fimasys Security CA - Subject: - Name: your.ciscobox.hosts.name - Serial Number: 12013150 - serialNumber=12013150 - hostname=your.ciscobox.hosts.name - Validity Date: - start date: 08:58:28 CET Oct 19 2005 - end date: 09:08:28 CET Oct 19 2007 - Associated Trustpoints: FMSCA - -CA Certificate - Status: Available - Certificate Serial Number: 7AA2B9942CD0D362 - Certificate Usage: Signature - Issuer: - c=FR - o=Fimasys - cn=Fimasys Security CA - Subject: - c=FR - o=Fimasys - cn=Fimasys Security CA - Validity Date: - start date: 07:29:35 CET Oct 17 2005 - end date: 07:39:35 CET Oct 15 2015 - Associated Trustpoints: FMSCA - - - -

- There is a Cisco 7200 emulator called dynamips available - and a graphical front end GNS3. -

-

Below is a short run through how to configure and enroll directly with EJBCA using GNS3 on Ubuntu 8.10. -

- -sudo apt-get install gns3 uml-utilities bridge-utils - -

Now you have to configure the host and gns3 to be able to communicate with each other, so the router can connect to EJBCA on the host computer. - This is taken from http://www.blindhog.net/linux-bridging-for-gns3-lan-communications/". -

- -1. Create a tap interface - sudo tunctl -t tap0 -2. Remove ip addressing and set eth0 and tap0 to promiscuous mode - sudo ifconfig tap0 0.0.0.0 promisc up - sudo ifconfig eth0 0.0.0.0 promisc up -3. Create a new bridge interface - sudo brctl addbr br0 -4. Add tap0 and eth0 to the bridge group - sudo brctl addif br0 tap0 - sudo brctl addif br0 eth0 -5. Enable the bridge interface and give it an ip address - sudo ifconfig br0 up - sudo ifconfig br0 10.10.10.99/24 -6. Configure the default route - sudo route add default gw 10.10.10.254 - -

Now start gns3.

- -sudo gns3 - -

Configure with IOS image, for example c7200-jk9s-mz.124-13b.bin (an image with crypto commands), it's available on the net. - Also configure a simple topology: -

    -
  • drag cloud to topology window
  • -
  • drag c7200 to topology window
  • -
  • configure cloud and add tap0 interface
  • -
  • add manual link from cloud to c7200
  • -
  • start c7200
  • -
  • open console on c7200
  • -
  • enter configuration and configure FastEthernet0/0 with ip 10.10.10.98/255.255.255.0
  • -
- Now you should be able to ping the host computer, where EJBCA is running. - It is now time to do the actual enrollment as described above. Below are sample commands I have used. -

- -Router>enable -Router#configure terminal -Router(config)# -Router(config)#crypto ca trustpoint ScepCA - -Router(ca-trustpoint)#enrollment url http://10.10.10.99:8080/ejbca/publicweb/apply/scep -Router(ca-trustpoint)#serial-number -Router(ca-trustpoint)#ip-address none -Router(ca-trustpoint)#subject-name OU=Network Management, O=PrimeKey Solutions AB, C=SE -Router(ca-trustpoint)#revocation-check none -Router(ca-trustpoint)#exit - -Router(config)#crypto ca authenticate ScepCA -Router(config)#crypto ca enroll ScepCA - -

- You will see in the log what the username of the user you must create is called. - create end entity profile and user with DN containing SN=FFFFFF and unstructuredName=Router, as seen in the log file (FFFFFF and Router are the default values in the simulator). -

- -Router(config)#crypto ca enroll ScepCA -Router(config)#exit -Router#show crypto ca certificate - -

-You can always look at the defined trustpoints using the command: -

- -Router#show crypto ca trustpoints - -

-If you are enrolling towards an RA instead (see External RA documentation for information how to set up an external RA for SCEP) you issue the following commands: -

- -Router>enable -Router#configure terminal -Router(config)# -Router(config)#crypto ca trustpoint ScepRA - -Router(ca-trustpoint)#enrollment url http://10.10.10.99:8080/scepraserver/scep -Router(ca-trustpoint)#enrollment mode ra -Router(ca-trustpoint)#serial-number -Router(ca-trustpoint)#ip-address none -Router(ca-trustpoint)#subject-name OU=Network Management, O=PrimeKey Solutions AB, C=SE -Router(ca-trustpoint)#revocation-check none -Router(ca-trustpoint)#exit - -Router(config)#crypto ca authenticate ScepRA -Router(config)#crypto ca enroll ScepRA - -

-Note! This would only have a chance to work in EJBCA 3.8.1 and later, and actually it does not work due to the following -error in Cisco. If you have any ideas, please contact us. -

- -Router#debug crypto pki API -Router#debug crypto pki messages -Router#debug crypto pki server -Router#debug crypto pki transactions -Router#debug crypto pki validation - -... - -*Jan 16 21:47:32.546: CRYPTO_PKI: make trustedCerts list for ScepRA -*Jan 16 21:47:32.550: CRYPTO_PKI: subject="c=SE,o=Foo,cn=Scep RA" serial number= 3A 46 2F B4 5B AC 06 47 - -*Jan 16 21:47:32.554: CRYPTO_PKI: subject="c=SE,o=EJBCA Sample,cn=ScepCA" serial number= 19 A6 7D 78 AF 9D 3B 27 - -*Jan 16 21:47:32.566: E ../cert-c/source/p7digdat.c(377) : Error #703h -*Jan 16 21:47:32.566: E ../cert-c/source/p7spprt.c(589) : Error #703h -*Jan 16 21:47:32.582: pkcs7 verify data returned status 0x703 -*Jan 16 21:47:32.582: CRYPTO_PKI: status = 1795: failed to verify -*Jan 16 21:47:32.582: %PKI-6-CERTFAIL: Certificate enrollment failed. -*Jan 16 21:47:32.582: CRYPTO_PKI: All enrollment requests completed for trustpoint ScepRA. - - -
- -
- - -
-

Bruno Bonfils has written this excellent howto on using SSH with certificates from EJBCA:

-

- OpenSSH and X509 authentication. -

-

- Another interesting link is this one: -
- PKCS#11 support in OpenSSH. -

-
- -
-

EJBCA can issue certificates to be used when protecting sites using OpenSSO (Sun's Access Manager). - EJBCA will then be configured to publish issued certificates to the AM LDAP server. -

-

The configuration is really simple and after installing EJBCA consists of only these steps: -

    -
  • Create a Publisher, AMPublisher with the following properties: -
      -
    • Publisher Type: LDAP V3 Search Publisher
    • -
    • Base DN: The Base DN in the AM LDAP, for example dc=company,dc=com
    • -
    • Login parameters to the AM LDAP server
    • -
    • Create Nonexisting Users: false
    • -
    • Modify Existing Users: true
    • -
    • Add multiple certificates per user: false
    • -
    • Remove certificates when revoked: true
    • -
    • Remove ldap user when certificate revoked: false
    • -
    • LDAP location fields from cert DN: CN, Common Name (not really used)
    • -
    • Suffix base DN of the LDAP Search: same as Base DN, for example dc=company,dc=com
    • -
    • LDAP filter of the search: uid=$USERNAME
    • -
    -
  • -
  • Create a Certificate Profile, AMUser: -
      -
    • Use ENDUSER as template when creating the profile
    • -
    • Extended Key Usage: Client Authentication
    • -
    • Publishers: AMPublisher
    • -
    -
  • -
  • Create an End Entity Profile, AMUser: -
      -
    • Subject DN Fields: UID, CN, O, C is sufficient
    • -
    • Default Certificate Profile: AMUser
    • -
    • Available Certificate Profiles: AMUser
    • -
    -
  • -
- The procedure when adding a new user is now simple: -
    -
  • Create a new user in AM
  • -
  • Create a new user in EJBCA with the same username and UID as the username in AM
  • -
  • Get the certificate for the user, for example with the user's browser on the public web pages of EJBCA
  • -
- When the users certificate is created, the certificate is published to the AM LDAP server and certificate authentication can be configured and used in AM. -

- - -

- A really good article and description about EJBCA and OpenSSO is written by Bruno Bonfils. -

-

This paper also describes easy integration between EJBCA and OpenSSO, where EJBCA is used for user provisioning. -

-
-
- -
-

- This section will show you how to use an Apache Web Server Proxy in front of EJBCA. - The resulting server will -

-
    -
  • Display EJBCA public web at https://ca-server.company.local/
  • -
  • Redirect all HTTP-requests to HTTPS, except for OCSP and CRL.
  • -
  • Require a client SSL certificate when accessing https://ca-server.company.local/adminweb/
  • -
  • Be able to loadbalance requests
  • -
  • Still answer to requests on https://ca-server.company.local/ejbca/*
  • -
-

- This example was created on Ubuntu 64-bit Server 7.10 using the Apache Web Server 2.2 package, - but should be easy to adapt to any system able to run Apache. -

-

- Start by installing EJBCA as normal. If you intend to have the CA on the same machine as - the proxy you should modify $EJBCA_HOME/conf/web.properties to only listen to localhost -

- - httpsserver.bindaddress.pubhttp=127.0.0.1 - httpsserver.bindaddress.pubhttps=127.0.0.1 - httpsserver.bindaddress.privhttps=127.0.0.1 - -

- Install the Apache web server and enable required modules: -

- - $sudo su - #apt-get install apache2 - #cd /etc/apache2/mods-enabled/ - #ln -s ../mods-available/proxy.load proxy.load - #ln -s ../mods-available/proxy_http.load proxy_http.load - #ln -s ../mods-available/proxy_ajp.load proxy_ajp.load - #ln -s ../mods-available/proxy_balancer.load proxy_balancer.load - #ln -s ../mods-available/rewrite.load rewrite.load - #ln -s ../mods-available/ssl.load ssl.load - -

- Generate the SSL-certificate for Apache. This should be issued by the same CA that issued the Tomcat SSL - certificate (AdminCA1 in the default configuration). This can be done with the EJBCA CLI: -

- - $ cd $EJBCA_HOME - $ bin/ejbca.sh ra adduser apache-ssl foo123 "CN=ca-server.company.local,O=EJBCA Sample,C=SE" "" AdminCA1 "" 1 PEM SERVER - $ bin/ejbca.sh ra setclearpwd apache-ssl foo123 - $ bin/ejbca.sh batch - $ ls p12/pem/ca-server.company.local* - p12/pem/ca-server.company.local-CA.pem p12/pem/ca-server.company.local-Key.pem p12/pem/ca-server.company.local.pem - -

- Configure the default virtual host-file /etc/apache2/sites-enabled/000-default -

- - Note that this configuration with SSLVerifyClient inside a Location directtive is not safe with the newly (2009-11-15) discovered - vulnerability in SSL/TLS. You should only use SSLVerifyClient and SSLCipherSuite on whole virtualhosts. You can create the same effect - as below by using a separate subdomain for EJBCA administration (i.e. admin.ca.youdomain.com). -
See for example the Debian advisory. -
- -NameVirtualHost *:80 -<VirtualHost *:80> - DocumentRoot /var/www/ - - # Proxy requests to EJBCA instances (only one on local machine configured) - <Proxy balancer://mycluster-kerb> - BalancerMember ajp://localhost:8009/ejbca/ - </Proxy> - ProxyPass / balancer://mycluster-kerb/ - - RewriteEngine On - # Redirect all but the CRL Distribution Point, OCSP and Helthcheck to HTTPS - RewriteCond %{THE_REQUEST} !(/publicweb/webdist/certdist.*cmd=crl|/publicweb/status/) - RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R] - # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web. - RewriteCond %{THE_REQUEST} /ejbca/ - RewriteRule ^/ejbca/(.*)$ /$1 [PT] - - # Configure log - LogLevel warn - ErrorLog /var/log/apache2/error.log - CustomLog /var/log/apache2/access.log combined -</VirtualHost> - -NameVirtualHost *:443 -<VirtualHost *:443> - DocumentRoot /var/www/ - - RewriteEngine On - # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web. - RewriteCond %{THE_REQUEST} /ejbca/ - RewriteRule ^/ejbca/(.*)$ /$1 [PT] - - # Configure secure SSL for this server using SSL certificate generated by EJBCA - SSLEngine on - SSLCipherSuite HIGH - SSLProtocol all -SSLv2 - SSLCertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local.pem - SSLCertificateKeyFile /home/jboss/ejbca/p12/pem/ca-server.company.local-Key.pem - - # Require Client SSL certificate for the Admin GUI - <Location /adminweb> - SSLVerifyClient require - SSLVerifyDepth 1 - SSLCACertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local-CA.pem - </Location> - - # Proxy requests to EJBCA instances (only one on local machine configured) - <Proxy balancer://mycluster-kerb> - BalancerMember ajp://localhost:8009/ejbca/ - </Proxy> - ProxyPass / balancer://mycluster-kerb/ - - # Configure log - LogLevel warn - ErrorLog /var/log/apache2/error.log - CustomLog /var/log/apache2/access.log combined -</VirtualHost> - -

- Reload the apache configuration and verify that only port 80, 443 and other desired services - (e.g. a ssh-daemon) are listening on all or external interfaces -

- - $sudo /etc/init.d/apache2 reload - $sudo netstat -nap | grep LISTEN | grep -v 127.0.0.1 - tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 7612/apache2 - tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 7612/apache2 - tcp6 0 0 :::22 :::* LISTEN 3746/sshd - -

- Even though this looks secure, it is still a good idea to use a firewall as an extra layer of security (e.g. drop malformed packages and - prevent future services from being exploited). -

- - -

- A sample configuration how to fix up nice URLs for OCSP so that you can point your OCSP service locator to http://ocsp.company.com/ instead of http://ocsp.company.com:8080/ejbca/publicweb/status/ocsp - (some info left out for brevity). -

- -<VirtualHost ocsp.company.com:80> - <Proxy *> - Order deny,allow - Allow from all - </Proxy> - ProxyPass / http://127.0.0.1:8080/ejbca/publicweb/status/ocsp - ProxyPassReverse / http://127.0.0.1:8080/ejbca/publicweb/status/ocsp -</VirtualHost> - -

You can easily do the same for CRL distribution points. -

-
- -
- -
-

- Instead of using a proxy you can use mod_jk which uses a JK connector between apache and tomcat. I think this have some benefits. - You can easily combine it with mod_rewrite to have any type of external URLs, for OCSP, CRLs etc, and mapping them to other URLs in EJBCA. -

-

- This section will show you how to use an Apache with mod_jk in front of EJBCA. - The resulting server will -

-
    -
  • Display EJBCA public web at http://demo.primekey.se/
  • -
  • Require a client SSL certificate when accessing https://demo.primekey.se/, which works for the admin-GUI.
  • -
- mod_jk have many features and by using it you can virtually do anything you want with hosts, ports and URLs. -

- This example was created on Ubuntu 64-bit Server 8.10 using the Apache Web Server 2.2 package, - but should be easy to adapt to any system able to run Apache. -

- -# sudo apt-get install apache2 libapache2-mod-jk -# vim /etc/libapache2-mod-jk/workers.properties ------ -worker.list=jboss - -# Define a worker using ajp13 -worker.jboss.port=8009 -worker.jboss.host=127.0.0.1 -worker.jboss.type=ajp13 ------ - - -# vim /etc/apache2/sites-available/demo.primekey.se ------ -<VirtualHost demo.primekey.se:80> - # We must disable default charset or everything will be ISO-8859-1, - AddDefaultCharset off - ServerAdmin webmaster@primekey.se - ServerName demo.primekey.se - ServerAlias demo.primekey.se - - JkLogFile /var/log/apache2/mod_jk.log - JkLogLevel debug - - JkMount /* jboss - JkMount / jboss -</VirtualHost> - -<VirtualHost demo.primekey.se:443>> - # We must disable default charset or everything will be ISO-8859-1, - AddDefaultCharset off - ServerAdmin webmaster@primekey.se - ServerName demo.primekey.se - ServerAlias demo.primekey.se - - SSLEngine on - - JkLogFile /var/log/apache2/mod_jk.log - JkLogLevel debug - - JkMount /* jboss - JkMount / jboss - - # JkExtractSSL is On by default - # JkExtractSSL On -</VirtualHost> ------ - -Enable demo.primekey.se in /etc/apache2/sites-enabled - - -# vim /etc/apache2/mods-available/ssl.conf ------ -SSLVerifyClient require -SSLVerifyDepth 3 - -SSLCACertificateFile /etc/apache2/ssl/apache-CA.pem -SSLCertificateFile /etc/apache2/ssl/apache.pem - -SSLOptions +StdEnvVars +ExportCertData ------ - - - -# vim /etc/apache2/mods-available/jk.load ------ -LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so -JkWorkersFile /etc/libapache2-mod-jk/workers.properties ------ - - -

- Now enable ssl.load and ssl.conf in /etc/apache2/mods-enabled. -

-

Finally restart apache and go to http://demo.primekey.se/ (or https). Same security considerations as for using proxy applies.

-

- If you are using the external OCSP responder then you also got to ensure you got this line in the file apache2.conf: -

KeepAlive Off

- If not apache will hang. -

-

- Also an external OCSP responder it could be good to add these lines to the 'Virtual Host' configuration: -

- RewriteEngine on - RewriteRule .* /ejbca/publicweb/status/ocsp [PT] - - JkMount /ejbca/publicweb/status/ocsp/* ocsp_worker - JkMount /ejbca/publicweb/status/ocsp ocsp_worker -

- By doing this you don't have to bother about typing the last part of the URL. Just right server name will do. -

-
- -
-

- This section will show you how to set up automatic certificate enroll of - machines and users in an Windows environment with EJBCA. -

- General idea -

-
    -
  • Use mod_auth_kerb on a Apache2 web server proxy to validate the requesters identity using Kerberos.
  • -
  • A login VBS-Script creates a certificate request that is sent to the proxy using IE-components.
  • -
  • A Servlet protected by the proxy receives the requests and creates a new cert.
  • -
  • The new certificate will use information from the request (UPN and CertificateTemplate) and read.
  • -
  • information from active directory (CN,DC etc).
  • -
  • Autoenrollment should be configurable in the Admin GUI.
  • -
- -

- Current status -

-
    -
  • Machine enroll on Domain Controller: WORKING
  • -
  • DomainController enroll on Domain Controller: WORKING
  • -
  • User enroll (Administrator) on Domain Controller: NOT WORKING (Does not trusts ca-server as Intranet, despite GP)
  • -
  • Machine enroll on other WS2K3 client: WORKING (not checked in a while)
  • -
  • User enroll (Administrator) on other WS2K3 client: NOT WORKING (Does not trusts ca-server as Intranet, despite GP, also complains about untrusted VBS if ran manually)
  • -
  • Machine enroll on WinXP client: WORKING
  • -
  • User enroll (Administrator) on WinXP client: WORKING
  • -
-

- Known issues -

-
    -
  • SECURITY: The Servlet should verify that e.g. only Users can request User certificates, DCs only DC certs etc.. and other permissions if possible.
  • -
  • The enroll scripts always fetches new certificates. They should use the command=status first to see if a new cert is needed.
  • -
  • AdminWeb cannot verify admin certificates if non-"/ejbca/" path is used in URL.
  • -
  • Autoenroll Servlet doesn't get X-Remote-User if "/ejbca/" path is used in URL.
  • -
  • Order of Subject DNs is wrong compared with MS certs..
  • -
  • SSL connection to AD has not been tested.
  • -
  • Certificates don't have the CertificateTemplate attrib yet.. looks nicer in Certificate MMC snapin..
  • -
  • JavaScript "onchange" behaves strangely in IE6. Only activated when the table is clicked, not the checkbox..
  • -
  • Creation of EEPs is inefficient due to attempted removal of EEP before each new request.. (Debug-code)
  • -
-

- ... -

-
- -

- Domain Controller: dc1.company.local -

-
    -
  • Windows Server 2003 EE patched to SP2
  • -
  • Active Directory
  • -
  • DNS Server
  • -
-

- CA Server: ca-server.company.local -

-
    -
  • Ubuntu 64 Server 7.10
  • -
  • Apache2 with modules
  • -
  • Kerberos 5
  • -
  • Java 1.6u4
  • -
  • JBoss 4.2.2.GA
  • -
  • EJBCA 3.6 Alpha
  • -
  • Apache Ant 1.7.0
  • -
-

- Desktop client: client-01.company.local -

-
    -
  • Windows XP Pro SP1 patched to SP2
  • -
-
- -

- Configure EJBCA not to respond to external web-requests by editing $EJBCA_HOME/conf/web.properties -

- -... -httpsserver.bindaddress.pubhttp=127.0.0.1 -httpsserver.bindaddress.pubhttps=127.0.0.1 -httpsserver.bindaddress.privhttps=127.0.0.1 -... - -

- After installation, go to EJBCA Admin GUI -> System Configuration and - configure the autoenrollment settings. -

-
- -

- This could probably be done on a Windows server as well, since Apache - and Kerberos is supposed to work on that platform too.. -

- -$sudo su -#apt-get update -#apt-get install krb5-user apache2 libapache2-mod-auth-kerb - ** Skip kerberos config.. we will configure this later ** -#cd /etc/apache2/mods-enabled/ -#ln -s ../mods-available/proxy.load proxy.load -#ln -s ../mods-available/proxy_ajp.load proxy_ajp.load -#ln -s ../mods-available/proxy_balancer.load proxy_balancer.load -#ln -s ../mods-available/rewrite.load rewrite.load -#ln -s ../mods-available/ssl.load ssl.load -#ln -s ../mods-available/headers.load headers.load - -

- Edit /etc/krb5.conf where dc1.company.local is the DNS-name of the Domain Controller and COMPANY.LOCAL is our domain. -

- -[libdefaults] -default_realm = COMPANY.LOCAL - -[realms] -COMPANY.LOCAL = { - kdc = dc1.company.local:88 - admin_server = dc1.company.local:88 -} - -[domain_realm] - .company.local = COMPANY.LOCAL - company.local = COMPANY.LOCAL - -[logging] -default = FILE:/var/log/apache2/krb5.log - -

- Edit /etc/network/interfaces and set a static IP address -

- -... -#iface eth0 inet dhcp -iface eth0 inet static - address 192.168.0.102 # Address of this machine - netmask 255.255.255.0 - gateway 192.168.0.101 # In our local network this is the Domain Controller - -

- Use the DC as DNS server in /etc/resolv.conf -

- -search localdomain -nameserver 192.168.0.101 - -

- and restart networking (sudo /etc/init.d/networking restart). -

-

- Add "ntdpdate dc1.company.local" to /etc/rc.local or a cron job to make sure the - ca-server is syncronized with the Domain Controller. -

-

- Create the SSL certificates for the Apache proxy using the same CA as our EJBCA installation and the same subject DN. -

- -$cd $EJBCA_HOME -$bin/ejbca.sh ra adduser apache-ssl foo123 "CN=ca-server.company.local,O=EJBCA Sample,C=SE" "" AdminCA1 "" 1 PEM SERVER -$bin/ejbca.sh ra setclearpwd apache-ssl foo123 -$bin/ejbca.sh batch -$ls p12/pem/ca-server.company.local* -p12/pem/ca-server.company.local-CA.pem p12/pem/ca-server.company.local-Key.pem p12/pem/ca-server.company.local.pem - -

- Edit /etc/apache2/sites-enabled/000-default to display an apache proxy front for EJBCA -

- -NameVirtualHost *:80 -<VirtualHost *:80> - DocumentRoot /var/www/ - - # Proxy requests to EJBCA instances (only one on local machine configured) - <Proxy balancer://mycluster-kerb> - BalancerMember ajp://localhost:8009/ejbca/ - </Proxy> - ProxyPass / balancer://mycluster-kerb/ - - RewriteEngine On - # Redirect all but the CRL Distribution Point, OCSP and Helthcheck to HTTPS - RewriteCond %{THE_REQUEST} !(/publicweb/webdist/certdist.*cmd=crl|/publicweb/status/) - RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R] - # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web. - RewriteCond %{THE_REQUEST} /ejbca/ - RewriteRule ^/ejbca/(.*)$ /$1 [PT] - - # Configure log - LogLevel warn - ErrorLog /var/log/apache2/error.log - CustomLog /var/log/apache2/access.log combined -</VirtualHost> - -NameVirtualHost *:443 -<VirtualHost *:443> - DocumentRoot /var/www/ - - RewriteEngine On - # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web. - RewriteCond %{THE_REQUEST} /ejbca/ - RewriteRule ^/ejbca/(.*)$ /$1 [PT] - - # Configure secure SSL for this server using SSL certificate generated by EJBCA - SSLEngine on - SSLCipherSuite HIGH - SSLProtocol all -SSLv2 - SSLCertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local.pem - SSLCertificateKeyFile /home/jboss/ejbca/p12/pem/ca-server.company.local-Key.pem - - # Require Client SSL certificate for the Admin GUI - <Location /adminweb> - SSLVerifyClient require - SSLVerifyDepth 1 - SSLCACertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local-CA.pem - </Location> - - # Require Kerberos authentication for the Autoenroll Servlet - <Location /autoenroll> - AuthType Kerberos - Krb5Keytab /etc/apache2/http.keytab - KrbAuthRealms COMPANY.LOCAL - KrbServiceName HTTP - KrbMethodNegotiate on - KrbMethodK5Passwd off - Require valid-user - </Location> - - # Forward the UPN as variable X-Remote-User - RewriteCond %{IS_SUBREQ} ^false$ - RewriteCond %{LA-U:REMOTE_USER} (.+) - RewriteRule .* - [E=RU:%1] - RequestHeader set X-Remote-User %{RU}e - - # Proxy requests to EJBCA instances (only one on local machine configured) - <Proxy balancer://mycluster-kerb> - BalancerMember ajp://localhost:8009/ejbca/ - </Proxy> - ProxyPass / balancer://mycluster-kerb/ - - # Configure log - LogLevel warn - ErrorLog /var/log/apache2/error.log - CustomLog /var/log/apache2/access.log combined -</VirtualHost> - -

- Restart apache with "sudo /etc/init.d/apache2 restart" -

-

- Install Windows support tools on the Domain Controller (found in %WIN2k3CD%\SUPPORT\TOOLS\SUPTOOLS.msi) to get ktpass.exe. - Create a new user "ca-server@company.local" and a strong password e.g not FooBar123 used here. - Create a keytab-file "http.keytab" on the Domain Controller: -

- -ktpass.exe -princ HTTP/ca-server.company.local@COMPANY.LOCAL -mapuser ca-server -crypto DES-CBC-MD5 -ptype KRB5_NT_PRINCIPAL -mapop set +desonly -pass FooBar123 -out http.keytab - ... - keysize 55 HTTP/ca-server.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype - 0x3 (DES-CBC-MD5) keylength 8 (0x64614c9d256bcd6d) - ... - -

- And move the file to ca-server.company.local:/etc/apache2/http.keytab change permissions to be - readable only by the apache-process. -

- -$chown root:root /etc/apace2/http.keytab - -

- Verify that the keytab is correct: -

- -$kinit Administrator -$kvno HTTP/ca-server.company.local -$klist -e -** Output here should match the one from ktpass.exe ** - -

- Verify that the keytab can be used: -

- -$kdestroy -$sudo kinit -k -t /etc/apache2/http.keytab HTTP/ca-server.company.local -$sudo klist -(You should have received a ticket here if everything is working.) -$sudo kdestroy - -

- Add ca-server.company.local (192.168.1.2) to your Domain Controllers DNS server as a "Host (A)" record. -

-
- -

- Create a Shared directory on the Domain Controller, C:\Shared with read and exec rights by Everyone -

- -copy %SYSTEMROOT%\system32\certreq.exe C:\Shared\Autoenroll\ -copy %SYSTEMROOT%\system32\certcli.dll C:\Shared\Autoenroll\ -copy %SYSTEMROOT%\system32\certadm.dll C:\Shared\Autoenroll\ -(copy %SYSTEMROOT%\system32\certutil.exe C:\Shared\Autoenroll\ This is used by EnrollDomainController and is already available at all DCs.) - -

- Edit or create C:\Shared\Autoenroll\autoenroll.conf -

- -# This is a primitive config file that does not allow spaces - -# The request URL is built from the following properties -# https://[requestpath]?request=... -# - -# Standard SSL-port and using URL rewrite from /ejbca/* to /* -requestpath=ca-server.company.local/autoenroll - -# Non-standard SSL-port and not using URL rewrite -#requestpath=ca-server.company.local:4443/ejbca/autoenroll - -# Debug setting, use only for manual testing -#debug=true -debug=false - -

- Edit or create C:\Shared\Autoenroll\RequestAndInstall.vbs -

- - Set oArgs = WScript.Arguments - if oArgs.Count < 1 then - WScript.Echo "Usage: thisscript.vbs fullpathnameofrequest.inf" - WScript.Quit 1 - else - sRequestInfo = Trim(oArgs(0)) - end if - - Set WS = CreateObject("WScript.Shell") - - sRequest = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.req" - sResult = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.p7b" - - Set oFilesystem = CreateObject("Scripting.FileSystemObject") - On Error Resume Next ' Ignore if we try to delete a file that does not exist - oFilesystem.DeleteFile(sRequest) - Err.Clear - On Error GoTo 0 - sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\" - - Set iFile = oFilesystem.OpenTextFile(sSharedDir & "autoenroll.conf") - Do While iFile.AtEndOfStream <> True - sLine = iFile.Readline - If InStr(Left(sLine,1), "#") = 0 then - If InStr(sLine, "requestpath=") <> 0 then - sRequestPath = Trim(Right(sLine, Len(sLine)-Len("requestpath="))) - end if - If InStr(sLine, "debug=") <> 0 then - sDebug = Trim(Right(sLine, Len(sLine)-Len("debug="))) - end if - End if - Loop - iFile.Close - - WS.Run sSharedDir & "certreq.exe -f -new " & sRequestInfo & " " & sRequest, 0, True - - sRequestData = "" - Set objFile = oFilesystem.OpenTextFile(sRequest, 1) - Do Until objFile.AtEndOfStream - sRequestData = sRequestData & objFile.ReadLine - Loop - objFile.Close - - set oIE = CreateObject("InternetExplorer.Application") - - oIE.navigate2("https://" & sRequestPath & "?debug=" & sDebug & "&request=" & sRequestData) - - If sDebug = "true" Then - oIE.visible = true - End If - - 'Wait max 30 seconds - wscript.sleep 1000 - counter = 0 - While oIE.Busy = true And counter < 30 - counter = counter + 1 - wscript.sleep 1000 - Wend - - sResultData = oIE.Document.Body.innerHTML - sResultData = Mid(sResultData, 6, Len(sResultData)-11) - - Set oFile = oFilesystem.CreateTextFile(sResult, True) - oFile.WriteLine sResultData - oFile.Close - - on error resume next ' in case the Task Manager is used to close IE. - If sDebug <> "true" Then - oIE.quit ' Close the window - WS.Run sSharedDir & "certreq.exe -accept " & Chr(34) & sResult & Chr(34), 0, True - End If - -

- Edit or create C:\Shared\Autoenroll\EnrollDomainController.vbs -

- - ' This Script is based on the script found at http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/security/advcert.mspx#EURAE - - iRole = GetLastDomainRole() - If iRole <> 4 And iRole <> 5 Then - WScript.Echo "This script should only run on a Domain Controller." - WScript.Quit 1 - End If - - Set WS = CreateObject("WScript.Shell") - - Set objDC = GetObject("LDAP://" & CreateObject("ADSystemInfo").ComputerName) - sGUID = objDC.GUID - sDNShostname = objDC.DNShostname - - Set oFilesystem = CreateObject("Scripting.FileSystemObject") - sTempfilePrefix = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled" - sRequestInfo = sTempFilePrefix & ".inf" - sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\" - - 'Create b64 encoded extension - Dim aASNsubstring(2, 5) - Const HEX_DATA_LENGTH = 1 - Const ASCIIDATA = 2 - Const HEXDATA = 3 - Const HEX_BLOB_LENGTH = 4 - Const HEX_TYPE = 5 - ' Encode DNS - aASNsubstring(0, ASCIIDATA) = sDNShostname - aASNsubstring(0, HEX_TYPE) = "82" - For i = 1 to Len(aASNsubstring(0, ASCIIDATA)) - aASNsubstring(0, HEXDATA) = aASNsubstring(0, HEXDATA) & Hex(Asc(Mid(aASNsubstring(0, ASCIIDATA), i, 1))) - Next - aASNsubstring(0, HEX_DATA_LENGTH) = ComputeASN1 (Len(aASNsubstring(0, HEXDATA)) / 2) - sASN = aASNsubstring(0, HEX_TYPE) & aASNsubstring(0, HEX_DATA_LENGTH) & aASNsubstring(0, HEXDATA) - ' Encode GUID - aASNsubstring(1, HEXDATA) = sGUID - aASNsubstring(1, HEX_TYPE) = "A0" - aASNsubstring(1, HEX_DATA_LENGTH) = ComputeASN1 (Len(aASNsubstring(1, HEXDATA)) / 2) - sASN = sASN & "A01F06092B0601040182371901" & aASNsubstring(1, HEX_TYPE) & "120410" & aASNsubstring(1, HEXDATA) - - Set oFile = oFilesystem.CreateTextFile(sTempfilePrefix & ".asn") - oFile.WriteLine "30" & ComputeASN1 (Len(sASN) / 2) & sASN - oFile.Close - WS.Run "certutil -f -decodehex " & sTempfilePrefix & ".asn " & sTempfilePrefix & ".bin", 0, True - WS.Run "certutil -f -encode " & sTempfilePrefix & ".bin " & sTempfilePrefix & ".b64", 0, True - - Set iFile = oFilesystem.OpenTextFile(sTempfilePrefix & ".b64") - Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True) - oFile.WriteLine "[Version]" - oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) - oFile.WriteLine "" - oFile.WriteLine "[NewRequest]" - oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34) - oFile.WriteLine "KeySpec = 1" - oFile.WriteLine "KeyLength = 2048" - oFile.WriteLine "Exportable = TRUE" - oFile.WriteLine "MachineKeySet = TRUE" - oFile.WriteLine "SMIME = FALSE" - oFile.WriteLine "PrivateKeyArchive = FALSE" - oFile.WriteLine "UserProtected = FALSE" - oFile.WriteLine "UseExistingKeySet = FALSE" - oFile.WriteLine "ProviderName = " & Chr(34) & "Microsoft RSA SChannel Cryptographic Provider" & Chr(34) - oFile.WriteLine "ProviderType = 12" - oFile.WriteLine "RequestType = PKCS10" - oFile.WriteLine "KeyUsage = 0xa0" - oFile.WriteLine "" - oFile.WriteLine "[EnhancedKeyUsageExtension]" - oFile.WriteLine "OID=1.3.6.1.5.5.7.3.1" - oFile.WriteLine "OID=1.3.6.1.5.5.7.3.2" - oFile.WriteLine "" - oFile.WriteLine "[Extensions]" - iLine = 0 - Do While iFile.AtEndOfStream <> True - sLine = iFile.Readline - If sLine = "-----END CERTIFICATE-----" then - Exit Do - end if - if sLine <> "-----BEGIN CERTIFICATE-----" then - if iLine = 0 then - oFile.WriteLine "2.5.29.17=" & sLine - else - oFile.WriteLine "_continue_=" & sLine - end if - iLine = iLine + 1 - end if - Loop - oFile.WriteLine "Critical=2.5.29.17" - oFile.WriteLine "" - oFile.WriteLine "[RequestAttributes]" - oFile.WriteLine "CertificateTemplate = DomainController" - oFile.Close - iFile.Close - - WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True - - ' Sub - Function ComputeASN1 (iStrLen) - If Len(Hex(iStrLen)) Mod 2 = 0 then - sLength = Hex(iStrLen) - else - sLength = "0" & Hex(iStrLen) - end if - if iStrLen > 127 then - ComputeASN1 = Hex (128 + (Len(sLength) / 2)) & sLength - else - ComputeASN1 = sLength - End If - End Function - - 'Return the domain role number where: - '-1 Error - '0 Standalone Workstation - '1 Member Workstation - '2 Standalone Server - '3 Member Server - '4 Backup Domain Controller - '5 Primary Domain Controller - Function GetLastDomainRole () - On Error Resume Next - strComputer = "." - Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") - Set colItems = objWMIService.ExecQuery("Select DomainRole from Win32_ComputerSystem",,48) - For Each objItem in colItems - iReturn = objItem.DomainRole - Next - On Error Goto 0 - GetLastDomainRole = iReturn - End Function - -

- Edit or create C:\Shared\Autoenroll\EnrollMachine.vbs -

- - Set WS = CreateObject("WScript.Shell") - Set oFilesystem = CreateObject("Scripting.FileSystemObject") - sRequestInfo = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.inf" - Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True) - oFile.WriteLine "[Version]" - oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) - oFile.WriteLine "" - oFile.WriteLine "[NewRequest]" - oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34) - oFile.WriteLine "KeyLength = 2048" - oFile.WriteLine "MachineKeySet = TRUE" - oFile.WriteLine "RequestType = PKCS10" - oFile.WriteLine "" - oFile.WriteLine "[RequestAttributes]" - oFile.WriteLine "CertificateTemplate = Machine" - oFile.Close - - sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\" - WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True - -

- Edit or create C:\Shared\Autoenroll\EnrollUser.vbs -

- - Set WS = CreateObject("WScript.Shell") - Set oFilesystem = CreateObject("Scripting.FileSystemObject") - sRequestInfo = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.inf" - Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True) - oFile.WriteLine "[Version]" - oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) - oFile.WriteLine "" - oFile.WriteLine "[NewRequest]" - oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34) - oFile.WriteLine "KeyLength = 2048" - oFile.WriteLine "RequestType = PKCS10" - oFile.WriteLine "" - oFile.WriteLine "[RequestAttributes]" - oFile.WriteLine "CertificateTemplate = User" - oFile.Close - - sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\" - WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True - -

- Verify that all the file in Shared\Autoenroll directory has read end exec right for Everyone. -

- Install Certificate Templates by adding the corresponding Snap-in i the MMC console. -

- Install the root CA-certificate(s) in the NTAuthStore, so windows can verify all cerificates produced by EJBCA. - Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> - Edit Default Domain Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Public Key Policies -> - Trusted Root Certificate Authorities -> Import -> import the root ca certificate and run "gpupdate /force" on - machines that are used for testing. - (You can fetch the CA certificate using the EJCBA CLI with "$EJBCA_HOME/bin/ejbca.sh ca getrootcert AdminCA1 ~/AdminCA1.crt -der".) -

- Add Startup Scripts in - Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> - Edit Default Domain Policy -> Computer Configuration -> Windows Settings -> Scripts -> Startup -> - Add the machine-related scripts from the shared directory. -

- Add Login Scripts in - Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> - Edit Default Domain Policy -> User Configuration -> Windows Settings -> Scripts -> Logon -> - Add the user-related scripts from the shared directory. -

- Add the ca-server and shared directory to the Intranet - Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> - Edit Default Domain Policy -> Computer Configuration | User Configuration (do both!!) -> Administrative Templates -> - Windows Components -> Internet Explorer -> Internet Control Page -> Security Page -> - Site to Zone assignement list -> Enabled and added "https://ca-server.company.local" to zone "1", "\\Dc1\Shared" to zone "1" -

- Configure clients to synchronize time using NTP: - Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> - Edit Default Domain Policy -> Computer Configuration -> Administrative Templates -> - System -> Windows Time Service -> Time Providers -> Configure Windows NTP Client (Add "dc1.company.local" as an NTP server.) - and Enable Windows NTP Client. -

- Use "gpupdate /force" on clients before running tests or wait 8h.. =) -

-
- -

- Well, good luck with Windows error messages.. but you can enable debug - ("debug=true" in autoenroll.conf) to see the response from the Servlet. -

- Test the machine-cert-retreival script by starting a Console as "LocalSystem". C:\Shared\Autoenroll\ConsoleAsLocalSystem.vbs: -

- - Set WS = CreateObject("WScript.Shell") - WS.Run "sc.exe delete lsc", 0, True - WS.Run "sc.exe create lsc binpath= " & Chr(34) & "cmd /K start" & Chr(34) & " type= own type= interact", 0, True - WS.Run "sc.exe start lsc", 0, True - -

- Test the machine-cert-retreival script by starting a Console as "LocalSystem". C:\Shared\ConsoleAsLocalSystem.vbs: -

- - Set WS = CreateObject("WScript.Shell") - WS.Run "sc.exe delete lsc", 0, True - WS.Run "sc.exe create lsc binpath= " & Chr(34) & "cmd /K start" & Chr(34) & " type= own type= interact", 0, True - WS.Run "sc.exe start lsc", 0, True - -

- Adding a custom Administrative template can be done as in this example if needed: - Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> - Edit Default Domain Policy -> Computer Configuration -> Administrative Templates -> Add/Remove Templates -> Add Autoenroll.adm -

-

- This is just a sample, but shows how a custom GP can be configured.. (Use the intructions above instead of this template. - The example Administrative Template "Autoenroll Related" can be used to force ca-server.company.local - into the Intranet zone or add a NTP syncronizing policy. C:\Shared\Autoenroll\Autoenroll.adm: -

- -CLASS MACHINE - -CATEGORY "Autoenroll Related" - CATEGORY "NTP Synch for clients with AD" - POLICY "Enable NTP synch" - SUPPORTED "This is a hack to get WinXP clients working" - EXPLAIN ".." - KEYNAME "Software\Policies\Microsoft\W32Time\TimeProviders" - VALUENAME "NtpServer" - VALUEON NUMERIC 1 - VALUEOFF NUMERIC 0 - - ACTIONLISTON - KEYNAME "Software\Policies\Microsoft\W32Time\Parameters" - VALUENAME "Type" - VALUE "NTP" - - KEYNAME "Software\Policies\Microsoft\W32Time\Config" - VALUENAME "AnnounceFlags" - VALUE NUMERIC 5 - - KEYNAME "Software\Policies\Microsoft\W32Time\Config" - VALUENAME "MaxPosPhaseCorrection" - VALUE NUMERIC 1099511627775 - - KEYNAME "Software\Policies\Microsoft\W32Time\Config" - VALUENAME "MaxNegPhaseCorrection" - VALUE NUMERIC 1099511627775 - END ACTIONLISTON - - PART "NTP Servers in the form ntp.server1.com,0x1 ntp.server2.com,0x1 ntp.server3.com,0x1" EDITTEXT - KEYNAME "Software\Policies\Microsoft\W32Time\Parameters" - VALUENAME "NtpServer" - MAXLEN 4096 - END PART - - PART "Poll interval in seconds" NUMERIC - KEYNAME "Software\Policies\Microsoft\W32Time\TimeProviders\NtpClient" - VALUENAME "SpecialPollInterval" - DEFAULT 900 - END PART - END POLICY - END CATEGORY - - CATEGORY "Required trust" - POLICY "Trust ca-server.company.local" - SUPPORTED "Might need IE6 for this to work.." - EXPLAIN "This adds the ca-server.company.local to the list of intranet-sites.." - KEYNAME "Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\company.local\ca-server" - VALUENAME "https" - VALUEON NUMERIC 1 - VALUEOFF NUMERIC 0 - END POLICY - END CATEGORY -END CATEGORY - -CLASS USER - -CATEGORY "Autoenroll Related" - CATEGORY "Required trust" - POLICY "Trust ca-server.company.local" - SUPPORTED "Might need IE6 for this to work.." - EXPLAIN "This adds the ca-server.company.local to the list of intranet-sites.." - KEYNAME "Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\company.local\ca-server" - VALUENAME "https" - VALUEON NUMERIC 1 - VALUEOFF NUMERIC 0 - END POLICY - END CATEGORY -END CATEGORY - -

- Useful reg-for VMwares with runaway clocks if GP mod didn't work or you just want to modify a single client. -

- -Windows Registry Editor Version 5.00 - -[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config] -"AnnounceFlags"=dword:00000005 -"MaxPosPhaseCorrection"=dword:ffffffff -"MaxNegPhaseCorrection"=dword:ffffffff - -[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters] -"Type"="NTP" -"NtpServer"="dc1.company.local,0x1" - -[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters\NtpServer] -"NtpServer"="dc1.company.local,0x1" - -[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient] -"SpecialPollInterval"=dword:00000030 - -[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer] -"Enabled"=dword:00000001 - -
- - -

Other auto enroll references

- -
-
- -
-

- This is a very thorough guide with screen-shots of how to setup EJBCA 3.6.0 - with GemSAFE Toolbox in a windows environment for smartcard logon, email signing, - email encryption and SSL services. -

-

- The guide is divided into three PDF-files: -

-

-
- -
-

- A fully working RA Admin sample program, written using Java and EJBCA web services, may be downloaded from - the WebServiceRA project on SourceForge. -

-

- This Java program provides a simple UI for creating and querying end entities. - All communications with the appserver are via EJBCA web services. -

-

- It includes wizard dialogs that prompt the user for the type of certificate to create, that prompt the user to enter values that define the subject DN, - that allow the user to receive an email notification containing the password for the new end entity, - that allow the user to choose between adding the new end entity to the EJBCA database and actually generating the certificate (as a P12 or JKS file). -

-

- Further information on this application can be found in the project's README.txt (building and running the application), - its troubleshooting.txt (further tips on running the application), and todo.txt (notes and issues for developers). -

-

- A short movie demonstrating the program may be downloaded from - SourceForge - or - YouTube. -

-
- -
-

Bruno Bonfils have written some documentation in french

-
- -
- diff -urN ../ejbca_4_0_6/doc/xdocs/index.xml ./doc/xdocs/index.xml --- ../ejbca_4_0_6/doc/xdocs/index.xml 2011-11-18 12:33:18.000000000 +0100 +++ ./doc/xdocs/index.xml 2011-12-25 12:00:02.000000000 +0100 @@ -8,7 +8,7 @@
-

2011-11-02: EJBCA 4.0.5 and cert-cvc 1.2.13 with EAC ePassport support is now out! +

2011-12-25: EJBCA 4.0.7 is now out!
Visit the download section. There is also a LiveCD!

@@ -18,10 +18,11 @@
The library is freely usable under the LGPL 2.1 (or later) license for all parties interesting in handling CVC certificates, in particular for EU EAC ePassports. - The cert-cvc library was donated to the open source by the Swedish National Police Board. + The cert-cvc library was donated to the open source by the Swedish National Police Board. + The current version is cert-cvc 1.2.13, with full EAC ePassport support. - Did you know that EJBCA includes a stand-alone OCSP responder? The responder is scalable with high-performance and can be used + Did you know that EJBCA includes a stand-alone Validation Authority, including an OCSP responder? The responder is scalable with high-performance and can be used also with any other CA than EJBCA. diff -urN ../ejbca_4_0_6/doc/xdocs/stylesheets/project.xml ./doc/xdocs/stylesheets/project.xml --- ../ejbca_4_0_6/doc/xdocs/stylesheets/project.xml 2011-11-18 12:33:18.000000000 +0100 +++ ./doc/xdocs/stylesheets/project.xml 2011-12-25 12:00:02.000000000 +0100 @@ -46,7 +46,7 @@ - + diff -urN ../ejbca_4_0_6/modules/admin-gui/resources/ca/editcertificateprofiles/certificateprofilepage.jspf ./modules/admin-gui/resources/ca/editcertificateprofiles/certificateprofilepage.jspf --- ../ejbca_4_0_6/modules/admin-gui/resources/ca/editcertificateprofiles/certificateprofilepage.jspf 2011-11-18 12:33:36.000000000 +0100 +++ ./modules/admin-gui/resources/ca/editcertificateprofiles/certificateprofilepage.jspf 2011-12-25 12:00:32.000000000 +0100 @@ -438,8 +438,8 @@
-

<%= ejbcawebbean.getText("EDITCERTIFICATEPROFILE") %>

-

<%= ejbcawebbean.getText("CERTIFICATEPROFILE")+ " : " + certprofile %>

+

" />

+

" />

@@ -452,17 +452,17 @@ - <%= ejbcawebbean.getText("BACKTOCERTIFICATEPROFILES") %> + " /> + " /> --> - <%= ejbcawebbean.getText("CERTIFICATEPROFILEID") %> + " /> <%= cabean.getCertificateProfileId(certprofile) %> @@ -470,7 +470,7 @@ - <%= ejbcawebbean.getText("TYPE") %> + " /> @@ -489,7 +489,7 @@ - <%= ejbcawebbean.getText("AVAILABLEBITLENGTHS") %> + " /> @@ -509,12 +509,12 @@ - <%= ejbcawebbean.getText("SIGNATUREALGORITHM") %> + " /> <% String signAlg = certificateprofiledata.getSignatureAlgorithm(); %>
- <%= ejbcawebbean.getText("DATE_INFO") %> <%= ejbcawebbean.getDateExample() %> + " /> - + <%-- Authorizations --%> - <%= ejbcawebbean.getText("PERMISSIONS") %> + " />   @@ -549,7 +549,7 @@ - <%= ejbcawebbean.getText("ALLOWVALIDITYOVERRIDE") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Validity") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Validity") %> - <%= ejbcawebbean.getText("ALLOWEXTENSIONOVERRIDE") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Allow%20extension%20override") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Allow%20extension%20override") %> - <%= ejbcawebbean.getText("ALLOWCERTSERIALNUMBEROVERRIDE") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Allow%20certificate%20serial%20number%20override") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Allow%20certificate%20serial%20number%20override") %> <% if ( cabean.isUniqueIndexForSerialNumber() ) { %> @@ -583,14 +583,14 @@ } %>> <%} else {%> - <%= ejbcawebbean.getText("CERTSERIALNOUNIQUEIX") %> + " /> <%}%> - <%= ejbcawebbean.getText("ALLOWDNOVERRIDE") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Allow%20subject%20DN%20override") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Allow%20subject%20DN%20override") %> - <%= ejbcawebbean.getText("ALLOWKEYUSAGEOVERRIDE") %> + " /> - <%= ejbcawebbean.getText("X509EXTENSIONS") %> + " />   @@ -628,8 +628,8 @@ <%-- Basic Constraints extension --%> - <%= ejbcawebbean.getText("EXT_PKIX_BASICCONSTRAINTS") %>
- <%= ejbcawebbean.getText("BASICCONSTRAINTSCRITICAL") %> + " />
+ " /> - <%= ejbcawebbean.getText("EXT_PKIX_BC_PATHLENGTH") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Path%20Length%20Constraints") %>
- <%= ejbcawebbean.getText("PATHLENGTHCONSTRAINT") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Path%20Length%20Constraints") %>
+ " /> <% boolean enablepathlenconstraint = certificateprofiledata.getUseBasicConstraints() && (certificateprofiledata.getType() == SecConst.CERTTYPE_SUBCA ||certificateprofiledata.getType() == SecConst.CERTTYPE_ROOTCA); %> @@ -669,8 +669,8 @@ <%-- Authority Key Identifier (AKI) extension --%> - <%= ejbcawebbean.getText("EXT_PKIX_AUTHORITYKEYID") %> + " /> + " /> + " /> --> @@ -382,7 +382,7 @@   - <%= ejbcawebbean.getText("ENDENTITYPROFILEID") %> + " /> <%= ejbcarabean.getEndEntityProfileId(profile) %> @@ -394,7 +394,7 @@   - <%= ejbcawebbean.getText("USERNAME") %> + " /> - <%= ejbcawebbean.getText("PASSWORD") %> + " /> <% used = profiledata.getUse(EndEntityProfile.PASSWORD,0); %> >
- <%= ejbcawebbean.getText("REQUIRED") %> + " /> <% if(profiledata.isRequired(EndEntityProfile.PASSWORD,0)) out.write("CHECKED"); %>> - <%= ejbcawebbean.getText("AUTOGENERATED") %> + " /> <% } %> -  <%= ejbcawebbean.getText("OFLENGTH") %>  +  " />  > <% if(!used) { out.write("disabled"); } %>> <%= ejbcawebbean.getText("UNLIMITED") %>
- <%= ejbcawebbean.getText("USE") %> + " /> />    - <%= ejbcawebbean.getText("MODIFYABLE") %> + " /> - <%= ejbcawebbean.getText("USEINBATCH") %> + " /> <% used = false; if(profiledata.getUse(EndEntityProfile.CLEARTEXTPASSWORD,0)) used=true; %> - <%= ejbcawebbean.getText("USE") %> + " /> >
- <%= ejbcawebbean.getText("DEFAULT") %> + " /> <% if(profiledata.getValue(EndEntityProfile.CLEARTEXTPASSWORD,0).equals(EndEntityProfile.TRUE) && used) out.write(" CHECKED "); %>>    - <%= ejbcawebbean.getText("REQUIRED") %> + " /> <% if(profiledata.isRequired(EndEntityProfile.CLEARTEXTPASSWORD,0) && used) out.write("CHECKED"); @@ -531,8 +531,8 @@   - <%= ejbcawebbean.getText("EMAILDOMAIN") %>
- <%= ejbcawebbean.getText("USEONLYDOMAIN") %> + " />
+ " /> <% used = false; @@ -540,17 +540,17 @@ used=true; %> value="<% if(profiledata.getValue(EndEntityProfile.EMAIL,0) != null && used) out.write(profiledata.getValue(EndEntityProfile.EMAIL,0)); %>">
- <%= ejbcawebbean.getText("USE") %> + " /> >   - <%= ejbcawebbean.getText("REQUIRED") %> + " /> <% if(profiledata.isRequired(EndEntityProfile.EMAIL,0) && used) out.write("CHECKED"); %>> -   <%= ejbcawebbean.getText("MODIFYABLE") %> +   " /> <% if(profiledata.isModifyable(EndEntityProfile.EMAIL,0) && used) out.write("CHECKED"); @@ -566,7 +566,7 @@   - <%= ejbcawebbean.getText("DIRECTIVES") %> + " />   @@ -578,7 +578,7 @@   - <%= ejbcawebbean.getText("REVERSEFIELDCHECKS") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Reverse%20Subject%20DN%20Alt%20Name%20Checks") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Reverse%20Subject%20DN%20Alt%20Name%20Checks") %> > @@ -590,7 +590,7 @@   - <%= ejbcawebbean.getText("ALLOWMERGEDNWEBSERVICES") %> + " /> <%= ejbcawebbean.getHelpReference("/adminguide.html#Configuring%20Web%20Services%20behavior") %> @@ -607,7 +607,7 @@   - <%= ejbcawebbean.getText("CERT_SUBJECTDN_ATTRIBUTES") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#End%20Entity%20Profile%20fields") %> @@ -617,17 +617,17 @@ - <%= ejbcawebbean.getText("SELECTFORREMOVAL") %> + " /> - <%= ejbcawebbean.getText("CERT_SUBJECTDN_ATTRIBUTES") %> + " /> @@ -644,18 +644,18 @@ - <%= ejbcawebbean.getText(DnComponents.getLanguageConstantFromProfileId(fielddata[EndEntityProfile.FIELDTYPE])) %> + <% if(!EndEntityProfile.isFieldOfType(fielddata[EndEntityProfile.FIELDTYPE], DnComponents.DNEMAIL) ){ %>
- <%= ejbcawebbean.getText("REQUIRED") %> + " /> > -   <%= ejbcawebbean.getText("MODIFYABLE") %> +   " /> - <%= ejbcawebbean.getText("REQUIRED") %> + " /> >   <%=ejbcawebbean.getText("SEEEMAILCONFIGURATION") %> + %>>   " /> <% }%> @@ -694,7 +694,7 @@   - <%= ejbcawebbean.getText("OTHERSUBJECTATTR") %> + " />   @@ -703,10 +703,10 @@ - <%= ejbcawebbean.getText("SELECTFORREMOVAL") %> + " /> - <%= ejbcawebbean.getText("EXT_PKIX_SUBJECTALTNAME") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Subject%20Alternative%20Names") %> @@ -715,7 +715,7 @@ String[] subjectaltnamefields = EndEntityProfile.getSubjectAltnameProfileFields(); for(int i=0; i < subjectaltnamefields.length; i++){ if (EndEntityProfile.isFieldImplemented(subjectaltnamefields[i])) { %> - <% } }%> @@ -734,15 +734,15 @@ - <%= ejbcawebbean.getText(DnComponents.getLanguageConstantFromProfileId(fielddata[EndEntityProfile.FIELDTYPE])) %> + <% if ( EndEntityProfile.isFieldOfType(fielddata[EndEntityProfile.FIELDTYPE], DnComponents.UPN) ) { %>
- <%= ejbcawebbean.getText("USEONLYUPNDOMAIN") %> + " /> <% } %> <% if ( EndEntityProfile.isFieldOfType(fielddata[EndEntityProfile.FIELDTYPE], DnComponents.RFC822NAME) ) { %> - <%= ejbcawebbean.getText("USEENTITYEMAILFIELD") %> + " /> />
- <%= ejbcawebbean.getText("REQUIRED") %> + " /> > -   <%= ejbcawebbean.getText("MODIFYABLE") %> +   " /> - <%= ejbcawebbean.getText("SELECTFORREMOVAL") %> + " /> - <%= ejbcawebbean.getText("EXT_PKIX_SUBJECTDIRATTRS") %> + " /> @@ -820,18 +820,18 @@ - <%= ejbcawebbean.getText(DnComponents.getLanguageConstantFromProfileId(fielddata[EndEntityProfile.FIELDTYPE])) %> +
- <%= ejbcawebbean.getText("REQUIRED") %> + " /> > -   <%= ejbcawebbean.getText("MODIFYABLE") %> +   " /> - <%= ejbcawebbean.getText("MAINCERTIFICATEDATA") %> + " />   @@ -872,7 +872,7 @@   - <%= ejbcawebbean.getText("DEFAULTCERTIFICATEPROFILE") %> + " /> @@ -923,7 +923,7 @@   - <%= ejbcawebbean.getText("DEFAULTCA") %> + " /> @@ -953,7 +953,7 @@ <% } iter = authorizedcas.iterator(); @@ -975,7 +975,7 @@   - <%= ejbcawebbean.getText("DEFAULTTOKEN") %> + " /> @@ -1023,7 +1023,7 @@   - <%= ejbcawebbean.getText("USEHARDTOKENISSUERS") %> + " /> <% used = profiledata.getUse(EndEntityProfile.AVAILTOKENISSUER,0); %> @@ -1038,7 +1038,7 @@   - <%= ejbcawebbean.getText("DEFAULTHARDTOKENISSUER") %> + " /> > @@ -1083,7 +1083,7 @@   - <%= ejbcawebbean.getText("OTHERCERTIFICATEDATA") %> + " />   @@ -1095,11 +1095,11 @@   - <%= ejbcawebbean.getText("CERT_SERIALNUMBER_CUSTOM") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Allow%20certificate%20serial%20number%20override") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Allow%20certificate%20serial%20number%20override") %> <% used = profiledata.getUse(EndEntityProfile.CERTSERIALNR, 0); %> - <%= ejbcawebbean.getText("USE") %> + " /> - +   - <%= ejbcawebbean.getText("CERT_EXTENSIONDATA_CUSTOM") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Custom%20certificate%20extension%20data") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Custom%20certificate%20extension%20data") %> <% used = profiledata.getUseExtensiondata(); %> - <%= ejbcawebbean.getText("USE") %> + " /> - <%= ejbcawebbean.getText("TIMEOFSTART") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Certificate%20Validity") %>
- (<%= ejbcawebbean.getText("DATE_INFO") %>
<%= ejbcawebbean.getDateExample() - %> <%= ejbcawebbean.getText("OR").toLowerCase() %> <%= ejbcawebbean.getText("DAYS").toLowerCase() - %>:<%= ejbcawebbean.getText("HOURS").toLowerCase() %>:<%= ejbcawebbean.getText("MINUTES").toLowerCase() %>) + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Certificate%20Validity") %>
+ (" />
" /> " />:" />:" />) <% used = profiledata.getUse(EndEntityProfile.STARTTIME, 0); %> @@ -1146,7 +1146,7 @@ out.write(" disabled "); } %> />
- <%= ejbcawebbean.getText("USE") %> + " /> />    - <%= ejbcawebbean.getText("MODIFYABLE") %> + " /> - <%= ejbcawebbean.getText("TIMEOFEND") %> <%= ejbcawebbean.getHelpReference("/userguide.html#Certificate%20Validity") %>
- (<%= ejbcawebbean.getText("DATE_INFO") %>
<%= ejbcawebbean.getDateExample() - %> <%= ejbcawebbean.getText("OR").toLowerCase() %> <%= ejbcawebbean.getText("DAYS").toLowerCase() - %>:<%= ejbcawebbean.getText("HOURS").toLowerCase() %>:<%= ejbcawebbean.getText("MINUTES").toLowerCase() %>) + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Certificate%20Validity") %>
+ (" />
" /> " />:" />:" />) <% used = profiledata.getUse(EndEntityProfile.ENDTIME, 0); %> @@ -1185,7 +1185,7 @@ out.write(" disabled "); } %> />
- <%= ejbcawebbean.getText("USE") %> + " /> />    - <%= ejbcawebbean.getText("MODIFYABLE") %> + " /> - <%= ejbcawebbean.getText("CARDNUMBER") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Cardnumber") %> <% used = profiledata.getUse(EndEntityProfile.CARDNUMBER,0); %> - <%= ejbcawebbean.getText("USE") %> + " /> > - <%= ejbcawebbean.getText("REQUIRED") %> + " /> <% if(profiledata.isRequired(EndEntityProfile.CARDNUMBER,0) && used) out.write("CHECKED"); @@ -1237,7 +1237,7 @@   - <%= ejbcawebbean.getText("OTHERDATA") %> + " />   @@ -1249,7 +1249,7 @@   - <%= ejbcawebbean.getText("ALLOWEDREQUESTS") %> + " /> <% used = profiledata.getUse(EndEntityProfile.ALLOWEDREQUESTS,0); @@ -1258,7 +1258,7 @@ nrofrequests = "1"; } %> - <%= ejbcawebbean.getText("USE") %> + " /> - <%= ejbcawebbean.getText("KEYRECOVERABLE") %> + " /> <% used = profiledata.getUse(EndEntityProfile.KEYRECOVERABLE,0); %> - <%= ejbcawebbean.getText("USE") %> + " /> > - <%= ejbcawebbean.getText("REUSEOLDCERTIFICATE") %> + " /> <% if(profiledata.getReUseKeyRecoveredCertificate() && used) out.write("CHECKED"); %> >
- <%= ejbcawebbean.getText("DEFAULT") %> + " /> <% if(profiledata.getValue(EndEntityProfile.KEYRECOVERABLE,0) != null && used) if(profiledata.getValue(EndEntityProfile.KEYRECOVERABLE,0).equals(EndEntityProfile.TRUE)) out.write("CHECKED"); %>>   - <%= ejbcawebbean.getText("REQUIRED") %> + " /> <% if(profiledata.isRequired(EndEntityProfile.KEYRECOVERABLE,0) && used) out.write("CHECKED"); @@ -1316,16 +1316,16 @@   - <%= ejbcawebbean.getText("ISSUANCEREVOCATIONREASON",true) %> <%= ejbcawebbean.getHelpReference("/userguide.html#Revocation%20reason%20to%20set%20after%20certificate%20issuance") %> + " /> <%= ejbcawebbean.getHelpReference("/userguide.html#Revocation%20reason%20to%20set%20after%20certificate%20issuance") %> <% used = profiledata.getUse(EndEntityProfile.ISSUANCEREVOCATIONREASON,0); %> - <%= ejbcawebbean.getText("USE") %> + " /> > - <%= ejbcawebbean.getText("MODIFYABLE") %> + " /> + %>>" /> + %>>" />: " /> + %>>" />: " /> + %>>" />: " /> + %>>" />: " /> + %>>" />: " /> + %>>" />: " /> + %>>" />: " /> + %>>" />: " /> + %>>" />: " /> @@ -1391,23 +1391,23 @@   - <%= ejbcawebbean.getText("SENDNOTIFICATION") %> + " /> <%= ejbcawebbean.getHelpReference("/adminguide.html#Email%20notifications") %> <% used = profiledata.getUse(EndEntityProfile.SENDNOTIFICATION,0); %> - <%= ejbcawebbean.getText("USE") %> + " /> >
- <%= ejbcawebbean.getText("DEFAULT") %> + " /> <% if(profiledata.getValue(EndEntityProfile.SENDNOTIFICATION,0) != null && used) if(profiledata.getValue(EndEntityProfile.SENDNOTIFICATION,0).equals(EndEntityProfile.TRUE)) out.write("CHECKED"); %>>   - <%= ejbcawebbean.getText("REQUIRED") %> + " /> <% if(profiledata.isRequired(EndEntityProfile.SENDNOTIFICATION,0) && used) out.write("CHECKED"); @@ -1427,7 +1427,7 @@ " /> - <%= ejbcawebbean.getText("NOTIFICATIONSENDER") %>
(<%= ejbcawebbean.getText("EMAILADDRESS") %>) + " />
(" />) - <%= ejbcawebbean.getText("NOTIFICATIONRECIPIENT") %> + " /> - <%= ejbcawebbean.getText("NOTIFICATIONEVENTS") %> + " /> - <%= ejbcawebbean.getText("NOTIFICATIONMESSAGE") %> + " /> @@ -1507,7 +1507,7 @@ " <%=profiledata.getUse(EndEntityProfile.SENDNOTIFICATION,0) ? "" : "disabled"%>/> - <%= ejbcawebbean.getText("NOTIFICATIONSENDER") %>
(<%= ejbcawebbean.getText("EMAILADDRESS") %>) + " />
(" />) /> @@ -1518,7 +1518,7 @@   - <%= ejbcawebbean.getText("NOTIFICATIONRECIPIENT") %> + " /> /> @@ -1529,7 +1529,7 @@   - <%= ejbcawebbean.getText("NOTIFICATIONEVENTS") %> + " /> >
- <%= ejbcawebbean.getText("DEFAULT") %> + " /> <% if(profiledata.getPrintingDefault() && used){ out.write("CHECKED"); } %>>   - <%= ejbcawebbean.getText("REQUIRED") %> + " /> <% if(profiledata.getPrintingRequired() && used){ out.write("CHECKED"); @@ -1606,12 +1606,12 @@   - <%= ejbcawebbean.getText("PRINTERNAME") %> + " /> > @@ -1650,7 +1650,7 @@   - <%= ejbcawebbean.getText("CURRENTTEMPLATE") %> + " /> <% if(profiledata.getPrinterSVGFileName().equals("")){ @@ -1666,7 +1666,7 @@   - <%= ejbcawebbean.getText("UPLOADTEMPLATE") %>  + " />  "> diff -urN ../ejbca_4_0_6/modules/build-properties.xml ./modules/build-properties.xml --- ../ejbca_4_0_6/modules/build-properties.xml 2011-11-18 12:33:40.000000000 +0100 +++ ./modules/build-properties.xml 2011-12-25 12:00:44.000000000 +0100 @@ -13,7 +13,6 @@ - diff -urN ../ejbca_4_0_6/modules/build.xml ./modules/build.xml --- ../ejbca_4_0_6/modules/build.xml 2011-11-18 12:33:40.000000000 +0100 +++ ./modules/build.xml 2011-12-25 12:00:30.000000000 +0100 @@ -87,7 +87,7 @@ - + diff -urN ../ejbca_4_0_6/modules/clientToolBox/src/org/ejbca/ui/cli/ClientToolBox.java ./modules/clientToolBox/src/org/ejbca/ui/cli/ClientToolBox.java --- ../ejbca_4_0_6/modules/clientToolBox/src/org/ejbca/ui/cli/ClientToolBox.java 2011-11-18 12:33:36.000000000 +0100 +++ ./modules/clientToolBox/src/org/ejbca/ui/cli/ClientToolBox.java 2011-12-25 12:00:36.000000000 +0100 @@ -17,7 +17,7 @@ /** * Extend this class for each new tool you want to add and add the new extended class to the toolBox array in {@link #main(String[])} * @author primelars - * @version $Id: ClientToolBox.java 12819 2011-10-05 08:14:18Z aveen4711 $ + * @version $Id: ClientToolBox.java 13330 2011-12-13 16:29:14Z aveen4711 $ * */ public abstract class ClientToolBox { @@ -59,6 +59,7 @@ new EjbcaWsRaCli(), new CvcWsRaCli(), new CMPTest(), + new CMPKeyUpdateStressTest(), new CMPNestedMessageTest(), new CMPNestedMessageStressTest(), new SCEPTest(), diff -urN ../ejbca_4_0_6/modules/clientToolBox/src/org/ejbca/ui/cli/CMPKeyUpdateStressTest.java ./modules/clientToolBox/src/org/ejbca/ui/cli/CMPKeyUpdateStressTest.java --- ../ejbca_4_0_6/modules/clientToolBox/src/org/ejbca/ui/cli/CMPKeyUpdateStressTest.java 1970-01-01 01:00:00.000000000 +0100 +++ ./modules/clientToolBox/src/org/ejbca/ui/cli/CMPKeyUpdateStressTest.java 2011-12-25 12:00:36.000000000 +0100 @@ -0,0 +1,846 @@ +/************************************************************************* + * * + * EJBCA: The OpenSource Certificate Authority * + * * + * This software is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or any later version. * + * * + * See terms of license at gnu.org. * + * * + *************************************************************************/ + +package org.ejbca.ui.cli; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.net.HttpURLConnection; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.Signature; +import java.security.SignatureException; +import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Date; + +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.lang.StringUtils; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERGeneralizedTime; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DEROutputStream; +import org.bouncycastle.asn1.DERUTF8String; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.asn1.x509.X509CertificateStructure; +import org.bouncycastle.asn1.x509.X509Name; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.ejbca.core.model.InternalResources; +import org.ejbca.core.protocol.cmp.CMPSendHTTP; +import org.ejbca.util.CertTools; +import org.ejbca.util.CryptoProviderTools; +import org.ejbca.util.PerformanceTest; +import org.ejbca.util.PerformanceTest.Command; +import org.ejbca.util.PerformanceTest.CommandFactory; + +import com.novosec.pkix.asn1.cmp.CMPObjectIdentifiers; +import com.novosec.pkix.asn1.cmp.CertConfirmContent; +import com.novosec.pkix.asn1.cmp.CertOrEncCert; +import com.novosec.pkix.asn1.cmp.CertRepMessage; +import com.novosec.pkix.asn1.cmp.CertResponse; +import com.novosec.pkix.asn1.cmp.CertifiedKeyPair; +import com.novosec.pkix.asn1.cmp.PKIBody; +import com.novosec.pkix.asn1.cmp.PKIHeader; +import com.novosec.pkix.asn1.cmp.PKIMessage; +import com.novosec.pkix.asn1.cmp.PKIStatusInfo; +import com.novosec.pkix.asn1.crmf.AttributeTypeAndValue; +import com.novosec.pkix.asn1.crmf.CRMFObjectIdentifiers; +import com.novosec.pkix.asn1.crmf.CertReqMessages; +import com.novosec.pkix.asn1.crmf.CertReqMsg; +import com.novosec.pkix.asn1.crmf.CertRequest; +import com.novosec.pkix.asn1.crmf.CertTemplate; +import com.novosec.pkix.asn1.crmf.OptionalValidity; +import com.novosec.pkix.asn1.crmf.PBMParameter; +import com.novosec.pkix.asn1.crmf.POPOSigningKey; +import com.novosec.pkix.asn1.crmf.ProofOfPossession; + +/** + * Used to stress test the CMP interface. + */ +class CMPKeyUpdateStressTest extends ClientToolBox { + /** Internal localization of logs and errors */ + private static final InternalResources intres = InternalResources.getInstance(); + static private class StressTest { + final PerformanceTest performanceTest; + + final private PrivateKey oldKey; + final private KeyPair newKeyPair; + final private Certificate extraCert; + final private X509Certificate cacert; + final private String eepassword; + final private CertificateFactory certificateFactory; + final private Provider bcProvider = new BouncyCastleProvider(); + final private String hostName; + final private int port; + final String urlPath; + final String resultCertFilePrefix; + boolean isSign; + boolean firstTime = true; + + StressTest( final String _hostName, + final int _port, + final int numberOfThreads, + final int waitTime, + final String _urlPath, + final String _resultCertFilePrefix, + final String _eepassword, + final Certificate _cacert, + final PrivateKey _oldKey, + final Certificate _extraCert) throws Exception { + + this.hostName = _hostName; + this.certificateFactory = CertificateFactory.getInstance("X.509", this.bcProvider); + this.cacert = (X509Certificate) _cacert; + this.eepassword = _eepassword; + this.port = _port; + this.urlPath = _urlPath; + this.resultCertFilePrefix = _resultCertFilePrefix; + + final KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA"); + keygen.initialize(2048); + this.newKeyPair = keygen.generateKeyPair(); + this.oldKey = _oldKey; + this.extraCert = _extraCert; + + this.performanceTest = new PerformanceTest(); + this.performanceTest.execute(new MyCommandFactory(), numberOfThreads, waitTime, System.out); + } + + private CertRequest genKeyUpdateReq() throws IOException { + final OptionalValidity myOptionalValidity = new OptionalValidity(); + final int day = 1000*60*60*24; + myOptionalValidity.setNotBefore( new org.bouncycastle.asn1.x509.Time(new Date(new Date().getTime()-day)) ); + myOptionalValidity.setNotAfter( new org.bouncycastle.asn1.x509.Time(new Date(new Date().getTime()+10*day)) ); + + final CertTemplate myCertTemplate = new CertTemplate(); + myCertTemplate.setValidity( myOptionalValidity ); + final byte[] bytes = this.newKeyPair.getPublic().getEncoded(); + final ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); + final ASN1InputStream dIn = new ASN1InputStream(bIn); + final SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo((ASN1Sequence)dIn.readObject()); + myCertTemplate.setPublicKey(keyInfo); + return new CertRequest(new DERInteger(4), myCertTemplate); + } + private PKIMessage genPKIMessage(final SessionData sessionData, + final boolean raVerifiedPopo, + final CertRequest keyUpdateRequest) throws NoSuchAlgorithmException, IOException, InvalidKeyException, SignatureException { + + final CertReqMsg myCertReqMsg = new CertReqMsg(keyUpdateRequest); + + ProofOfPossession myProofOfPossession; + if (raVerifiedPopo) { + // raVerified POPO (meaning there is no POPO) + myProofOfPossession = new ProofOfPossession(new DERNull(), 0); + } else { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final DEROutputStream mout = new DEROutputStream( baos ); + mout.writeObject( keyUpdateRequest ); + mout.close(); + final byte[] popoProtectionBytes = baos.toByteArray(); + final Signature sig = Signature.getInstance( PKCSObjectIdentifiers.sha1WithRSAEncryption.getId()); + sig.initSign(this.oldKey); + sig.update( popoProtectionBytes ); + + final DERBitString bs = new DERBitString(sig.sign()); + + final POPOSigningKey myPOPOSigningKey = + new POPOSigningKey( + new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption), + bs); + //myPOPOSigningKey.setPoposkInput( myPOPOSigningKeyInput ); + myProofOfPossession = new ProofOfPossession(myPOPOSigningKey, 1); + } + + myCertReqMsg.setPop(myProofOfPossession); + + final AttributeTypeAndValue av = new AttributeTypeAndValue(CRMFObjectIdentifiers.regCtrl_regToken, new DERUTF8String("foo123")); + myCertReqMsg.addRegInfo(av); + + final CertReqMessages myCertReqMessages = new CertReqMessages(myCertReqMsg); + + final PKIHeader myPKIHeader = + new PKIHeader( new DERInteger(2), + new GeneralName(new X509Name(CertTools.getSubjectDN(extraCert))), + new GeneralName(new X509Name(this.cacert.getSubjectDN().getName())) ); + myPKIHeader.setMessageTime(new DERGeneralizedTime(new Date())); + myPKIHeader.setSenderNonce(new DEROctetString(sessionData.getNonce())); + myPKIHeader.setSenderKID(new DEROctetString(sessionData.getNonce())); + myPKIHeader.setTransactionID(new DEROctetString(sessionData.getTransId())); + + final PKIBody myPKIBody = new PKIBody(myCertReqMessages, 7); // key update request + return new PKIMessage(myPKIHeader, myPKIBody); + } + + private void addExtraCert(PKIMessage msg, Certificate cert) throws CertificateEncodingException, IOException{ + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + ASN1InputStream dIn = new ASN1InputStream(bIn); + ASN1Sequence extraCertSeq = (ASN1Sequence)dIn.readObject(); + X509CertificateStructure extraCert = new X509CertificateStructure(ASN1Sequence.getInstance(extraCertSeq)); + msg.addExtraCert(extraCert); + } + + private PKIMessage signPKIMessage(final PKIMessage msg, PrivateKey signingKey) throws NoSuchAlgorithmException, NoSuchProviderException, + InvalidKeyException, SignatureException { + PKIMessage message = msg; + final Signature sig = Signature.getInstance(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId(), "BC"); + sig.initSign(signingKey); + sig.update(message.getProtectedBytes()); + byte[] eeSignature = sig.sign(); + message.setProtection(new DERBitString(eeSignature)); + return message; + } + + private PKIMessage protectPKIMessage(final PKIMessage msg, + final boolean badObjectId, + final String password) throws NoSuchAlgorithmException, InvalidKeyException { + // SHA1 + final AlgorithmIdentifier owfAlg = new AlgorithmIdentifier("1.3.14.3.2.26"); + // 567 iterations + final int iterationCount = 567; + // HMAC/SHA1 + final AlgorithmIdentifier macAlg = new AlgorithmIdentifier("1.2.840.113549.2.7"); + final byte[] salt = "foo123".getBytes(); + final DEROctetString derSalt = new DEROctetString(salt); + final PKIMessage ret; + + + // Create the PasswordBased protection of the message + final PKIHeader head = msg.getHeader(); + head.setSenderKID(new DEROctetString("EMPTY".getBytes())); + final DERInteger iteration = new DERInteger(iterationCount); + + // Create the new protected return message + String objectId = "1.2.840.113533.7.66.13"; + if (badObjectId) { + objectId += ".7"; + } + final PBMParameter pp = new PBMParameter(derSalt, owfAlg, iteration, macAlg); + final AlgorithmIdentifier pAlg = new AlgorithmIdentifier(new DERObjectIdentifier(objectId), pp); + head.setProtectionAlg(pAlg); + + final PKIBody body = msg.getBody(); + ret = new PKIMessage(head, body); + + + // Calculate the protection bits + final byte[] raSecret = password.getBytes(); + byte basekey[] = new byte[raSecret.length + salt.length]; + for (int i = 0; i < raSecret.length; i++) { + basekey[i] = raSecret[i]; + } + for (int i = 0; i < salt.length; i++) { + basekey[raSecret.length+i] = salt[i]; + } + // Construct the base key according to rfc4210, section 5.1.3.1 + final MessageDigest dig = MessageDigest.getInstance(owfAlg.getObjectId().getId(), this.bcProvider); + for (int i = 0; i < iterationCount; i++) { + basekey = dig.digest(basekey); + dig.reset(); + } + // For HMAC/SHA1 there is another oid, that is not known in BC, but the result is the same so... + final String macOid = macAlg.getObjectId().getId(); + final byte[] protectedBytes = ret.getProtectedBytes(); + final Mac mac = Mac.getInstance(macOid, this.bcProvider); + final SecretKey key = new SecretKeySpec(basekey, macOid); + mac.init(key); + mac.reset(); + mac.update(protectedBytes, 0, protectedBytes.length); + final byte[] out = mac.doFinal(); + final DERBitString bs = new DERBitString(out); + + // Finally store the protection bytes in the msg + ret.setProtection(bs); + + return ret; + } + + private byte[] sendCmpHttp(final byte[] message) throws Exception { + final CMPSendHTTP send = CMPSendHTTP.doIt(message, StressTest.this.hostName, StressTest.this.port, StressTest.this.urlPath, false); + if ( send.responseCode!=HttpURLConnection.HTTP_OK ) { + StressTest.this.performanceTest.getLog().error(intres.getLocalizedMessage("cmp.responsecodenotok", Integer.valueOf(send.responseCode))); + return null; + } + if ( send.contentType==null ) { + StressTest.this.performanceTest.getLog().error("No content type received."); + return null; + } + // Some appserver (Weblogic) responds with "application/pkixcmp; charset=UTF-8" + if ( !send.contentType.startsWith("application/pkixcmp") ) { + StressTest.this.performanceTest.getLog().info("wrong content type: "+send.contentType); + } + return send.response; + } + private boolean checkCmpResponseGeneral(final byte[] retMsg, + final SessionData sessionData, + final boolean requireProtection) throws Exception { + // + // Parse response message + // + final PKIMessage respObject = PKIMessage.getInstance(new ASN1InputStream(new ByteArrayInputStream(retMsg)).readObject()); + if ( respObject==null ) { + StressTest.this.performanceTest.getLog().error("No command response message."); + return false; + } + + // The signer, i.e. the CA, check it's the right CA + final PKIHeader header = respObject.getHeader(); + if ( header==null ) { + StressTest.this.performanceTest.getLog().error("No header in response message."); + return false; + } + // Check that the signer is the expected CA + final X509Name name = X509Name.getInstance(header.getSender().getName()); + if ( header.getSender().getTagNo()!=4 || name==null || !name.equals(this.cacert.getSubjectDN()) ) { + StressTest.this.performanceTest.getLog().error("Not signed by right issuer."); + } + + if ( header.getSenderNonce().getOctets().length!=16 ) { + StressTest.this.performanceTest.getLog().error("Wrong length of received sender nonce (made up by server). Is "+header.getSenderNonce().getOctets().length+" byte but should be 16."); + } + + if ( !Arrays.equals(header.getRecipNonce().getOctets(), sessionData.getNonce()) ) { + StressTest.this.performanceTest.getLog().error("recipient nonce not the same as we sent away as the sender nonce. Sent: "+Arrays.toString(sessionData.getNonce())+" Received: "+Arrays.toString(header.getRecipNonce().getOctets())); + } + + if ( !Arrays.equals(header.getTransactionID().getOctets(), sessionData.getTransId()) ) { + StressTest.this.performanceTest.getLog().error("transid is not the same as the one we sent"); + } + { + // Check that the message is signed with the correct digest alg + final AlgorithmIdentifier algId = header.getProtectionAlg(); + if (algId==null || algId.getObjectId()==null || algId.getObjectId().getId()==null) { + if ( requireProtection ) { + StressTest.this.performanceTest.getLog().error("Not possible to get algorithm."); + return false; + } + return true; + } + final String id = algId.getObjectId().getId(); + if ( id.equals(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId()) ) { + if ( this.firstTime ) { + this.firstTime = false; + this.isSign = true; + StressTest.this.performanceTest.getLog().info("Signature protection used."); + } else if ( !this.isSign ) { + StressTest.this.performanceTest.getLog().error("Message password protected but should be signature protected."); + } + } else if ( id.equals(CMPObjectIdentifiers.passwordBasedMac.getId()) ) { + if ( this.firstTime ) { + this.firstTime = false; + this.isSign = false; + StressTest.this.performanceTest.getLog().info("Password (PBE) protection used."); + } else if ( this.isSign ) { + StressTest.this.performanceTest.getLog().error("Message signature protected but should be password protected."); + } + } else { + StressTest.this.performanceTest.getLog().error("No valid algorithm."); + return false; + } + } + if ( this.isSign ) { + // Verify the signature + byte[] protBytes = respObject.getProtectedBytes(); + final DERBitString bs = respObject.getProtection(); + final Signature sig; + try { + sig = Signature.getInstance(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId()); + sig.initVerify(this.cacert); + sig.update(protBytes); + if ( !sig.verify(bs.getBytes()) ) { + StressTest.this.performanceTest.getLog().error("CA signature not verifying"); + } + } catch ( Exception e) { + StressTest.this.performanceTest.getLog().error("Not possible to verify signature.", e); + } + } else { + //final DEROctetString os = header.getSenderKID(); + //if ( os!=null ) + // StressTest.this.performanceTest.getLog().info("Found a sender keyId: "+new String(os.getOctets())); + // Verify the PasswordBased protection of the message + final PBMParameter pp; { + final AlgorithmIdentifier pAlg = header.getProtectionAlg(); + // StressTest.this.performanceTest.getLog().info("Protection type is: "+pAlg.getObjectId().getId()); + pp = PBMParameter.getInstance(pAlg.getParameters()); + } + final int iterationCount = pp.getIterationCount().getPositiveValue().intValue(); + // StressTest.this.performanceTest.getLog().info("Iteration count is: "+iterationCount); + final AlgorithmIdentifier owfAlg = pp.getOwf(); + // Normal OWF alg is 1.3.14.3.2.26 - SHA1 + // StressTest.this.performanceTest.getLog().info("Owf type is: "+owfAlg.getObjectId().getId()); + final AlgorithmIdentifier macAlg = pp.getMac(); + // Normal mac alg is 1.3.6.1.5.5.8.1.2 - HMAC/SHA1 + // StressTest.this.performanceTest.getLog().info("Mac type is: "+macAlg.getObjectId().getId()); + final byte[] salt = pp.getSalt().getOctets(); + //log.info("Salt is: "+new String(salt)); + final byte[] raSecret = new String("password").getBytes(); + // HMAC/SHA1 os normal 1.3.6.1.5.5.8.1.2 or 1.2.840.113549.2.7 + final String macOid = macAlg.getObjectId().getId(); + final SecretKey key; { + byte[] basekey = new byte[raSecret.length + salt.length]; + for (int i = 0; i < raSecret.length; i++) { + basekey[i] = raSecret[i]; + } + for (int i = 0; i < salt.length; i++) { + basekey[raSecret.length+i] = salt[i]; + } + // Construct the base key according to rfc4210, section 5.1.3.1 + final MessageDigest dig = MessageDigest.getInstance(owfAlg.getObjectId().getId(), this.bcProvider); + for (int i = 0; i < iterationCount; i++) { + basekey = dig.digest(basekey); + dig.reset(); + } + key = new SecretKeySpec(basekey, macOid); + } + final Mac mac = Mac.getInstance(macOid, this.bcProvider); + mac.init(key); + mac.reset(); + final byte[] protectedBytes = respObject.getProtectedBytes(); + final DERBitString protection = respObject.getProtection(); + mac.update(protectedBytes, 0, protectedBytes.length); + byte[] out = mac.doFinal(); + // My out should now be the same as the protection bits + byte[] pb = protection.getBytes(); + if ( !Arrays.equals(out, pb) ) { + StressTest.this.performanceTest.getLog().error("Wrong PBE hash"); + } + } + return true; + } + private X509Certificate checkCmpCertRepMessage(final SessionData sessionData, + final byte[] retMsg, + final int requestId) throws IOException, CertificateException { + // + // Parse response message + // + final PKIMessage respObject = PKIMessage.getInstance(new ASN1InputStream(new ByteArrayInputStream(retMsg)).readObject()); + if ( respObject==null ) { + StressTest.this.performanceTest.getLog().error("No PKIMessage for certificate received."); + return null; + } + final PKIBody body = respObject.getBody(); + if ( body==null ) { + StressTest.this.performanceTest.getLog().error("No PKIBody for certificate received."); + return null; + } + if ( body.getTagNo()!=8 ) { + StressTest.this.performanceTest.getLog().error("Cert body tag not 8."); + return null; + } + final CertRepMessage c = body.getKup(); + if ( c==null ) { + StressTest.this.performanceTest.getLog().error("No CertRepMessage for certificate received."); + return null; + } + final CertResponse resp = c.getResponse(0); + if ( resp==null ) { + StressTest.this.performanceTest.getLog().error("No CertResponse for certificate received."); + return null; + } + if ( resp.getCertReqId().getValue().intValue()!=requestId ) { + StressTest.this.performanceTest.getLog().error("Received CertReqId is "+resp.getCertReqId().getValue().intValue()+" but should be "+requestId); + return null; + } + final PKIStatusInfo info = resp.getStatus(); + if ( info==null ) { + StressTest.this.performanceTest.getLog().error("No PKIStatusInfo for certificate received."); + return null; + } + if ( info.getStatus().getValue().intValue()!=0 ) { + StressTest.this.performanceTest.getLog().error("Received Status is "+info.getStatus().getValue().intValue()+" but should be 0"); + return null; + } + final CertifiedKeyPair kp = resp.getCertifiedKeyPair(); + if ( kp==null ) { + StressTest.this.performanceTest.getLog().error("No CertifiedKeyPair for certificate received."); + return null; + } + final CertOrEncCert cc = kp.getCertOrEncCert(); + if ( cc==null ) { + StressTest.this.performanceTest.getLog().error("No CertOrEncCert for certificate received."); + return null; + } + final X509CertificateStructure struct = cc.getCertificate(); + if ( struct==null ) { + StressTest.this.performanceTest.getLog().error("No X509CertificateStructure for certificate received."); + return null; + } + final byte encoded[] = struct.getEncoded(); + if ( encoded==null || encoded.length<=0 ) { + StressTest.this.performanceTest.getLog().error("No encoded certificate received."); + return null; + } + final X509Certificate cert = (X509Certificate)this.certificateFactory.generateCertificate(new ByteArrayInputStream(encoded)); + if ( cert==null ) { + StressTest.this.performanceTest.getLog().error("Not possbile to create certificate."); + return null; + } + // Remove this test to be able to test unid-fnr + if ( cert.getSubjectDN().hashCode() != new X509Name(CertTools.getSubjectDN(extraCert)).hashCode() ) { + StressTest.this.performanceTest.getLog().error("Subject is '"+cert.getSubjectDN()+"' but should be '"+CertTools.getSubjectDN(extraCert)+'\''); + return null; + } + if ( cert.getIssuerX500Principal().hashCode() != this.cacert.getSubjectX500Principal().hashCode() ) { + StressTest.this.performanceTest.getLog().error("Issuer is '"+cert.getIssuerDN()+"' but should be '"+this.cacert.getSubjectDN()+'\''); + return null; + } + try { + cert.verify(this.cacert.getPublicKey()); + } catch (Exception e) { + StressTest.this.performanceTest.getLog().error("Certificate not verifying. See exception", e); + return null; + } + return cert; + } + + + private boolean checkCmpPKIConfirmMessage(final SessionData sessionData, + final byte retMsg[]) throws IOException { + // + // Parse response message + // + final PKIMessage respObject = PKIMessage.getInstance(new ASN1InputStream(new ByteArrayInputStream(retMsg)).readObject()); + if ( respObject==null ) { + StressTest.this.performanceTest.getLog().error("Not possbile to get response message."); + return false; + } + final PKIHeader header = respObject.getHeader(); + if ( header.getSender().getTagNo()!=4 ) { + StressTest.this.performanceTest.getLog().error("Wrong tag in respnse message header. Is "+header.getSender().getTagNo()+" should be 4."); + return false; + } + { + final X509Name name = X509Name.getInstance(header.getSender().getName()); + String senderDN = name.toString().replaceAll(" ", ""); + String caDN = this.cacert.getSubjectDN().toString().replaceAll(" ", ""); + if(!StringUtils.equals(senderDN, caDN)) { + StressTest.this.performanceTest.getLog().error("Wrong CA DN. Is '"+name+"' should be '"+this.cacert.getSubjectDN()+"'."); + return false; + } + } + { + final X509Name name = X509Name.getInstance(header.getRecipient().getName()); + if ( name.hashCode() != new X509Name(CertTools.getSubjectDN(extraCert)).hashCode() ) { + StressTest.this.performanceTest.getLog().error("Wrong recipient DN. Is '"+name+"' should be '"+CertTools.getSubjectDN(extraCert)+"'."); + return false; + } + } + final PKIBody body = respObject.getBody(); + if ( body==null ) { + StressTest.this.performanceTest.getLog().error("No PKIBody for response received."); + return false; + } + if ( body.getTagNo()!=19 ) { + StressTest.this.performanceTest.getLog().error("Cert body tag not 19. It was " + body.getTagNo()); + + StressTest.this.performanceTest.getLog().error(body.getError().getPKIStatus().getStatusString().getString(0).getString()); + + + return false; + } + final DERNull n = body.getConf(); + if ( n==null ) { + StressTest.this.performanceTest.getLog().error("Confirmation is null."); + return false; + } + return true; + } + + private PKIMessage genCertConfirm(final SessionData sessionData, final String hash) { + + PKIHeader myPKIHeader = new PKIHeader( + new DERInteger(2), + new GeneralName(new X509Name(CertTools.getSubjectDN(this.extraCert))), + new GeneralName(new X509Name(this.cacert.getSubjectDN().getName()))); + myPKIHeader.setMessageTime(new DERGeneralizedTime(new Date())); + // senderNonce + myPKIHeader.setSenderNonce(new DEROctetString(sessionData.getNonce())); + // TransactionId + myPKIHeader.setTransactionID(new DEROctetString(sessionData.getTransId())); + + CertConfirmContent cc = new CertConfirmContent(new DEROctetString(hash.getBytes()), new DERInteger(sessionData.getReqId())); + PKIBody myPKIBody = new PKIBody(cc, 24); // Cert Confirm + PKIMessage myPKIMessage = new PKIMessage(myPKIHeader, myPKIBody); + return myPKIMessage; + } + + private class GetCertificate implements Command { + final private SessionData sessionData; + GetCertificate(final SessionData sd) { + this.sessionData = sd; + } + + public boolean doIt() throws Exception { + this.sessionData.newSession(); + + CertRequest keyUpdateReq = genKeyUpdateReq(); + PKIMessage certMsg = genPKIMessage(this.sessionData, true, keyUpdateReq); + if ( certMsg==null ) { + StressTest.this.performanceTest.getLog().error("No certificate request."); + return false; + } + AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption); + certMsg.getHeader().setProtectionAlg(pAlg); + //certMsg.getHeader().setSenderKID(new DEROctetString("EMPTY".getBytes())); + PKIMessage signedMsg = signPKIMessage(certMsg, oldKey); + addExtraCert(signedMsg, extraCert); + if ( signedMsg==null ) { + StressTest.this.performanceTest.getLog().error("No protected message."); + return false; + } + + + this.sessionData.setReqId(signedMsg.getBody().getKur().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); + final ByteArrayOutputStream bao = new ByteArrayOutputStream(); + final DEROutputStream out = new DEROutputStream(bao); + out.writeObject(signedMsg); + final byte[] ba = bao.toByteArray(); + // Send request and receive response + final byte[] resp = sendCmpHttp(ba); + if ( resp==null || resp.length <= 0 ) { + StressTest.this.performanceTest.getLog().error("No response message."); + return false; + } + if ( !checkCmpResponseGeneral(resp, this.sessionData, true) ) { + return false; + } + final X509Certificate cert = checkCmpCertRepMessage(this.sessionData, resp, this.sessionData.getReqId()); + if ( cert==null ) { + return false; + } + String fp = CertTools.getFingerprintAsString((Certificate) cert); + this.sessionData.setFP(fp); + final BigInteger serialNumber = CertTools.getSerialNumber(cert); + if ( StressTest.this.resultCertFilePrefix!=null ) { + new FileOutputStream(StressTest.this.resultCertFilePrefix+serialNumber+".dat").write(cert.getEncoded()); + } + StressTest.this.performanceTest.getLog().result(serialNumber); + + return true; + } + public String getJobTimeDescription() { + return "Get certificate"; + } + + } + + + private class SendConfirmMessageToCA implements Command { + final private SessionData sessionData; + SendConfirmMessageToCA(final SessionData sd) { + this.sessionData = sd; + } + public boolean doIt() throws Exception { + final String hash = this.sessionData.getFP(); //"foo123"; + final PKIMessage con = genCertConfirm(this.sessionData, hash); + if ( con==null ) { + StressTest.this.performanceTest.getLog().error("Not possible to generate PKIMessage."); + return false; + } + //final String password = PBEPASSWORD; + //final String password = StressTest.this.performanceTest.getRandom().nextInt()%10!=0 ? PBEPASSWORD : PBEPASSWORD+"a"; + final PKIMessage confirm = protectPKIMessage(con, false, "foo123"); + final ByteArrayOutputStream bao = new ByteArrayOutputStream(); + final DEROutputStream out = new DEROutputStream(bao); + out.writeObject(confirm); + final byte ba[] = bao.toByteArray(); + // Send request and receive response + final byte[] resp = sendCmpHttp(ba); + if ( resp==null || resp.length <= 0 ) { + StressTest.this.performanceTest.getLog().error("No response message."); + return false; + } + if ( !checkCmpResponseGeneral(resp, this.sessionData, false) ) { + return false; + } + if ( !checkCmpPKIConfirmMessage(this.sessionData, resp) ) { + return false; + } + //StressTest.this.performanceTest.getLog().info("User with DN '"+this.sessionData.getUserDN()+"' finished."); + return true; + } + public String getJobTimeDescription() { + return "Send confirmation to CA"; + } + } + + + class SessionData { + final private byte[] nonce = new byte[16]; + final private byte[] transid = new byte[16]; + private int reqId; + private String newcertfp; + + SessionData() { + super(); + } + + void newSession() { + StressTest.this.performanceTest.getRandom().nextBytes(this.nonce); + StressTest.this.performanceTest.getRandom().nextBytes(this.transid); + } + int getReqId() { + return this.reqId; + } + void setReqId(int i) { + this.reqId = i; + } + void setFP(String fp) { + this.newcertfp = fp; + } + String getFP() { + return this.newcertfp; + } + byte[] getTransId() { + return this.transid; + } + byte[] getNonce() { + return this.nonce; + } + } + private class MyCommandFactory implements CommandFactory { + public Command[] getCommands() throws Exception { + final SessionData sessionData = new SessionData(); + return new Command[]{new GetCertificate(sessionData), new SendConfirmMessageToCA(sessionData)};//, new Revoke(sessionData)}; + } + } + } + + /* (non-Javadoc) + * @see org.ejbca.ui.cli.ClientToolBox#execute(java.lang.String[]) + */ + @Override + protected void execute(String[] args) { + final String hostName; + final String keystoreFile; + final String keystorePassword; + final String certNameInKeystore; + final int numberOfThreads; + final int waitTime; + final int port; + final String urlPath; + final String resultFilePrefix; + if ( args.length < 5 ) { + System.out.println(args[0]+" [] [] [] [] []"); + System.out.println("EJBCA build configuration requirements: cmp.operationmode=normal, cmp.allowraverifypopo=true, cmp.allowautomatickeyupdate=true, cmp.allowupdatewithsamekey=true"); +// System.out.println("EJBCA build configuration optional: cmp.ra.certificateprofile=KeyId cmp.ra.endentityprofile=KeyId (used when the KeyId argument should be used as profile name)."); + System.out.println("Ejbca expects the following: There exists an end entity with a generated certificate. The end entity's certificate and its private key are stored in the keystore used " + + "in the commandline. The end entity's certificate's 'friendly name' in the keystore is the one used in the command line. Such keystore can be obtained, for example, by specifying " + + "the token to be 'P12' when creating the end entity and then download the keystore by choosing 'create keystore' from the public web"); + return; + } + hostName = args[1]; + keystoreFile = args[2]; + keystorePassword = args[3]; + certNameInKeystore = args[4]; + numberOfThreads = args.length>5 ? Integer.parseInt(args[5].trim()):1; + waitTime = args.length>6 ? Integer.parseInt(args[6].trim()):0; + port = args.length>7 ? Integer.parseInt(args[7].trim()):8080; +// isHttp = true; + urlPath = args.length>8 && args[8].toLowerCase().indexOf("null")<0 ? args[8].trim():null; + resultFilePrefix = args.length>9 ? args[9].trim() : null; + + CryptoProviderTools.installBCProviderIfNotAvailable(); + + Certificate cacert = null; + Certificate extracert = null; + PrivateKey oldCertKey = null; + + FileInputStream file_inputstream; + try { + file_inputstream = new FileInputStream(keystoreFile); + KeyStore keyStore = KeyStore.getInstance("PKCS12"); + keyStore.load(file_inputstream, keystorePassword.toCharArray()); + Key key=keyStore.getKey(certNameInKeystore, keystorePassword.toCharArray()); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key.getEncoded()); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + oldCertKey = keyFactory.generatePrivate(keySpec); + //extracert = keyStore.getCertificate(certNameInKeystore); + + Certificate[] certs = keyStore.getCertificateChain(certNameInKeystore); + extracert = certs[0]; + cacert = certs[1]; + + } catch (FileNotFoundException e2) { + e2.printStackTrace(); + System.exit(-1); + } catch (KeyStoreException e) { + e.printStackTrace(); + System.exit(-1); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + System.exit(-1); + } catch (CertificateException e) { + e.printStackTrace(); + System.exit(-1); + } catch (IOException e) { + e.printStackTrace(); + System.exit(-1); + } catch (UnrecoverableKeyException e) { + e.printStackTrace(); + System.exit(-1); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + System.exit(-1); + } + + try { + new StressTest(hostName, port, numberOfThreads, waitTime, urlPath, resultFilePrefix, keystorePassword, cacert, oldCertKey, extracert); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /* (non-Javadoc) + * @see org.ejbca.ui.cli.ClientToolBox#getName() + */ + @Override + protected String getName() { + return "CMPKeyUpdateStressTest"; + } + +} diff -urN ../ejbca_4_0_6/modules/clientToolBox/src/org/ejbca/ui/cli/CMPNestedMessageStressTest.java ./modules/clientToolBox/src/org/ejbca/ui/cli/CMPNestedMessageStressTest.java --- ../ejbca_4_0_6/modules/clientToolBox/src/org/ejbca/ui/cli/CMPNestedMessageStressTest.java 2011-11-18 12:33:36.000000000 +0100 +++ ./modules/clientToolBox/src/org/ejbca/ui/cli/CMPNestedMessageStressTest.java 2011-12-25 12:00:36.000000000 +0100 @@ -689,7 +689,7 @@ final String resultFilePrefix; if ( args.length < 6 ) { System.out.println(args[0]+" [] [] [] [] [] []"); - System.out.println("EJBCA build configutation requirements: cmp.operationmode=ra, cmp.allowraverifypopo=true, cmp.authenticationmodule=EndEntityCertificate, cmp.authenticationparameters=AdminCA1, checkadminauthorization=false, cmp.racertificatepath=/tmp/racerts"); + System.out.println("EJBCA build configuration requirements: cmp.operationmode=ra, cmp.allowraverifypopo=true, cmp.authenticationmodule=EndEntityCertificate, cmp.authenticationparameters=AdminCA1, checkadminauthorization=false, cmp.racertificatepath=/tmp/racerts"); System.out.println("EJBCA build configuration optional: cmp.ra.certificateprofile=KeyId cmp.ra.endentityprofile=KeyId (used when the KeyId argument should be used as profile name)."); return; } diff -urN ../ejbca_4_0_6/modules/clientToolBox/src/org/ejbca/ui/cli/CMPTest.java ./modules/clientToolBox/src/org/ejbca/ui/cli/CMPTest.java --- ../ejbca_4_0_6/modules/clientToolBox/src/org/ejbca/ui/cli/CMPTest.java 2011-11-18 12:33:36.000000000 +0100 +++ ./modules/clientToolBox/src/org/ejbca/ui/cli/CMPTest.java 2011-12-25 12:00:36.000000000 +0100 @@ -96,7 +96,7 @@ /** * Used to stress test the CMP interface. * @author primelars - * @version $Id: CMPTest.java 11982 2011-05-16 13:36:33Z primelars $ + * @version $Id: CMPTest.java 13432 2011-12-19 14:44:07Z anatom $ * */ class CMPTest extends ClientToolBox { @@ -838,7 +838,7 @@ final String resultFilePrefix; if ( args.length < 3 ) { System.out.println(args[0]+" [] [] [] [] [] [] []"); - System.out.println("EJBCA build configutation requirements: cmp.operationmode=ra, cmp.allowraverifypopo=true, cmp.responseprotection=signature, cmp.ra.authenticationsecret=password"); + System.out.println("EJBCA build configuration requirements: cmp.operationmode=ra, cmp.allowraverifypopo=true, cmp.responseprotection=signature, cmp.ra.authenticationsecret=password"); System.out.println("EJBCA build configuration optional: cmp.ra.certificateprofile=KeyId cmp.ra.endentityprofile=KeyId (used when the KeyId argument should be used as profile name)."); return; } diff -urN ../ejbca_4_0_6/modules/ejbca-ejb/build.xml ./modules/ejbca-ejb/build.xml --- ../ejbca_4_0_6/modules/ejbca-ejb/build.xml 2011-11-18 12:33:36.000000000 +0100 +++ ./modules/ejbca-ejb/build.xml 2011-12-25 12:00:30.000000000 +0100 @@ -53,6 +53,7 @@ + @@ -319,6 +320,7 @@ + @@ -337,7 +339,7 @@ - + - - - - - - - - - - - @@ -139,7 +128,6 @@ encoding="iso8859-1" target="${java.target.version}" classpathref="va-compile.classpath"> - diff -urN ../ejbca_4_0_6/modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestMissingStoredCertTestCommand.java ./modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestMissingStoredCertTestCommand.java --- ../ejbca_4_0_6/modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestMissingStoredCertTestCommand.java 2011-11-18 12:33:40.000000000 +0100 +++ ./modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestMissingStoredCertTestCommand.java 2011-12-25 12:00:46.000000000 +0100 @@ -276,7 +276,7 @@ protected void usage() { getPrintStream().println("Command used to send a cmp certificate request inside a NestedMessageContent signed by an untrusted RA."); getPrintStream().println("Usage : missingstoredcert [] []"); - getPrintStream().println("EJBCA build configutation requirements: cmp.operationmode=ra, cmp.authenticationmodule=EndEntityCertificate, cmp.authenticationparameters=AdminCA1, cmp.racertificatepath=/opt/racerts"); + getPrintStream().println("EJBCA build configuration requirements: cmp.operationmode=ra, cmp.authenticationmodule=EndEntityCertificate, cmp.authenticationparameters=AdminCA1, cmp.racertificatepath=/opt/racerts"); } diff -urN ../ejbca_4_0_6/modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestTestCommand.java ./modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestTestCommand.java --- ../ejbca_4_0_6/modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestTestCommand.java 2011-11-18 12:33:40.000000000 +0100 +++ ./modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestTestCommand.java 2011-12-25 12:00:46.000000000 +0100 @@ -308,7 +308,7 @@ protected void usage() { getPrintStream().println("Command used to send a cmp certificate request inside a NestedMessageContent and get back a certificate."); getPrintStream().println("Usage : crmfrequest [] [] [] []"); - getPrintStream().println("EJBCA build configutation requirements: cmp.operationmode=ra, cmp.allowraverifypopo=false, cmp.authenticationmodule=EndEntityCertificate, cmp.authenticationparameters=AdminCA1, cmp.racertificatepath=/opt/racerts"); + getPrintStream().println("EJBCA build configuration requirements: cmp.operationmode=ra, cmp.allowraverifypopo=false, cmp.authenticationmodule=EndEntityCertificate, cmp.authenticationparameters=AdminCA1, cmp.racertificatepath=/opt/racerts"); } diff -urN ../ejbca_4_0_6/modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestWrongSignatureTestCommand.java ./modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestWrongSignatureTestCommand.java --- ../ejbca_4_0_6/modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestWrongSignatureTestCommand.java 2011-11-18 12:33:40.000000000 +0100 +++ ./modules/ejbca-ws-cli/src/org/ejbca/core/protocol/ws/client/NestedCrmfRequestWrongSignatureTestCommand.java 2011-12-25 12:00:46.000000000 +0100 @@ -363,7 +363,7 @@ getPrintStream().println("Command used to send a cmp certificate request inside a NestedMessageContent with an invalid RA signature."); getPrintStream().println("Usage : invalidrasignature [] [] []"); - getPrintStream().println("EJBCA build configutation requirements: cmp.operationmode=ra, cmp.allowraverifypopo=true, cmp.authenticationmodule=EndEntityCertificate, cmp.authenticationparameters=AdminCA1, checkadminauthorization=false, cmp.racertificatepath=/opt/racerts"); + getPrintStream().println("EJBCA build configuration requirements: cmp.operationmode=ra, cmp.allowraverifypopo=true, cmp.authenticationmodule=EndEntityCertificate, cmp.authenticationparameters=AdminCA1, checkadminauthorization=false, cmp.racertificatepath=/opt/racerts"); } diff -urN ../ejbca_4_0_6/modules/healtcheck-war/build.xml ./modules/healtcheck-war/build.xml --- ../ejbca_4_0_6/modules/healtcheck-war/build.xml 2011-11-18 12:33:34.000000000 +0100 +++ ./modules/healtcheck-war/build.xml 2011-12-25 12:00:28.000000000 +0100 @@ -29,6 +29,7 @@ + diff -urN ../ejbca_4_0_6/modules/healtcheck-war/resources/WEB-INF/web-ocsp.xml ./modules/healtcheck-war/resources/WEB-INF/web-ocsp.xml --- ../ejbca_4_0_6/modules/healtcheck-war/resources/WEB-INF/web-ocsp.xml 2011-11-18 12:33:34.000000000 +0100 +++ ./modules/healtcheck-war/resources/WEB-INF/web-ocsp.xml 2011-12-25 12:00:28.000000000 +0100 @@ -23,7 +23,7 @@ ExtOCSPHealthCheckServlet - /extocsphealth + /vahealth diff -urN ../ejbca_4_0_6/modules/systemtests/src/org/ejbca/core/protocol/cmp/AuthenticationModulesTest.java ./modules/systemtests/src/org/ejbca/core/protocol/cmp/AuthenticationModulesTest.java --- ../ejbca_4_0_6/modules/systemtests/src/org/ejbca/core/protocol/cmp/AuthenticationModulesTest.java 2011-11-18 12:33:40.000000000 +0100 +++ ./modules/systemtests/src/org/ejbca/core/protocol/cmp/AuthenticationModulesTest.java 2011-12-25 12:00:48.000000000 +0100 @@ -53,6 +53,7 @@ import org.ejbca.core.ejb.ca.caadmin.CaSessionRemote; import org.ejbca.core.ejb.ca.sign.SignSessionRemote; import org.ejbca.core.ejb.ca.store.CertificateStoreSession; +import org.ejbca.core.ejb.ca.store.CertificateStoreSessionRemote; import org.ejbca.core.ejb.config.ConfigurationSessionRemote; import org.ejbca.core.ejb.ra.UserAdminSessionRemote; import org.ejbca.core.model.AlgorithmConstants; @@ -82,7 +83,7 @@ /** * This will test the different cmp authentication modules. * - * @version $Id: AuthenticationModulesTest.java 12957 2011-10-21 06:42:19Z anatom $ + * @version $Id: AuthenticationModulesTest.java 13507 2011-12-23 16:54:41Z anatom $ * */ public class AuthenticationModulesTest extends CmpTestCase { @@ -108,6 +109,7 @@ private AuthorizationSession authorizationSession = InterfaceCache.getAuthorizationSession(); private AdminGroupSessionRemote adminGroupSession = InterfaceCache.getAdminGroupSession(); private AdminEntitySessionRemote adminEntitySession = InterfaceCache.getAdminEntitySession(); + private CertificateStoreSessionRemote certStoreSession = InterfaceCache.getCertificateStoreSession(); public AuthenticationModulesTest(String arg0) { super(arg0); @@ -209,7 +211,7 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), true, null); Certificate cert1 = checkCmpCertRepMessage(userDN, cacert, resp, req.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("Crmf request did not return a certificate", cert1); } @@ -254,7 +256,7 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), true, null); int revStatus = checkRevokeStatus(issuerDN, CertTools.getSerialNumber(cert)); assertNotSame("Revocation request failed to revoke the certificate", RevokedCertInfo.NOT_REVOKED, revStatus); } @@ -293,7 +295,7 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), true, null); Certificate cert2 = checkCmpCertRepMessage(userDN, cacert, resp, msg.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("CrmfRequest did not return a certificate", cert2); } @@ -348,12 +350,75 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), true, null); int revStatus = checkRevokeStatus(issuerDN, CertTools.getSerialNumber(cert)); assertNotSame("Revocation request failed to revoke the certificate", RevokedCertInfo.NOT_REVOKED, revStatus); } + + public void test07EERevReqWithUnknownCA() throws NoSuchAlgorithmException, EjbcaException, IOException, Exception { + confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE); + assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE)); + confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONPARAMETERS, "AdminCA1"); + assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_AUTHENTICATIONPARAMETERS, "AdminCA1")); + confSession.updateProperty(CmpConfiguration.CONFIG_OPERATIONMODE, "ra"); + assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_OPERATIONMODE, "ra")); + + Collection certs = certStoreSession.findCertificatesBySubjectAndIssuer(admin, userDN, issuerDN); + log.debug("Found " + certs.size() + " certificates for userDN \"" + userDN + "\""); + Certificate cert = null, tmp=null; + Iterator itr = certs.iterator(); + while(itr.hasNext()) { + tmp = itr.next(); + if(!certStoreSession.isRevoked(issuerDN, CertTools.getSerialNumber(tmp))) { + cert = tmp; + break; + } + } + if(cert == null) { + createUser("cmprevuser1", "CN=cmprevuser1,C=SE", "foo123"); + KeyPair admkeys = KeyTools.genKeys("1024", "RSA"); + cert = signSession.createCertificate(admin, "cmprevuser1", "foo123", admkeys.getPublic()); + } + assertNotNull("No certificate to revoke.", cert); + + + PKIMessage msg = genRevReq("CN=cmprevuser1,C=SE", userDN, CertTools.getSerialNumber(cert), cert, nonce, transid, false); + assertNotNull("Generating CrmfRequest failed.", msg); + + AlgorithmIdentifier pAlg = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption); + msg.getHeader().setProtectionAlg(pAlg); + msg.getHeader().setSenderKID(new DEROctetString(nonce)); + + String adminName = "cmpTestAdmin"; + createUser(adminName, "CN=cmpTestAdmin,C=SE", "foo123"); + KeyPair admkeys = KeyTools.genKeys("1024", "RSA"); + Certificate admCert = signSession.createCertificate(admin, adminName, "foo123", admkeys.getPublic()); + Admin adm = new Admin(admCert, adminName, adminName + "@primekey.se"); + setupAccessRights(adm); + addExtraCert(msg, admCert); + signPKIMessage(msg, admkeys); + assertNotNull(msg); + + final ByteArrayOutputStream bao = new ByteArrayOutputStream(); + final DEROutputStream out = new DEROutputStream(bao); + out.writeObject(msg); + final byte[] ba = bao.toByteArray(); + // Send request and receive response + final byte[] resp = sendCmpHttp(ba, 200); + checkCmpResponseGeneral(resp, "C=SE,CN=cmprevuser1", userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), false, null); + //int revStatus = checkRevokeStatus(issuerDN, CertTools.getSerialNumber(cert)); + //assertNotSame("Revocation request failed to revoke the certificate", RevokedCertInfo.NOT_REVOKED, revStatus); + PKIMessage respObject = PKIMessage.getInstance(new ASN1InputStream(new ByteArrayInputStream(resp)).readObject()); + assertNotNull(respObject); + + PKIBody body = respObject.getBody(); + assertEquals(23, body.getTagNo()); + String errMsg = body.getError().getPKIStatus().getStatusString().getString(0).getString(); + String expectedErrMsg = "CA with DN 'C=SE,CN=cmprevuser1' is unknown"; + assertEquals(expectedErrMsg, errMsg); + } - public void test07EECrmfReqMultipleAuthModules() throws NoSuchAlgorithmException, EjbcaException, IOException, Exception { + public void test08EECrmfReqMultipleAuthModules() throws NoSuchAlgorithmException, EjbcaException, IOException, Exception { assertFalse("Configurations have not been backed up before starting testing.", confSession.backupConfiguration()); String modules = CmpConfiguration.AUTHMODULE_HMAC + ";" + CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE; @@ -393,7 +458,7 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), true, null); Certificate cert2 = checkCmpCertRepMessage(userDN, cacert, resp, msg.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("CrmfRequest did not return a certificate", cert2); @@ -403,11 +468,12 @@ assertEquals(CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE, verifier.getUsedAuthenticationModule().getName()); } - public void test08HMACCrmfReqMultipleAuthenticationModules() throws Exception { + public void test09HMACCrmfReqMultipleAuthenticationModules() throws Exception { assertFalse("Configurations have not been backed up before starting testing.", confSession.backupConfiguration()); + final String pbeSecret = "foo123hmac"; String modules = CmpConfiguration.AUTHMODULE_REG_TOKEN_PWD + ";" + CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE + ";" + CmpConfiguration.AUTHMODULE_HMAC; - String parameters = "-;AdminCA1;foo123hmac"; + String parameters = "-;AdminCA1;"+pbeSecret; confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, modules); assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, modules)); ConfigurationHolder.updateConfiguration(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, modules); @@ -420,12 +486,15 @@ assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_OPERATIONMODE, "ra")); ConfigurationHolder.updateConfiguration(CmpConfiguration.CONFIG_OPERATIONMODE, "ra"); assertTrue("The CMP Authentication module was not configured correctly.", CmpConfiguration.getRAOperationMode()); - + + confSession.updateProperty(CmpConfiguration.CONFIG_RESPONSEPROTECTION, "pbe"); + assertTrue("The response protection was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_RESPONSEPROTECTION, "pbe")); + KeyPair keys = KeyTools.genKeys("512", AlgorithmConstants.KEYALGORITHM_RSA); PKIMessage msg = genCertReq(issuerDN, userDN, keys, cacert, nonce, transid, false, null, null, null, null); assertNotNull("Generating CrmfRequest failed." + msg); - PKIMessage req = protectPKIMessage(msg, false, "foo123hmac", "mykeyid", 567); + PKIMessage req = protectPKIMessage(msg, false, pbeSecret, "mykeyid", 567); assertNotNull("Protecting PKIMessage with HMACPbe failed.", req); final ByteArrayOutputStream bao = new ByteArrayOutputStream(); @@ -434,7 +503,7 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, userDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), false, pbeSecret); Certificate cert1 = checkCmpCertRepMessage(userDN, cacert, resp, req.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("Crmf request did not return a certificate", cert1); @@ -444,7 +513,7 @@ assertEquals(CmpConfiguration.AUTHMODULE_HMAC, verifier.getUsedAuthenticationModule().getName()); } - public void test09HMACCrmfReqWrongAuthenticationModule() throws Exception { + public void test10HMACCrmfReqWrongAuthenticationModule() throws Exception { assertFalse("Configurations have not been backed up before starting testing.", confSession.backupConfiguration()); confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_DN_PART_PWD); @@ -483,13 +552,15 @@ } - public void test10EECrmfCheckAdminAuthorization() throws NoSuchAlgorithmException, EjbcaException, IOException, Exception { + public void test11EECrmfCheckAdminAuthorization() throws NoSuchAlgorithmException, EjbcaException, IOException, Exception { assertFalse("Configurations have not been backed up before starting testing.", confSession.backupConfiguration()); confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE); assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE)); confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONPARAMETERS, "AdminCA1"); assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_AUTHENTICATIONPARAMETERS, "AdminCA1")); + confSession.updateProperty(CmpConfiguration.CONFIG_CHECKADMINAUTHORIZATION, "true"); + assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_CHECKADMINAUTHORIZATION, "true")); confSession.updateProperty(CmpConfiguration.CONFIG_OPERATIONMODE, "ra"); assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_OPERATIONMODE, "ra")); @@ -530,12 +601,12 @@ assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_CHECKADMINAUTHORIZATION, "false")); final byte[] resp2 = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp2, issuerDN, userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp2, issuerDN, userDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), true, null); Certificate cert2 = checkCmpCertRepMessage(userDN, cacert, resp2, msg.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("CrmfRequest did not return a certificate", cert2); } - public void test11CrmfReqClientModeHMAC() throws Exception { + public void test12CrmfReqClientModeHMAC() throws Exception { assertFalse("Configurations have not been backed up before starting testing.", confSession.backupConfiguration()); confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_HMAC); @@ -547,6 +618,9 @@ ConfigurationHolder.updateConfiguration(CmpConfiguration.CONFIG_OPERATIONMODE, "normal"); assertFalse("The CMP Authentication module was not configured correctly.", CmpConfiguration.getRAOperationMode()); + confSession.updateProperty(CmpConfiguration.CONFIG_RESPONSEPROTECTION, "signature"); + assertTrue("The response protection was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_RESPONSEPROTECTION, "signature")); + String clientUsername = "clientTestUser"; String clientDN = "CN=" + clientUsername + ",C=SE"; String clientPassword = "foo123client"; @@ -568,7 +642,7 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, clientDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, clientDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), true, null); Certificate cert1 = checkCmpCertRepMessage(clientDN, cacert, resp, req.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("Crmf request did not return a certificate", cert1); @@ -585,7 +659,7 @@ final byte[] ba2 = bao2.toByteArray(); // Send request and receive response final byte[] respNoIssuer = sendCmpHttp(ba2, 200); - checkCmpResponseGeneral(respNoIssuer, issuerDN, clientDN, cacert, reqNoIssuer.getHeader().getSenderNonce().getOctets(), reqNoIssuer.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(respNoIssuer, issuerDN, clientDN, cacert, reqNoIssuer.getHeader().getSenderNonce().getOctets(), reqNoIssuer.getHeader().getTransactionID().getOctets(), true, null); Certificate cert2 = checkCmpCertRepMessage(clientDN, cacert, respNoIssuer, reqNoIssuer.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("Crmf request did not return a certificate", cert2); @@ -600,12 +674,12 @@ final byte[] ba3 = bao3.toByteArray(); // Send request and receive response byte[] resp3 = sendCmpHttp(ba3, 200); - checkCmpResponseGeneral(resp3, issuerDN, userDN, cacert, nonce, transid, false, null); + checkCmpResponseGeneral(resp3, issuerDN, userDN, cacert, nonce, transid, true, null); checkCmpPKIConfirmMessage(userDN, cacert, resp3); } - public void test12HMACModuleInClientMode() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, IOException, + public void test13HMACModuleInClientMode() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException, IOException, InvalidAlgorithmParameterException, AuthorizationDeniedException, UserDoesntFullfillEndEntityProfile, WaitingForApprovalException, EjbcaException, java.lang.Exception { @@ -647,7 +721,7 @@ assertEquals("HMAC returned the wrong password", clientPassword, hmac.getAuthenticationString()); } - public void test13CrmfReqClientModeRegToken() throws Exception { + public void test14CrmfReqClientModeRegToken() throws Exception { assertFalse("Configurations have not been backed up before starting testing.", confSession.backupConfiguration()); confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_REG_TOKEN_PWD); @@ -680,12 +754,12 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, clientDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, clientDN, cacert, req.getHeader().getSenderNonce().getOctets(), req.getHeader().getTransactionID().getOctets(), true, null); Certificate cert1 = checkCmpCertRepMessage(clientDN, cacert, resp, req.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("Crmf request did not return a certificate", cert1); } - public void test14CrmfReqClientModeMultipleModules() throws Exception { + public void test15CrmfReqClientModeMultipleModules() throws Exception { assertFalse("Configurations have not been backed up before starting testing.", confSession.backupConfiguration()); String authmodules = CmpConfiguration.AUTHMODULE_HMAC + ";" + CmpConfiguration.AUTHMODULE_REG_TOKEN_PWD; @@ -722,7 +796,7 @@ final byte[] ba = bao.toByteArray(); // Send request and receive response final byte[] resp = sendCmpHttp(ba, 200); - checkCmpResponseGeneral(resp, issuerDN, clientDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), false, null); + checkCmpResponseGeneral(resp, issuerDN, clientDN, cacert, msg.getHeader().getSenderNonce().getOctets(), msg.getHeader().getTransactionID().getOctets(), true, null); Certificate cert1 = checkCmpCertRepMessage(clientDN, cacert, resp, msg.getBody().getIr().getCertReqMsg(0).getCertReq().getCertReqId().getValue().intValue()); assertNotNull("Crmf request did not return a certificate", cert1); @@ -732,7 +806,7 @@ assertEquals(CmpConfiguration.AUTHMODULE_REG_TOKEN_PWD, verifier.getUsedAuthenticationModule().getName()); } - public void test15HMACCrmfReqClientModeHMACInvalidPassword() throws Exception { + public void test16HMACCrmfReqClientModeHMACInvalidPassword() throws Exception { assertFalse("Configurations have not been backed up before starting testing.", confSession.backupConfiguration()); confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_HMAC); @@ -788,7 +862,7 @@ * * @throws Exception on some errors */ - public void test16CrmfReqClientModeEESignature() throws Exception { + public void test17CrmfReqClientModeEESignature() throws Exception { confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE); assertTrue("The CMP Authentication module was not configured correctly.", confSession.verifyProperty(CmpConfiguration.CONFIG_AUTHENTICATIONMODULE, CmpConfiguration.AUTHMODULE_ENDENTITY_CERTIFICATE)); confSession.updateProperty(CmpConfiguration.CONFIG_AUTHENTICATIONPARAMETERS, "-"); diff -urN ../ejbca_4_0_6/modules/systemtests/src/org/ejbca/ui/web/pub/cluster/WebOcspHealthCheckTest.java ./modules/systemtests/src/org/ejbca/ui/web/pub/cluster/WebOcspHealthCheckTest.java --- ../ejbca_4_0_6/modules/systemtests/src/org/ejbca/ui/web/pub/cluster/WebOcspHealthCheckTest.java 2011-11-18 12:33:40.000000000 +0100 +++ ./modules/systemtests/src/org/ejbca/ui/web/pub/cluster/WebOcspHealthCheckTest.java 2011-12-25 12:00:48.000000000 +0100 @@ -11,7 +11,7 @@ /** * - * @version $Id: WebOcspHealthCheckTest.java 11135 2011-01-10 22:57:28Z jeklund $ + * @version $Id: WebOcspHealthCheckTest.java 13423 2011-12-19 13:04:32Z jeklund $ */ public class WebOcspHealthCheckTest extends WebHealthTestAbstract { private static final Logger log = Logger.getLogger(WebOcspHealthCheckTest.class); @@ -24,7 +24,7 @@ public WebOcspHealthCheckTest(String name) { super(name); httpPort = "8080"; - httpReqPath = "http://localhost:" + httpPort + "/ejbca/publicweb/vahealthcheck/extocsphealth"; + httpReqPath = "http://localhost:" + httpPort + "/ejbca/publicweb/vahealthcheck/vahealth"; } public void setUp() throws Exception { diff -urN ../ejbca_4_0_6/modules/va-war/build.xml ./modules/va-war/build.xml --- ../ejbca_4_0_6/modules/va-war/build.xml 2011-11-18 12:33:36.000000000 +0100 +++ ./modules/va-war/build.xml 2011-12-25 12:00:28.000000000 +0100 @@ -34,6 +34,7 @@ + @@ -102,7 +103,6 @@ - diff -urN ../ejbca_4_0_6/propertyDefaults.xml ./propertyDefaults.xml --- ../ejbca_4_0_6/propertyDefaults.xml 2011-11-18 12:33:42.000000000 +0100 +++ ./propertyDefaults.xml 2011-12-25 12:00:48.000000000 +0100 @@ -48,29 +48,14 @@ Prepare for possible EJBCA plugins that should built and merged into the EAR file. --> - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + @@ -239,7 +224,20 @@ - + + + + + + + + + + + + + + ---------- ${app.version} CONFIGURATION PROPERTIES ---------- appserver.type = ${appserver.type} diff -urN ../ejbca_4_0_6/src/internal.properties ./src/internal.properties --- ../ejbca_4_0_6/src/internal.properties 2011-11-18 13:50:32.000000000 +0100 +++ ./src/internal.properties 2011-12-25 12:01:18.000000000 +0100 @@ -6,8 +6,8 @@ # configuration you need to change in EJBCA_HOME/conf/. # -app.version.number=4.0.6 -svn.revision=r13172 +app.version.number=4.0.7 +svn.revision=r13519 app.version=EJBCA ${app.version.number} (${svn.revision}) # Prefix for the JNDI name of the DataSource used for direct JDBC. The prefix is different for diff -urN ../ejbca_4_0_6/src/java/org/ejbca/core/protocol/cmp/authentication/EndEntityCertificateAuthenticationModule.java ./src/java/org/ejbca/core/protocol/cmp/authentication/EndEntityCertificateAuthenticationModule.java --- ../ejbca_4_0_6/src/java/org/ejbca/core/protocol/cmp/authentication/EndEntityCertificateAuthenticationModule.java 2011-11-18 12:33:34.000000000 +0100 +++ ./src/java/org/ejbca/core/protocol/cmp/authentication/EndEntityCertificateAuthenticationModule.java 2011-12-25 12:00:24.000000000 +0100 @@ -50,7 +50,7 @@ /** * Check the authentication of the PKIMessage by verifying the signature of the administrator who sent the message * - * @version $Id: EndEntityCertificateAuthenticationModule.java 13117 2011-11-07 08:21:10Z aveen4711 $ + * @version $Id: EndEntityCertificateAuthenticationModule.java 13210 2011-11-24 07:01:44Z anatom $ * */ public class EndEntityCertificateAuthenticationModule implements ICMPAuthenticationModule { @@ -147,7 +147,7 @@ * Verifies the signature of 'msg'. msg should be signed by an authorized administrator in EJBCA and * the administrator's cerfificate should be attached in msg in the extraCert field. * - * When successful, the password is set to the randomly generated 16-gidits String. + * When successful, the password is set to the randomly generated 16-digit String. * When failed, the error message is set. * * @param msg diff -urN ../ejbca_4_0_6/src/java/org/ejbca/core/protocol/cmp/authentication/HMACAuthenticationModule.java ./src/java/org/ejbca/core/protocol/cmp/authentication/HMACAuthenticationModule.java --- ../ejbca_4_0_6/src/java/org/ejbca/core/protocol/cmp/authentication/HMACAuthenticationModule.java 2011-11-18 12:33:34.000000000 +0100 +++ ./src/java/org/ejbca/core/protocol/cmp/authentication/HMACAuthenticationModule.java 2011-12-25 12:00:24.000000000 +0100 @@ -48,7 +48,7 @@ * In client mode, the authenticity is checked through the clear-text-password of the * pre-registered endentity from the database. * - * @version $Id: HMACAuthenticationModule.java 12949 2011-10-20 16:52:06Z anatom $ + * @version $Id: HMACAuthenticationModule.java 13493 2011-12-23 12:05:29Z aveen4711 $ * */ public class HMACAuthenticationModule implements ICMPAuthenticationModule { @@ -266,11 +266,12 @@ final CertConfirmContent certConf = getCertConfirm(msg); if (certConf != null) { byte[] certhash = certConf.getCertHash().getOctets(); - final String fp = new String(Hex.encode(certhash)); + //final String fp = new String(Hex.encode(certhash)); + final String fphex = new String(certhash); if (LOG.isDebugEnabled()) { - LOG.debug("Looking for issued certificate with fingerprint: "+fp); + LOG.debug("Looking for issued certificate with fingerprint: "+fphex); } - Certificate cert = certStoreSession.findCertificateByFingerprint(admin, fp); + Certificate cert = certStoreSession.findCertificateByFingerprint(admin, fphex); subjectDN = CertTools.getSubjectDN(cert); issuerDN = CertTools.getIssuerDN(cert); } else { diff -urN ../ejbca_4_0_6/src/java/org/ejbca/core/protocol/cmp/authentication/VerifyPKIMessage.java ./src/java/org/ejbca/core/protocol/cmp/authentication/VerifyPKIMessage.java --- ../ejbca_4_0_6/src/java/org/ejbca/core/protocol/cmp/authentication/VerifyPKIMessage.java 2011-11-18 12:33:34.000000000 +0100 +++ ./src/java/org/ejbca/core/protocol/cmp/authentication/VerifyPKIMessage.java 2011-12-25 12:00:24.000000000 +0100 @@ -30,7 +30,7 @@ * Verifies a CMP message using a suitable authentication module. The authentication modules * are specified in the properties file. * - * @version $Id: VerifyPKIMessage.java 12962 2011-10-21 08:26:58Z anatom $ + * @version $Id: VerifyPKIMessage.java 13210 2011-11-24 07:01:44Z anatom $ * */ public class VerifyPKIMessage { @@ -120,7 +120,7 @@ int i=0; while (ihandleMessage"); IResponseMessage resp = null; + + CA ca = null; + try { + ca = caSession.getCA(admin, msg.getHeader().getRecipient().getName().toString().hashCode()); + } catch (CADoesntExistsException e) { + final String errMsg = "CA with DN '" + msg.getHeader().getRecipient().getName().toString() + "' is unknown"; + return CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_REQUEST, errMsg); + } + // if version == 1 it is cmp1999 and we should not return a message back // Try to find a HMAC/SHA1 protection key String owfAlg = null; @@ -104,22 +120,8 @@ FailInfo failInfo = FailInfo.BAD_MESSAGE_CHECK; String failText = null; - CAInfo caInfo; - try { - final int eeProfileId = getUsedEndEntityProfileId(keyId); - final int caId = getUsedCaId(keyId, eeProfileId); - caInfo = caAdminSession.getCAInfo(admin, caId); - } catch (NotFoundException e) { - LOG.info(INTRES.getLocalizedMessage(CMP_ERRORGENERAL, e.getMessage()), e); - return CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.INCORRECT_DATA, e.getMessage()); - } catch (EJBException e) { - final String errMsg = INTRES.getLocalizedMessage(CMP_ERRORADDUSER); - LOG.error(errMsg, e); - return null; // Fatal error - } - //Verify the authenticity of the message - final VerifyPKIMessage messageVerifyer = new VerifyPKIMessage(caInfo, admin, caAdminSession, userAdminSession, certificateStoreSession, authorizationSession, endEntityProfileSession); + final VerifyPKIMessage messageVerifyer = new VerifyPKIMessage(ca.getCAInfo(), admin, caAdminSession, userAdminSession, certificateStoreSession, authorizationSession, endEntityProfileSession); ICMPAuthenticationModule authenticationModule = null; if(messageVerifyer.verify(msg.getMessage(), null)) { authenticationModule = messageVerifyer.getUsedAuthenticationModule(); @@ -135,7 +137,7 @@ return CmpMessageHelper.createUnprotectedErrorMessage(msg, ResponseStatus.FAILURE, FailInfo.BAD_MESSAGE_CHECK, errMsg); } else { if(authenticationModule instanceof HMACAuthenticationModule) { - HMACAuthenticationModule hmacmodule = (HMACAuthenticationModule) authenticationModule; + final HMACAuthenticationModule hmacmodule = (HMACAuthenticationModule) authenticationModule; owfAlg = hmacmodule.getCmpPbeVerifyer().getOwfOid(); macAlg = hmacmodule.getCmpPbeVerifyer().getMacOid(); } @@ -254,6 +256,14 @@ } if (StringUtils.equals(responseProtection, "pbe") && (owfAlg != null) && (macAlg != null) && (keyId != null) && (cmpRaAuthSecret != null) ) { rresp.setPbeParameters(keyId, cmpRaAuthSecret, owfAlg, macAlg, iterationCount); + } else { + try { + rresp.setSignKeyInfo(ca.getCACertificate(), ca.getCAToken().getPrivateKey(SecConst.CAKEYPURPOSE_CERTSIGN), ca.getCAToken().getProvider()); + } catch(IllegalKeyStoreException e) { + LOG.error(e.getLocalizedMessage()); + } catch(CATokenOfflineException e) { + LOG.error(e.getLocalizedMessage()); + } } resp = rresp; try { diff -urN ../ejbca_4_0_6/src/java/org/ejbca/ui/web/LimitLengthASN1Reader.java ./src/java/org/ejbca/ui/web/LimitLengthASN1Reader.java --- ../ejbca_4_0_6/src/java/org/ejbca/ui/web/LimitLengthASN1Reader.java 2011-11-18 12:33:34.000000000 +0100 +++ ./src/java/org/ejbca/ui/web/LimitLengthASN1Reader.java 2011-12-25 12:00:26.000000000 +0100 @@ -28,10 +28,10 @@ * Example usage: *
  * final ServletInputStream in = request.getInputStream(); // ServletInputStream does not have to be closed, container handles this
- * ret = new LimitLengthServletPostReader(in, n).readFirstASN1Object();
+ * ret = new LimitLengthASN1Reader(in, n).readFirstASN1Object();
  * 
* - * @version $Id: LimitLengthASN1Reader.java 10397 2010-11-08 14:18:57Z anatom $ + * @version $Id: LimitLengthASN1Reader.java 13364 2011-12-15 08:34:07Z anatom $ */ public class LimitLengthASN1Reader extends ASN1InputStream { @@ -66,20 +66,31 @@ } /** * Read the 'value' of the top ASN1 object and append it to the already read 'tag' and 'value' - * @param length nr of value bytes + * @param length nr of value bytes that we should read * @return the top ASN1 object * @throws IOException - * @throws MalformedRequestException + * @throws MalformedRequestException if the number of bytes read is less than length, i.e. asn.1 length tag was invalid */ private byte[] readTopASN1(int length) throws IOException, MalformedRequestException { - final byte value[] = new byte[length]; - final int readLength = read(value); - if ( readLength != length ) { - final String msg = intres.getLocalizedMessage("request.notcorrectasn1length", Integer.valueOf(length), Integer.valueOf(readLength)); - m_log.info(msg); - throw new MalformedRequestException(msg); - } - this.baos.write(value); + // This small code snippet is inspired/copied from apache IO utils by Tomas Gustavsson... + byte[] buf = new byte[length]; // buf of length length, normal optimal case is only one read operation below + int n = 0; + int bytesRead = 0; + // We must always read until it returns -1, make sure we read maximum length bytes + while (-1 != (n = read(buf, 0, length-bytesRead))) { + bytesRead += n; + this.baos.write(buf, 0, n); + if (bytesRead >= length) { + // We read as much as we should, stop reading + break; + } + } + if (bytesRead != length) { + // If we have read less bytes than we should have, the asn.1 was incorrect and this might be some type of attempt to perform buffer overflow + final String msg = intres.getLocalizedMessage("request.notcorrectasn1length", Integer.valueOf(length), Integer.valueOf(bytesRead)); + m_log.info(msg); + throw new MalformedRequestException(msg); + } this.baos.flush(); return this.baos.toByteArray(); } diff -urN ../ejbca_4_0_6/src/samples/plugins/mypublisher/build.xml ./src/samples/plugins/mypublisher/build.xml --- ../ejbca_4_0_6/src/samples/plugins/mypublisher/build.xml 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mypublisher/build.xml 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -urN ../ejbca_4_0_6/src/samples/plugins/mypublisher/README ./src/samples/plugins/mypublisher/README --- ../ejbca_4_0_6/src/samples/plugins/mypublisher/README 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mypublisher/README 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,10 @@ +Minimal EJBCA plugin for EJBCA 4 +================================ + +This sample contains a minimal EJBCA "custom publisher". +It can be configured in the Admin GUI using the path: + + com.example.mypublisher.MyPublisher + +After install, you should be able to "Save and Test Connection" +in the publisher GUI. \ No newline at end of file diff -urN ../ejbca_4_0_6/src/samples/plugins/mypublisher/src/com/example/mypublisher/MyPublisher.java ./src/samples/plugins/mypublisher/src/com/example/mypublisher/MyPublisher.java --- ../ejbca_4_0_6/src/samples/plugins/mypublisher/src/com/example/mypublisher/MyPublisher.java 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mypublisher/src/com/example/mypublisher/MyPublisher.java 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,74 @@ +/************************************************************************* + * * + * EJBCA: The OpenSource Certificate Authority * + * * + * This software is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or any later version. * + * * + * See terms of license at gnu.org. * + * * + *************************************************************************/ + +package com.example.mypublisher; + +import java.security.cert.Certificate; +import java.util.Properties; + +import org.apache.log4j.Logger; +import org.ejbca.core.model.log.Admin; +import org.ejbca.core.model.ra.ExtendedInformation; + +import org.ejbca.core.model.ca.publisher.ICustomPublisher; +import org.ejbca.core.model.ca.publisher.PublisherConnectionException; +import org.ejbca.core.model.ca.publisher.PublisherException; + + +/** + * This is a class used for testing and example purposes. + * It is supposed to illustrate how to implement a custom publisher in EJBCA 4 + * + * + * @version $Id$ + */ +public class MyPublisher implements ICustomPublisher{ + + private static Logger log = Logger.getLogger(MyPublisher.class); + + /** + * Creates a new instance of DummyCustomPublisher + */ + public MyPublisher() {} + + /** + * @see org.ejbca.core.model.ca.publisher.ICustomPublisher#init(java.util.Properties) + */ + public void init(Properties properties) { + log.debug("Initializing DummyCustomPublisher " ); + } + + /** + * @see org.ejbca.core.model.ca.publisher.ICustomPublisher#storeCertificate(org.ejbca.core.model.log.Admin, java.security.cert.Certificate, java.lang.String, java.lang.String, int, int) + */ + public boolean storeCertificate(Admin admin, Certificate incert, String username, String password, String userDN, String cafp, int status, int type, long revocationDate, int revocationReason, String tag, int certificateProfileId, long lastUpdate, ExtendedInformation extendedinformation) throws PublisherException { + log.debug("DummyCustomPublisher, Storing Certificate for user: " + username); + return true; + } + + /** + * @see org.ejbca.core.model.ca.publisher.ICustomPublisher#storeCRL(org.ejbca.core.model.log.Admin, byte[], java.lang.String, int) + */ + public boolean storeCRL(Admin admin, byte[] incrl, String cafp, int number, String userDN) throws PublisherException { + log.debug("DummyCustomPublisher, Storing CRL"); + return true; + } + + /** + * @see org.ejbca.core.model.ca.publisher.ICustomPublisher#testConnection(org.ejbca.core.model.log.Admin) + */ + public void testConnection(Admin admin) throws PublisherConnectionException { + log.debug("DummyCustomPublisher, Testing connection"); + } + +} diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/build.xml ./src/samples/plugins/mywebapps/build.xml --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/build.xml 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/build.xml 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + my-ejbs.jar + + + + my-servlets.war + /ejbca/pluginweb + + +]]> + + + + + diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/README ./src/samples/plugins/mywebapps/README --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/README 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/README 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,14 @@ +WebApp EJBCA Plugin Demo - EJBCA 4.X +==================================== + +This sample plugin installs a webapp at the URL: http://localhost:8080/ejbca/pluginweb + +The web apps illustrates the plugin scheme including how to access internal +EJBCA CA resources. + +One of the applications extends the EJBCA database with another table and +accesses it using an entity bean, EJB3 and Hiberbate. That is, the same +stuff that EJBCA is made of. + +Note that this plugin adds a table "MyCounterData" to the EJBCA database schema. + diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/resources/META-INF/orm-database.xml ./src/samples/plugins/mywebapps/resources/META-INF/orm-database.xml --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/resources/META-INF/orm-database.xml 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/resources/META-INF/orm-database.xml 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + \ No newline at end of file diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/resources/META-INF/persistence.xml ./src/samples/plugins/mywebapps/resources/META-INF/persistence.xml --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/resources/META-INF/persistence.xml 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/resources/META-INF/persistence.xml 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,17 @@ + + + + org.hibernate.ejb.HibernatePersistence + @1@ + META-INF/orm-database.xml + + + + + + + \ No newline at end of file diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/ejb/MySimpleBean.java ./src/samples/plugins/mywebapps/src/com/example/ejb/MySimpleBean.java --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/ejb/MySimpleBean.java 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/src/com/example/ejb/MySimpleBean.java 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,66 @@ +package com.example.ejb; + +import javax.ejb.Stateless; +import javax.ejb.TransactionAttribute; +import javax.ejb.TransactionAttributeType; +import javax.ejb.Local; + +import org.apache.log4j.Logger; + +import com.example.entity.MyCounterData; + +import com.example.web.Counter; + +import javax.persistence.PersistenceContext; +import javax.persistence.EntityManager; + + +import javax.annotation.PostConstruct; + +@Stateless(name="mysimplebean") +@TransactionAttribute(TransactionAttributeType.REQUIRED) +@Local(MySimpleBeanLocal.class) +public class MySimpleBean implements MySimpleBeanLocal { + + private final static Logger log = Logger.getLogger(MySimpleBean.class); + + private final static Integer FIXED_PK = 1; + + @PersistenceContext(unitName = "plugin") + private EntityManager entityManager; + + + @PostConstruct + public void postConstruct() { + log.info("My Simple Bean is running!"); + } + + @Override + public int updateCounter () { + MyCounterData ac = getCurrent (); + if (ac == null) { + ac = new MyCounterData(); + ac.setPk(FIXED_PK); + ac.setCounter(1); + entityManager.persist (ac); + return 1; + } + int i = ac.getCounter () + 1; + ac.setCounter(i); + entityManager.merge (ac); + return i; + } + + @Override + public MyCounterData getCurrent() { + return entityManager.find (MyCounterData.class, FIXED_PK); + } + + @Override + public void clearCounter() { + MyCounterData ac = getCurrent (); + if (ac != null) { + entityManager.remove (ac); + } + } +} diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/ejb/MySimpleBeanLocal.java ./src/samples/plugins/mywebapps/src/com/example/ejb/MySimpleBeanLocal.java --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/ejb/MySimpleBeanLocal.java 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/src/com/example/ejb/MySimpleBeanLocal.java 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,13 @@ +package com.example.ejb; + +import com.example.entity.MyCounterData; + +public interface MySimpleBeanLocal { + + public int updateCounter (); + + public MyCounterData getCurrent (); + + public void clearCounter(); + +} diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/entity/MyCounterData.java ./src/samples/plugins/mywebapps/src/com/example/entity/MyCounterData.java --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/entity/MyCounterData.java 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/src/com/example/entity/MyCounterData.java 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,23 @@ +package com.example.entity; + +import java.io.Serializable; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity +@Table(name = "MyCounterData") +public class MyCounterData implements Serializable { + + private static final long serialVersionUID = -8493105317760641442L; + + private int pk; + private int counter; + + public void setPk (int pk) { this.pk = pk; } + public int getPk () { return pk; } + + public void setCounter (int counter) { this.counter = counter; } + public int getCounter () { return counter; } + +} diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/web/Counter.java ./src/samples/plugins/mywebapps/src/com/example/web/Counter.java --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/web/Counter.java 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/src/com/example/web/Counter.java 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,60 @@ +package com.example.web; + +import javax.ejb.EJB; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +import com.example.ejb.MySimpleBeanLocal; +import com.example.entity.MyCounterData; + +public class Counter extends HttpServlet { + + private static final long serialVersionUID = 1L; + private static final Logger log = Logger.getLogger(Counter.class); + + private static final String UPDATE = "update"; + private static final String CLEAR = "clear"; + + @EJB + private MySimpleBeanLocal mysimplebean; + + /** + * This is a demo servlet that operates on a counter in a database table + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + response.setContentType ("text/html; charset=utf-8"); + response.setHeader ("Pragma", "No-Cache"); + response.setDateHeader ("EXPIRES", 0); + StringBuffer out = new StringBuffer ("

Counter Sample

"); + String parm = request.getParameter (UPDATE); + if (parm == null) { + parm = request.getParameter (CLEAR); + if (parm == null) { + MyCounterData ac = mysimplebean.getCurrent(); + out.append("Current counter status: "); + if (ac == null) { + out.append ("No hits so far..."); + } else { + out.append(ac.getCounter ()); + } + } else { + mysimplebean.clearCounter (); + out.append("Counter was cleared"); + } + } else { + out.append("Counter's new value: ").append(mysimplebean.updateCounter()); + } + out.append("

Update counter
" + + "Clear counter"); + response.getOutputStream ().print (out.toString ()); + log.info("Counting..."); + } // doGet + +} diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/web/ListCAs.java ./src/samples/plugins/mywebapps/src/com/example/web/ListCAs.java --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/src/com/example/web/ListCAs.java 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/src/com/example/web/ListCAs.java 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,49 @@ +package com.example.web; + +import java.io.IOException; + +import javax.ejb.EJB; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; + +import org.ejbca.core.model.log.Admin; + +import org.ejbca.core.ejb.ca.caadmin.CaSessionLocal; +/** + * This is a demo servlet that list all CAs in the system + */ +public class ListCAs extends HttpServlet { + + private static final long serialVersionUID = 1L; + private final static Logger log = Logger.getLogger(ListCAs.class); + + @EJB + private CaSessionLocal caSession; + + /** + * This is a demo servlet that list all CAs in the system + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + response.setContentType ("text/html; charset=utf-8"); + response.setHeader ("Pragma", "No-Cache"); + response.setDateHeader ("EXPIRES", 0); + StringBuffer out = new StringBuffer ("

List CAs

"); + Admin admin = new Admin(Admin.TYPE_INTERNALUSER, request.getRemoteAddr()); + for (Integer caid : caSession.getAvailableCAs(admin)) { + try { + out.append("
").append(caSession.getCA(admin, caid).getName()); + } catch (Exception e) { + throw new IOException (e); + } + } + out.append(""); + response.getOutputStream ().print (out.toString ()); + log.info("Listed a few CAs..."); + } // doGet + +} diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/web/index.jsp ./src/samples/plugins/mywebapps/web/index.jsp --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/web/index.jsp 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/web/index.jsp 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,7 @@ + + +

Welcome to the Plugin Web!

+List CAs (calls EJBCA core)
+Counter (uses EJBCA database, hibernate, ejb3, logging, datasource) + + diff -urN ../ejbca_4_0_6/src/samples/plugins/mywebapps/web.xml ./src/samples/plugins/mywebapps/web.xml --- ../ejbca_4_0_6/src/samples/plugins/mywebapps/web.xml 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/mywebapps/web.xml 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,32 @@ + + + + + My Web Plugins + + + ListCAs + com.example.web.ListCAs + + + + Counter + com.example.web.Counter + + + + ListCAs + /listcas + + + + Counter + /counter + + + diff -urN ../ejbca_4_0_6/src/samples/plugins/parm-test-build.xml ./src/samples/plugins/parm-test-build.xml --- ../ejbca_4_0_6/src/samples/plugins/parm-test-build.xml 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/parm-test-build.xml 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -urN ../ejbca_4_0_6/src/samples/plugins/README ./src/samples/plugins/README --- ../ejbca_4_0_6/src/samples/plugins/README 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/README 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,16 @@ +This directory contains a couple of sample plugins that can be used as +a starting point for building "real" EJBCA plugins. Real plugins should +preferably be managed outside of the EJBCA source tree. + +By performing + + ant deploy -Dejbca.plugin.conf.path=ABSOLUTEPATHTOEJBCA/src/samples/plugins + +all the sample plugins will be added to EJBCA without any configuration. + +A subsequent "ant deploy" will restore EJBCA in its unextended state. + +The file EJBCA/conf/plugins/plugin.properties.sample describes how +a plugin build gets access to the core EJBCA environment. + + \ No newline at end of file diff -urN ../ejbca_4_0_6/src/samples/plugins/test-mypublisher.properties ./src/samples/plugins/test-mypublisher.properties --- ../ejbca_4_0_6/src/samples/plugins/test-mypublisher.properties 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/test-mypublisher.properties 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,4 @@ +# This file is intended for testing and demo of the EJBCA plugin samples + +# The mandatory path to the ANT build file +plugin.ejbca.ant.file ${ejbca.home}/src/samples/plugins/mypublisher/build.xml diff -urN ../ejbca_4_0_6/src/samples/plugins/test-mywebapps.properties ./src/samples/plugins/test-mywebapps.properties --- ../ejbca_4_0_6/src/samples/plugins/test-mywebapps.properties 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/test-mywebapps.properties 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,4 @@ +# This file is intended for testing and demo of the EJBCA plugin samples + +# The mandatory path to the ANT build file +plugin.ejbca.ant.file ${ejbca.home}/src/samples/plugins/mywebapps/build.xml diff -urN ../ejbca_4_0_6/src/samples/plugins/test-plugin-builder.properties ./src/samples/plugins/test-plugin-builder.properties --- ../ejbca_4_0_6/src/samples/plugins/test-plugin-builder.properties 1970-01-01 01:00:00.000000000 +0100 +++ ./src/samples/plugins/test-plugin-builder.properties 2011-12-25 12:00:26.000000000 +0100 @@ -0,0 +1,10 @@ +# This file is intended for testing the plugin builder interface itself + +# The mandatory path to the ANT build file +plugin.ejbca.ant.file ${ejbca.home}/src/samples/plugins/parm-test-build.xml + +# We test the target as well +plugin.ejbca.ant.target test-me + +# And a custom property +plugin.ejbca.ant.custom.testparam did we get this