summaryrefslogtreecommitdiffstats
path: root/base/tps
diff options
context:
space:
mode:
authorMatthew Harmsen <mharmsen@redhat.com>2014-09-03 21:07:07 -0700
committerMatthew Harmsen <mharmsen@redhat.com>2014-09-03 21:07:07 -0700
commitabaa8473f51a5c436a2952920625b7447e226b29 (patch)
treee9e731a6e4eb8be63f1a74fffad101332b060afe /base/tps
parent4dbec5fe960a89b7ced3028e000b5695b6d9aac7 (diff)
downloadpki-abaa8473f51a5c436a2952920625b7447e226b29.tar.gz
pki-abaa8473f51a5c436a2952920625b7447e226b29.tar.xz
pki-abaa8473f51a5c436a2952920625b7447e226b29.zip
Rename pki-tps-tomcat to pki-tps
* PKI TRAC Ticket #1017 - Rename pki-tps-tomcat to pki-tps
Diffstat (limited to 'base/tps')
-rw-r--r--base/tps/CMakeLists.txt45
-rw-r--r--base/tps/LICENSE469
-rw-r--r--base/tps/man/man5/pki-tps-connector.5217
-rw-r--r--base/tps/man/man5/pki-tps-profile.5204
-rw-r--r--base/tps/setup/CMakeLists.txt6
-rw-r--r--base/tps/setup/registry_instance60
-rw-r--r--base/tps/shared/applets/1.2.4122DFB4.ijcbin0 -> 11944 bytes
-rwxr-xr-xbase/tps/shared/applets/1.2.416DA155.ijcbin0 -> 11945 bytes
-rwxr-xr-xbase/tps/shared/applets/1.3.42260AFA.ijcbin0 -> 13117 bytes
-rw-r--r--base/tps/shared/applets/1.3.4255CC01.ijcbin0 -> 14909 bytes
-rwxr-xr-xbase/tps/shared/applets/1.3.42659461.ijcbin0 -> 14879 bytes
-rw-r--r--base/tps/shared/applets/1.3.427BDDB8.ijcbin0 -> 14527 bytes
-rwxr-xr-xbase/tps/shared/applets/1.3.44724DDE.ijcbin0 -> 14529 bytes
-rwxr-xr-xbase/tps/shared/applets/1.3.45787308.ijcbin0 -> 14893 bytes
-rw-r--r--base/tps/shared/applets/1.4.499dc06c.ijcbin0 -> 14912 bytes
-rw-r--r--base/tps/shared/applets/1.4.4d40a449.ijcbin0 -> 14874 bytes
-rw-r--r--base/tps/shared/applets/3FD00877.ijcbin0 -> 13662 bytes
-rw-r--r--base/tps/shared/applets/4003196C.ijcbin0 -> 13683 bytes
-rw-r--r--base/tps/shared/applets/402428AD.ijcbin0 -> 13699 bytes
-rw-r--r--base/tps/shared/applets/404E4697.ijcbin0 -> 11995 bytes
-rw-r--r--base/tps/shared/applets/4122DFB4.ijcbin0 -> 11944 bytes
-rwxr-xr-xbase/tps/shared/applets/listappletdates42
-rw-r--r--base/tps/shared/applets/readme.txt52
-rw-r--r--base/tps/shared/conf/CMakeLists.txt8
-rw-r--r--base/tps/shared/conf/CS.cfg.in1375
-rw-r--r--base/tps/shared/conf/Catalina/localhost/tps.xml37
-rw-r--r--base/tps/shared/conf/acl.ldif33
-rw-r--r--base/tps/shared/conf/acl.properties42
-rw-r--r--base/tps/shared/conf/auth-method.properties27
-rw-r--r--base/tps/shared/conf/catalina.policy182
-rw-r--r--base/tps/shared/conf/catalina.properties87
-rw-r--r--base/tps/shared/conf/database.ldif9
-rw-r--r--base/tps/shared/conf/db.ldif54
-rw-r--r--base/tps/shared/conf/index.ldif84
-rw-r--r--base/tps/shared/conf/jk2.manifest2
-rw-r--r--base/tps/shared/conf/jk2.properties31
-rw-r--r--base/tps/shared/conf/jkconf.ant.xml55
-rw-r--r--base/tps/shared/conf/jkconfig.manifest2
-rw-r--r--base/tps/shared/conf/logging.properties70
-rw-r--r--base/tps/shared/conf/manager.ldif46
-rw-r--r--base/tps/shared/conf/phoneHome.xml10
-rw-r--r--base/tps/shared/conf/registry.cfg5
-rw-r--r--base/tps/shared/conf/schema.ldif58
-rw-r--r--base/tps/shared/conf/server-minimal.xml29
-rw-r--r--base/tps/shared/conf/server.xml258
-rw-r--r--base/tps/shared/conf/shm.manifest2
-rw-r--r--base/tps/shared/conf/tomcat-jk2.manifest7
-rw-r--r--base/tps/shared/conf/tomcat-users.xml45
-rw-r--r--base/tps/shared/conf/tomcat6.conf58
-rw-r--r--base/tps/shared/conf/uriworkermap.properties18
-rw-r--r--base/tps/shared/conf/vlv.ldif51
-rw-r--r--base/tps/shared/conf/vlvtasks.ldif28
-rw-r--r--base/tps/shared/conf/web.xml993
-rw-r--r--base/tps/shared/conf/workers.properties209
-rw-r--r--base/tps/shared/conf/workers.properties.minimal22
-rw-r--r--base/tps/shared/conf/workers2.properties136
-rw-r--r--base/tps/shared/conf/workers2.properties.minimal60
-rwxr-xr-xbase/tps/shared/webapps/tps/404.html145
-rwxr-xr-xbase/tps/shared/webapps/tps/500.html138
-rw-r--r--base/tps/shared/webapps/tps/GenUnexpectedError.template67
-rw-r--r--base/tps/shared/webapps/tps/WEB-INF/velocity.properties13
-rw-r--r--base/tps/shared/webapps/tps/WEB-INF/web.xml297
-rw-r--r--base/tps/shared/webapps/tps/index.html73
-rw-r--r--base/tps/shared/webapps/tps/js/account.js37
-rw-r--r--base/tps/shared/webapps/tps/js/activity.js97
-rw-r--r--base/tps/shared/webapps/tps/js/audit.js232
-rw-r--r--base/tps/shared/webapps/tps/js/authenticator.js109
-rw-r--r--base/tps/shared/webapps/tps/js/cert.js100
-rw-r--r--base/tps/shared/webapps/tps/js/config.js51
-rw-r--r--base/tps/shared/webapps/tps/js/connector.js109
-rw-r--r--base/tps/shared/webapps/tps/js/group.js232
-rw-r--r--base/tps/shared/webapps/tps/js/profile-mapping.js109
-rw-r--r--base/tps/shared/webapps/tps/js/profile.js109
-rw-r--r--base/tps/shared/webapps/tps/js/selftest.js88
-rw-r--r--base/tps/shared/webapps/tps/js/token.js258
-rw-r--r--base/tps/shared/webapps/tps/js/tps.js231
-rw-r--r--base/tps/shared/webapps/tps/js/user.js150
-rw-r--r--base/tps/shared/webapps/tps/services.template106
-rw-r--r--base/tps/shared/webapps/tps/ui/activities.html83
-rw-r--r--base/tps/shared/webapps/tps/ui/activity.html47
-rw-r--r--base/tps/shared/webapps/tps/ui/audit.html134
-rw-r--r--base/tps/shared/webapps/tps/ui/authenticator.html131
-rw-r--r--base/tps/shared/webapps/tps/ui/authenticators.html74
-rw-r--r--base/tps/shared/webapps/tps/ui/cert.html49
-rw-r--r--base/tps/shared/webapps/tps/ui/certs.html87
-rw-r--r--base/tps/shared/webapps/tps/ui/config.html116
-rw-r--r--base/tps/shared/webapps/tps/ui/connector.html131
-rw-r--r--base/tps/shared/webapps/tps/ui/connectors.html75
-rw-r--r--base/tps/shared/webapps/tps/ui/group.html125
-rw-r--r--base/tps/shared/webapps/tps/ui/groups.html75
-rw-r--r--base/tps/shared/webapps/tps/ui/home.html60
-rw-r--r--base/tps/shared/webapps/tps/ui/index.html429
-rw-r--r--base/tps/shared/webapps/tps/ui/profile-mapping.html131
-rw-r--r--base/tps/shared/webapps/tps/ui/profile-mappings.html75
-rw-r--r--base/tps/shared/webapps/tps/ui/profile.html131
-rw-r--r--base/tps/shared/webapps/tps/ui/profiles.html75
-rw-r--r--base/tps/shared/webapps/tps/ui/selftest.html42
-rw-r--r--base/tps/shared/webapps/tps/ui/selftests.html79
-rw-r--r--base/tps/shared/webapps/tps/ui/token.html96
-rw-r--r--base/tps/shared/webapps/tps/ui/tokens.html135
-rw-r--r--base/tps/shared/webapps/tps/ui/user.html57
-rw-r--r--base/tps/shared/webapps/tps/ui/users.html75
-rw-r--r--base/tps/src/CMakeLists.txt170
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSPhoneHome.java95
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSServlet.java65
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSSession.java174
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java231
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSTokenPolicy.java158
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java425
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java92
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/authentication/AuthenticationManager.java287
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java148
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java1045
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/CAEnrollCertResponse.java52
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java760
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/CARenewCertResponse.java52
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/CARetrieveCertResponse.java45
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/CARevokeCertResponse.java39
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/ConnectionManager.java229
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/KRARecoverKeyResponse.java51
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java322
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/KRAServerSideKeyGenResponse.java51
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/RemoteRequestHandler.java91
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/RemoteResponse.java40
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java41
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java65
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSCreateKeySetDataResponse.java41
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSEncryptDataResponse.java41
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java448
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/cms/TKSResponse.java40
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/AuthenticatorDatabase.java143
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/AuthenticatorRecord.java28
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ConfigDatabase.java191
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ConfigRecord.java126
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ConfigService.java135
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ConnectorDatabase.java242
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ConnectorRecord.java28
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ProfileDatabase.java144
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ProfileMappingDatabase.java144
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ProfileMappingRecord.java28
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/config/ProfileRecord.java28
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/dbs/ActivityDatabase.java100
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/dbs/ActivityRecord.java214
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/dbs/TPSCertDatabase.java71
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/dbs/TPSCertRecord.java313
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java68
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/dbs/TokenRecord.java271
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java589
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/installer/CAInfoPanel.java171
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/installer/DRMInfoPanel.java154
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/installer/TKSInfoPanel.java150
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/installer/TPSInstaller.java124
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/main/AttributeSpec.java71
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java456
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/main/PKCS11Obj.java689
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/AppletInfo.java115
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java270
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/EnrolledCertsInfo.java262
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java2789
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java66
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java2404
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/profile/BaseTokenProfileResolver.java38
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/profile/MappingTokenProfileResolver.java294
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/profile/TokenProfileParams.java145
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/profile/TokenProfileResolverManager.java114
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/ActivityService.java177
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/AuthenticatorService.java350
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/ConnectorService.java350
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/ProfileMappingService.java341
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/ProfileService.java351
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/TPSApplication.java105
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/TPSCertService.java179
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java153
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java562
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/selftests/TPSPresence.java187
-rw-r--r--base/tps/src/org/dogtagpki/server/tps/selftests/TPSValidity.java197
-rw-r--r--base/tps/src/pki-tps.mf3
177 files changed, 29919 insertions, 0 deletions
diff --git a/base/tps/CMakeLists.txt b/base/tps/CMakeLists.txt
new file mode 100644
index 000000000..dac32876c
--- /dev/null
+++ b/base/tps/CMakeLists.txt
@@ -0,0 +1,45 @@
+project(tps Java)
+
+add_subdirectory(src)
+
+# install files
+add_subdirectory(setup)
+add_subdirectory(shared/conf)
+
+# install manual pages
+install(
+ DIRECTORY
+ man/
+ DESTINATION
+ ${MAN_INSTALL_DIR}
+ FILE_PERMISSIONS
+ OWNER_READ OWNER_WRITE
+ GROUP_READ
+ WORLD_READ
+)
+
+# install directories
+install(
+ DIRECTORY
+ shared/
+ DESTINATION
+ ${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}/${PROJECT_NAME}
+ PATTERN
+ "CMakeLists.txt" EXCLUDE
+ PATTERN
+ "conf/CS.cfg.in" EXCLUDE
+)
+
+# install empty directories
+install(
+ DIRECTORY
+ DESTINATION
+ ${VAR_INSTALL_DIR}/lock/pki/tps
+)
+
+install(
+ DIRECTORY
+ DESTINATION
+ ${VAR_INSTALL_DIR}/run/pki/tps
+)
+
diff --git a/base/tps/LICENSE b/base/tps/LICENSE
new file mode 100644
index 000000000..af64f0781
--- /dev/null
+++ b/base/tps/LICENSE
@@ -0,0 +1,469 @@
+This Program 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; version 2.1 of the License.
+
+This Program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this Program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
diff --git a/base/tps/man/man5/pki-tps-connector.5 b/base/tps/man/man5/pki-tps-connector.5
new file mode 100644
index 000000000..85b6792d6
--- /dev/null
+++ b/base/tps/man/man5/pki-tps-connector.5
@@ -0,0 +1,217 @@
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH pki-tps-connector 5 "April 22, 2014" "version 10.2" "PKI TPS Connector Configuration" Dogtag Team
+.\" Please adjust this date whenever revising the man page.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for man page specific macros, see man(7)
+.SH NAME
+PKI TPS Connector Configuration
+
+.SH LOCATION
+/var/lib/pki/<instance>/conf/tps/CS.cfg
+
+.SH DESCRIPTION
+
+TPS connector provides a mechanism for TPS to communicate with other PKI subsystems.
+There are three supported connector types: CA, KRA, and TKS. The connectors are
+defined using properties in the TPS configuration file.
+
+.SH CA CONNECTOR
+
+A CA connector is defined using properties that begin with tps.connector.ca<n> where
+n is a positive integer indicating the ID of the CA connector.
+
+.SS tps.connector.ca<n>.enable
+
+This property contains a boolean value indicating whether the connector is enabled.
+
+.SS tps.connector.ca<n>.host
+
+In no-failover configuration, the property contains the hostname of the CA.
+
+In failover configuration, the property contains a list of hostnames and port numbers
+of the CA subsystems. The format is hostname:port separated by spaces.
+
+.SS tps.connector.ca<n>.port
+
+In no-failover configuration, the property contains the port number of the CA.
+
+.SS tps.connector.ca<n>.nickName
+
+This property contains the nickname of the TPS subsystem certificate for SSL client
+authentication to the CA.
+
+.SS tps.connector.ca<n>.minHttpConns
+
+This property contains the minimum number of HTTP connections.
+
+.SS tps.connector.ca<n>.maxHttpConns
+
+This property contains the maximum number of HTTP connections.
+
+.SS tps.connector.ca<n>.uri.<op>
+
+This property contains the URI to contact CA for the operation <op>.
+Example ops: enrollment, renewal, revoke, unrevoke.
+
+.SS tps.connector.ca<n>.timeout
+
+This property contains the connection timeout.
+
+.SH KRA CONNECTOR
+
+A KRA connector is defined using properties that begin with tps.connector.kra<n> where
+n is a positive integer indicating the ID of the KRA connector.
+
+.SS tps.connector.kra<n>.enable
+
+This property contains a boolean value indicating whether the connector is enabled.
+
+.SS tps.connector.kra<n>.host
+
+In no-failover configuration, the property contains the hostname of the KRA.
+
+In failover configuration, the property contains a list of hostnames and port numbers
+of the KRA subsystems. The format is hostname:port separated by spaces.
+
+.SS tps.connector.kra<n>.port
+
+In no-failover configuration, the property contains the port number of the KRA.
+
+.SS tps.connector.kra<n>.nickName
+
+This property contains the nickname of the TPS subsystem certificate for SSL client
+authentication to the KRA.
+
+.SS tps.connector.kra<n>.minHttpConns
+
+This property contains the minimum number of HTTP connections.
+
+.SS tps.connector.kra<n>.maxHttpConns
+
+This property contains the maximum number of HTTP connections.
+
+.SS tps.connector.kra<n>.uri.<op>
+
+This property contains the URI to contact KRA for the operation <op>.
+Example ops: GenerateKeyPair, TokenKeyRecovery.
+
+.SS tps.connector.kra<n>.timeout
+
+This property contains the connection timeout.
+
+.SH TKS CONNECTOR
+
+A TKS connector is defined using properties that begin with tps.connector.tks<n> where
+n is a positive integer indicating the ID of the TKS connector.
+
+.SS tps.connector.tks<n>.enable
+
+This property contains a boolean value indicating whether the connector is enabled.
+
+.SS tps.connector.tks<n>.host
+
+In no-failover configuration, the property contains the hostname of the TKS.
+
+In failover configuration, the property contains a list of hostnames and port numbers
+of the TKS subsystems. The format is hostname:port separated by spaces.
+
+.SS tps.connector.tks<n>.port
+
+In no-failover configuration, the property contains the port number of the TKS.
+
+.SS tps.connector.tks<n>.nickName
+
+This property contains the nickname of the TPS subsystem certificate for SSL client
+authentication to the TKS.
+
+.SS tps.connector.tks<n>.minHttpConns
+
+This property contains the minimum number of HTTP connections.
+
+.SS tps.connector.tks<n>.maxHttpConns
+
+This property contains the maximum number of HTTP connections.
+
+.SS tps.connector.tks<n>.uri.<op>
+
+This property contains the URI to contact TKS for the operation <op>.
+Example ops: computeRandomData, computeSessionKey, createKeySetData, encryptData.
+
+.SS tps.connector.tks<n>.timeout
+
+This property contains the connection timeout.
+
+.SS tps.connector.tks<n>.generateHostChallenge
+
+This property contains a boolean value indicating whether to generate host challenge.
+
+.SS tps.connector.tks<n>.serverKeygen
+
+This property contains a boolean value indicating whether to generate keys on server side.
+
+.SS tps.connector.tks<n>.keySet
+
+This property contains the key set to be used on TKS.
+
+.SS tps.connector.tks<n>.tksSharedSymKeyName
+
+This property contains the shared secret key name.
+
+.SH EXAMPLE
+
+.nf
+tps.connector.ca1.enable=true
+tps.connector.ca1.host=server.example.com
+tps.connector.ca1.port=8443
+tps.connector.ca1.minHttpConns=1
+tps.connector.ca1.maxHttpConns=15
+tps.connector.ca1.nickName=subsystemCert cert-pki-tomcat TPS
+tps.connector.ca1.timeout=30
+tps.connector.ca1.uri.enrollment=/ca/ee/ca/profileSubmitSSLClient
+tps.connector.ca1.uri.renewal=/ca/ee/ca/profileSubmitSSLClient
+tps.connector.ca1.uri.revoke=/ca/ee/subsystem/ca/doRevoke
+tps.connector.ca1.uri.unrevoke=/ca/ee/subsystem/ca/doUnrevoke
+
+tps.connector.kra1.enable=true
+tps.connector.kra1.host=server.example.com
+tps.connector.kra1.port=8443
+tps.connector.kra1.minHttpConns=1
+tps.connector.kra1.maxHttpConns=15
+tps.connector.kra1.nickName=subsystemCert cert-pki-tomcat TPS
+tps.connector.kra1.timeout=30
+tps.connector.kra1.uri.GenerateKeyPair=/kra/agent/kra/GenerateKeyPair
+tps.connector.kra1.uri.TokenKeyRecovery=/kra/agent/kra/TokenKeyRecovery
+
+tps.connector.tks1.enable=true
+tps.connector.tks1.host=server.example.com
+tps.connector.tks1.port=8443
+tps.connector.tks1.minHttpConns=1
+tps.connector.tks1.maxHttpConns=15
+tps.connector.tks1.nickName=subsystemCert cert-pki-tomcat TPS
+tps.connector.tks1.timeout=30
+tps.connector.tks1.generateHostChallenge=true
+tps.connector.tks1.serverKeygen=false
+tps.connector.tks1.keySet=defKeySet
+tps.connector.tks1.tksSharedSymKeyName=sharedSecret
+tps.connector.tks1.uri.computeRandomData=/tks/agent/tks/computeRandomData
+tps.connector.tks1.uri.computeSessionKey=/tks/agent/tks/computeSessionKey
+tps.connector.tks1.uri.createKeySetData=/tks/agent/tks/createKeySetData
+tps.connector.tks1.uri.encryptData=/tks/agent/tks/encryptData
+.fi
+
+.SH AUTHORS
+Dogtag Team <pki-devel@redhat.com>.
+
+.SH COPYRIGHT
+Copyright (c) 2014 Red Hat, Inc. This is licensed under the GNU General Public License, version 2 (GPLv2). A copy of this license is available at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
diff --git a/base/tps/man/man5/pki-tps-profile.5 b/base/tps/man/man5/pki-tps-profile.5
new file mode 100644
index 000000000..2b864a05f
--- /dev/null
+++ b/base/tps/man/man5/pki-tps-profile.5
@@ -0,0 +1,204 @@
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH pki-tps-connector 5 "May 6, 2014" "version 10.2" "PKI TPS Profile Configuration" Dogtag Team
+.\" Please adjust this date whenever revising the man page.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for man page specific macros, see man(7)
+.SH NAME
+PKI TPS Profile Configuration
+
+.SH LOCATION
+/var/lib/pki/<instance>/conf/tps/CS.cfg
+
+.SH DESCRIPTION
+
+Token profiles are defined using properties in the TPS configuration file.
+
+.SS Enrollment Operation For CoolKey
+
+The following property sets the size of the key the token should generate:
+
+.B op.enroll.<tokenType>.keyGen.<keyType>.keySize=1024
+
+The maximum value is 1024.
+
+The following properties specify the PKCS11 attributes to set on the token:
+
+.nf
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.encrypt=false
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.sign=true
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.signRecover=true
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.decrypt=false
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.derive=false
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.unwrap=false
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.wrap=false
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.verifyRecover=true
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.verify=true
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.sensitive=true
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.private=true
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyCapabilities.token=true
+.fi
+
+The following property specifies the CUID shown in the certificate:
+
+.B op.enroll.<tokenType>.keyGen.<keyType>.cuid_label
+
+The following property specifies the token name:
+
+.B op.enroll.<tokenType>.keyGen.<keyType>.label
+
+The following variables can be used in the token name:
+ \fB$pretty_cuid$\fR - Pretty Print CUID (i.e. 4090-0062-FF02-0000-0B9C)
+ \fB$cuid$\fR - CUID (i.e. 40900062FF0200000B9C)
+ \fB$msn$\fR - MSN
+ \fB$userid$\fR - User ID
+ \fB$profileId$\fR - Profile ID
+
+All resulting labels for co-existing keys on the same token must be unique.
+
+The following property determines whether TPS will overwrite key and certificate if they already exist:
+
+.B op.enroll.<tokenType>.keyGen.<keyType>.overwrite=true|false
+
+The following properties specify name PKCS11 object IDs:
+
+.nf
+.B op.enroll.<tokenType>.keyGen.<keyType>.certId=C1
+.B op.enroll.<tokenType>.keyGen.<keyType>.certAttrId=c1
+.B op.enroll.<tokenType>.keyGen.<keyType>.privateKeyAttrId=k2
+.B op.enroll.<tokenType>.keyGen.<keyType>.publicKeyAttrId=k3
+.B op.enroll.<tokenType>.keyGen.<keyType>.privateKeyNumber=2
+.B op.enroll.<tokenType>.keyGen.<keyType>.publicKeyNumber=3
+.fi
+
+Lower case letters signify objects containing PKCS11 object attributes
+in the format described below:
+ \fBc\fR - An object containing PKCS11 attributes for a certificate.
+ \fBk\fR - An object containing PKCS11 attributes for a public or private key
+ \fBr\fR - An object containing PKCS11 attributes for an "reader".
+
+Upper case letters signify objects containing raw data corresponding to
+the lower case letters described above. For example, object \fBC0\fR
+contains raw data corresponding to object \fBc0\fR.
+ \fBC\fR - This object contains an entire DER cert, and nothing else.
+ \fBK\fR - This object contains a MUSCLE "key blob". TPS does not use this.
+
+The following properties specify the algorithm, the key size, the key usage,
+and which PIN user should be granted:
+
+.nf
+.B op.enroll.<tokenType>.keyGen.<keyType>.alg=2
+.B op.enroll.<tokenType>.keyGen.<keyType>.keySize=1024
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyUsage=0
+.B op.enroll.<tokenType>.keyGen.<keyType>.keyUser=0
+.fi
+
+The valid algorithms are:
+ \fB2\fR - RSA
+ \fB5\fR - ECC
+
+For ECC, the valid key sizes are 256 and 384.
+
+Use privilege of the generated private key, or 15 if all users have use privilege for the private key.
+Valid usages: (only specifies the usage for the private key)
+ \fB0\fR - default usage (Signing only for this APDU)
+ \fB1\fR - signing only
+ \fB2\fR - decryption only
+ \fB3\fR - signing and decryption
+
+The following property determines whether to enable writing of PKCS11 cache object to the token:
+
+.B op.enroll.<tokenType>.pkcs11obj.enable=true|false
+
+The following property determines whether to enable compression for writing of PKCS11 cache object to the token:
+
+.B op.enroll.<tokenType>.pkcs11obj.compress.enable=true|false
+
+The following property determines the maximum number of retries before blocking the token:
+
+.B op.enroll.<tokenType>.pinReset.pin.maxRetries=127
+
+The maximum value is 127.
+
+There is a special case of tokenType userKeyTemporary.
+Make sure the profile specified by the profileId to have
+short validity period (e.g. 7 days) for the certificate.
+
+.nf
+.B op.enroll.userKey.keyGen.<keyType>.publisherId=fileBasedPublisher
+.B op.enroll.userKeyTemporary.keyGen.<keyType>.publisherId=fileBasedPublisher
+.fi
+
+The folowing property describes the scheme used for recovery:
+
+.nf
+.B op.enroll.<tokenType>.keyGen.<keyType>.recovery.<tokenState>.scheme=GenerateNewKey
+.fi
+
+The three recovery schemes supported are:
+ \fBGenerateNewKey\fR - Generate a new cert for the encryption cert.
+ \fBRecoverLast\fR - Recover the most recent cert for the encryption cert.
+ \fBGenerateNewKeyandRecoverLast\fR - Generate new cert AND recover last for encryption cert.
+
+.SS Token Renewal
+
+The following properties are used to define token renewal:
+
+.B op.enroll.<tokenType>.renewal.*
+
+For each token in TPS UI, set the following to trigger renewal operations:
+
+.B RENEW=YES
+
+Optional grace period enforcement must coincide exactly with what the CA enforces.
+
+In case of renewal, encryption certId values are for completeness only,
+server code calculates actual values used.
+
+.SS Format Operation For tokenKey
+
+The following property determines whether to update applet if the token is empty:
+
+.B op.format.<tokenType>.update.applet.emptyToken.enable=false
+
+The property is applicable to:
+ - CoolKey
+ - HouseKey
+ - HouseKey with Legacy Applet
+
+.SS Certificate Chain Imports
+
+.nf
+.B op.enroll.certificates.num=1
+.B op.enroll.certificates.value.0=caCert
+.B op.enroll.certificates.caCert.nickName=caCert0 pki-tps
+.B op.enroll.certificates.caCert.certId=C5
+.B op.enroll.certificates.caCert.certAttrId=c5
+.B op.enroll.certificates.caCert.label=caCert Label
+.fi
+
+.SS Pin Reset Operation For CoolKey
+
+The following property determines whether to update applet if the token is empty:
+
+.B op.pinReset.<tokenType>.update.applet.emptyToken.enable=false
+
+The property is not applicable to:
+ - HouseKey
+ - HouseKey with Legacy Applet
+
+.SH AUTHORS
+Dogtag Team <pki-devel@redhat.com>.
+
+.SH COPYRIGHT
+Copyright (c) 2014 Red Hat, Inc. This is licensed under the GNU General Public License, version 2 (GPLv2). A copy of this license is available at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
diff --git a/base/tps/setup/CMakeLists.txt b/base/tps/setup/CMakeLists.txt
new file mode 100644
index 000000000..d2a1399e6
--- /dev/null
+++ b/base/tps/setup/CMakeLists.txt
@@ -0,0 +1,6 @@
+install(
+ FILES
+ registry_instance
+ DESTINATION
+ ${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}/${PROJECT_NAME}/setup
+)
diff --git a/base/tps/setup/registry_instance b/base/tps/setup/registry_instance
new file mode 100644
index 000000000..6365ecb9e
--- /dev/null
+++ b/base/tps/setup/registry_instance
@@ -0,0 +1,60 @@
+# Establish PKI Variable "Slot" Substitutions
+
+PKI_SUBSYSTEM_TYPE=[PKI_SUBSYSTEM_TYPE]
+export PKI_SUBSYSTEM_TYPE
+
+PKI_USER=[PKI_USER]
+export PKI_USER
+
+PKI_GROUP=[PKI_GROUP]
+export PKI_GROUP
+
+PKI_INSTANCE_NAME=[PKI_INSTANCE_NAME]
+export PKI_INSTANCE_NAME
+
+PKI_INSTANCE_PATH=[PKI_INSTANCE_PATH]
+export PKI_INSTANCE_PATH
+
+PKI_INSTANCE_INITSCRIPT=[PKI_INSTANCE_INITSCRIPT]
+export PKI_INSTANCE_INITSCRIPT
+
+PKI_SERVER_XML_CONF=[PKI_SERVER_XML_CONF]
+export PKI_SERVER_XML_CONF
+
+# Use CATALINA_BASE
+
+CATALINA_BASE=$PKI_INSTANCE_PATH
+export CATALINA_BASE
+
+TOMCAT_PROG=$PKI_INSTANCE_NAME
+export TOMCAT_PROG
+
+TOMCAT_USER=$PKI_USER
+export TOMCAT_USER
+
+TOMCAT_GROUP=$PKI_GROUP
+export TOMCAT_GROUP
+
+PKI_LOCKDIR="/var/lock/pki/${PKI_SUBSYSTEM_TYPE}"
+export PKI_LOCKDIR
+
+PKI_LOCKFILE="${PKI_LOCKDIR}/${PKI_INSTANCE_NAME}"
+export PKI_LOCKFILE
+
+PKI_PIDDIR="/var/run/pki/${PKI_SUBSYSTEM_TYPE}"
+export PKI_PIDDIR
+
+PKI_PIDFILE="${PKI_PIDDIR}/${PKI_INSTANCE_NAME}.pid"
+export PKI_PIDFILE
+
+TOMCAT_LOCKFILE=/var/lock/subsys/${PKI_INSTANCE_NAME}
+export TOMCAT_LOCKFILE
+
+TOMCAT_PIDFILE=[TOMCAT_PIDFILE]
+export TOMCAT_PIDFILE
+
+pki_instance_configuration_file=${PKI_INSTANCE_PATH}/conf/CS.cfg
+export pki_instance_configuration_file
+
+RESTART_SERVER=${PKI_INSTANCE_PATH}/conf/restart_server_after_configuration
+export RESTART_SERVER
diff --git a/base/tps/shared/applets/1.2.4122DFB4.ijc b/base/tps/shared/applets/1.2.4122DFB4.ijc
new file mode 100644
index 000000000..2a8ea0733
--- /dev/null
+++ b/base/tps/shared/applets/1.2.4122DFB4.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.2.416DA155.ijc b/base/tps/shared/applets/1.2.416DA155.ijc
new file mode 100755
index 000000000..21b0312a8
--- /dev/null
+++ b/base/tps/shared/applets/1.2.416DA155.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.3.42260AFA.ijc b/base/tps/shared/applets/1.3.42260AFA.ijc
new file mode 100755
index 000000000..f17f98281
--- /dev/null
+++ b/base/tps/shared/applets/1.3.42260AFA.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.3.4255CC01.ijc b/base/tps/shared/applets/1.3.4255CC01.ijc
new file mode 100644
index 000000000..322fe86e2
--- /dev/null
+++ b/base/tps/shared/applets/1.3.4255CC01.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.3.42659461.ijc b/base/tps/shared/applets/1.3.42659461.ijc
new file mode 100755
index 000000000..ccf8ba451
--- /dev/null
+++ b/base/tps/shared/applets/1.3.42659461.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.3.427BDDB8.ijc b/base/tps/shared/applets/1.3.427BDDB8.ijc
new file mode 100644
index 000000000..4a633e8d3
--- /dev/null
+++ b/base/tps/shared/applets/1.3.427BDDB8.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.3.44724DDE.ijc b/base/tps/shared/applets/1.3.44724DDE.ijc
new file mode 100755
index 000000000..e56705dff
--- /dev/null
+++ b/base/tps/shared/applets/1.3.44724DDE.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.3.45787308.ijc b/base/tps/shared/applets/1.3.45787308.ijc
new file mode 100755
index 000000000..164c7e0cd
--- /dev/null
+++ b/base/tps/shared/applets/1.3.45787308.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.4.499dc06c.ijc b/base/tps/shared/applets/1.4.499dc06c.ijc
new file mode 100644
index 000000000..388482123
--- /dev/null
+++ b/base/tps/shared/applets/1.4.499dc06c.ijc
Binary files differ
diff --git a/base/tps/shared/applets/1.4.4d40a449.ijc b/base/tps/shared/applets/1.4.4d40a449.ijc
new file mode 100644
index 000000000..bd716adb0
--- /dev/null
+++ b/base/tps/shared/applets/1.4.4d40a449.ijc
Binary files differ
diff --git a/base/tps/shared/applets/3FD00877.ijc b/base/tps/shared/applets/3FD00877.ijc
new file mode 100644
index 000000000..5e6624d5a
--- /dev/null
+++ b/base/tps/shared/applets/3FD00877.ijc
Binary files differ
diff --git a/base/tps/shared/applets/4003196C.ijc b/base/tps/shared/applets/4003196C.ijc
new file mode 100644
index 000000000..bed8a7900
--- /dev/null
+++ b/base/tps/shared/applets/4003196C.ijc
Binary files differ
diff --git a/base/tps/shared/applets/402428AD.ijc b/base/tps/shared/applets/402428AD.ijc
new file mode 100644
index 000000000..b91a64334
--- /dev/null
+++ b/base/tps/shared/applets/402428AD.ijc
Binary files differ
diff --git a/base/tps/shared/applets/404E4697.ijc b/base/tps/shared/applets/404E4697.ijc
new file mode 100644
index 000000000..9c927c0f0
--- /dev/null
+++ b/base/tps/shared/applets/404E4697.ijc
Binary files differ
diff --git a/base/tps/shared/applets/4122DFB4.ijc b/base/tps/shared/applets/4122DFB4.ijc
new file mode 100644
index 000000000..2a8ea0733
--- /dev/null
+++ b/base/tps/shared/applets/4122DFB4.ijc
Binary files differ
diff --git a/base/tps/shared/applets/listappletdates b/base/tps/shared/applets/listappletdates
new file mode 100755
index 000000000..cca5964b7
--- /dev/null
+++ b/base/tps/shared/applets/listappletdates
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+#
+# --- BEGIN COPYRIGHT BLOCK ---
+# This library 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;
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# Copyright (C) 2014 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+
+
+$f = `/bin/ls *.ijc`;
+
+@filenames = split /\n/ms, $f;
+
+foreach $file (@filenames) {
+ $timestamp = $file;
+ $timestamp =~ s/1\.\d\.//;
+
+ ($root) = ($timestamp =~ /(.*).ijc/);
+
+ ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(hex($root));
+
+ printf " %16s %4d/%02d/%02d %02d:%02d\n", $file,
+ $year+1900, $mon+1, $mday,
+ $hour, $min;
+
+}
+
diff --git a/base/tps/shared/applets/readme.txt b/base/tps/shared/applets/readme.txt
new file mode 100644
index 000000000..773e3bac5
--- /dev/null
+++ b/base/tps/shared/applets/readme.txt
@@ -0,0 +1,52 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# This library 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;
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# Copyright (C) 2014 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+This directory contains a list of CoolKey applets
+that can be used by the TPS for applet upgrade.
+
+
+Applet Information:
+------------------
+
+File Name Creation Date Applet Ver Major Ver Minor Ver Remark
+============ ================ ========== ========= ========= ==========
+427BDDB8.ijc 2005/05/06 14:12 427BDDB8 1 3 Official Applet
+
+Token Information:
+-----------------
+
+Type CUID (Token ID) ATR Remark
+======================== ==================== ======= ==================
+Old "E" and ealier cards 40900062ff00ssssssss
+(Acquired From WebSite)
+"F" cards 40900062ff00ssssssss
+(Acquired From WebSite)
+"G" & later (Oct/Nov) 409000620103ssssssss
+(Acquired From WebSite)
+Fortezza cards 409000620103ssssssss
+(Acquired From WebSite)
+Developement Keyed cards 409000620101ssssssss 3B76940000FF6276010000
+
+where ssssssss is the serial number.
+
+
+Remark
+======
+1.3.45787308.ijc - this is the unofficial jForte applet with hacks
diff --git a/base/tps/shared/conf/CMakeLists.txt b/base/tps/shared/conf/CMakeLists.txt
new file mode 100644
index 000000000..419289d03
--- /dev/null
+++ b/base/tps/shared/conf/CMakeLists.txt
@@ -0,0 +1,8 @@
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CS.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/CS.cfg @ONLY)
+
+install(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/CS.cfg
+ DESTINATION
+ ${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}/${PROJECT_NAME}/conf
+)
diff --git a/base/tps/shared/conf/CS.cfg.in b/base/tps/shared/conf/CS.cfg.in
new file mode 100644
index 000000000..1647acc5d
--- /dev/null
+++ b/base/tps/shared/conf/CS.cfg.in
@@ -0,0 +1,1375 @@
+_000=##
+_001=## Token Processing System (TPS) Configuration File
+_002=##
+accessEvaluator.impl.group.class=com.netscape.cms.evaluators.GroupAccessEvaluator
+accessEvaluator.impl.ipaddress.class=com.netscape.cms.evaluators.IPAddressAccessEvaluator
+accessEvaluator.impl.user.class=com.netscape.cms.evaluators.UserAccessEvaluator
+archive.configuration_file=true
+applet._000=#########################################
+applet._001=# applet information
+applet._002=# SAF Key:
+applet._003=# applet.aid.cardmgr_instance=A0000001510000
+applet._004=#########################################
+applet.aid.cardmgr_instance=A0000000030000
+applet.aid.netkey_file=627601FF0000
+applet.aid.netkey_instance=627601FF000000
+applet.aid.netkey_old_file=A000000001
+applet.aid.netkey_old_instance=A00000000101
+applet.delete_old=true
+applet.so_pin=000000000000
+auths._000=##
+auths._001=## new authentication
+auths._002=##
+auths.impl._000=##
+auths.impl._001=## authentication manager implementations
+auths.impl._002=##
+auths.impl.AgentCertAuth.class=com.netscape.cms.authentication.AgentCertAuthentication
+auths.impl.CMCAuth.class=com.netscape.cms.authentication.CMCAuth
+auths.impl.NISAuth.class=com.netscape.cms.authentication.NISAuth
+auths.impl.PortalEnroll.class=com.netscape.cms.authentication.PortalEnroll
+auths.impl.SSLclientCertAuth.class=com.netscape.cms.authentication.SSLclientCertAuthentication
+auths.impl.TokenAuth.class=com.netscape.cms.authentication.TokenAuthentication
+auths.impl.UdnPwdDirAuth.class=com.netscape.cms.authentication.UdnPwdDirAuthentication
+auths.impl.UidPwdDirAuth.class=com.netscape.cms.authentication.UidPwdDirAuthentication
+auths.impl.UidPwdPinDirAuth.class=com.netscape.cms.authentication.UidPwdPinDirAuthentication
+auths.instance.AgentCertAuth.agentGroup=Certificate Manager Agents
+auths.instance.AgentCertAuth.pluginName=AgentCertAuth
+auths.instance.TokenAuth.pluginName=TokenAuth
+auths.instance.ldap1.authCredName=uid
+auths.instance.ldap1.ui.retries=3
+auths.instance.ldap1.ui.title.en=LDAP Authentication
+auths.instance.ldap1.ui.description.en=This authenticates user against the LDAP directory.
+auths.instance.ldap1.ui.id.UID.description.en=LDAP User ID
+auths.instance.ldap1.ui.id.UID.name.en=LDAP User ID
+auths.instance.ldap1.ui.id.UID.credMap.authCred=uid
+auths.instance.ldap1.ui.id.UID.credMap.msgCred.extlogin=UID
+auths.instance.ldap1.ui.id.UID.credMap.msgCred.login=screen_name
+auths.instance.ldap1.ui.id.PASSWORD.description.en=LDAP Password
+auths.instance.ldap1.ui.id.PASSWORD.name.en=LDAP Password
+auths.instance.ldap1.ui.id.PASSWORD.credMap.authCred=pwd
+auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred.extlogin=PASSWORD
+auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred.login=password
+auths.instance.ldap1.dnpattern=
+auths.instance.ldap1.ldapByteAttributes=
+auths.instance.ldap1.ldapStringAttributes=mail,cn,uid
+auths.instance.ldap1.ldap.basedn=[LDAP_ROOT]
+auths.instance.ldap1.ldap.maxConns=15
+auths.instance.ldap1.ldap.minConns=3
+auths.instance.ldap1.ldap.ldapauth.authtype=BasicAuth
+auths.instance.ldap1.ldap.ldapauth.bindDN=
+auths.instance.ldap1.ldap.ldapauth.bindPWPrompt=ldap1
+auths.instance.ldap1.ldap.ldapauth.clientCertNickname=subsystemCert cert-[PKI_INSTANCE_NAME]
+auths.instance.ldap1.ldap.ldapconn.host=localhost
+auths.instance.ldap1.ldap.ldapconn.port=389
+auths.instance.ldap1.ldap.ldapconn.secureConn=false
+auths.instance.ldap1.ldap.ldapconn.version=3
+auths.instance.ldap1.pluginName=UidPwdDirAuth
+auths.instance.SSLclientCertAuth.pluginName=SSLclientCertAuth
+auths.revocationChecking.bufferSize=50
+auths.revocationChecking.enabled=true
+auths.revocationChecking.tps=tps
+auths.revocationChecking.unknownStateInterval=0
+auths.revocationChecking.validityInterval=120
+authType=pwd
+authz._000=##
+authz._001=## new authorizatioin
+authz._002=##
+authz.evaluateOrder=deny,allow
+authz.impl._000=##
+authz.impl._001=## authorization manager implementations
+authz.impl._002=##
+authz.impl.BasicAclAuthz.class=com.netscape.cms.authorization.BasicAclAuthz
+authz.impl.DirAclAuthz.class=com.netscape.cms.authorization.DirAclAuthz
+authz.instance.BasicAclAuthz.pluginName=BasicAclAuthz
+authz.instance.DirAclAuthz.ldap._000=##
+authz.instance.DirAclAuthz.ldap._001=## Internal Database
+authz.instance.DirAclAuthz.ldap._002=##
+authz.instance.DirAclAuthz.ldap=internaldb
+authz.instance.DirAclAuthz.pluginName=DirAclAuthz
+authz.sourceType=ldap
+channel._000=#########################################
+channel._001=# channel.encryption:
+channel._002=#
+channel._003=# - enable encryption for all operation commands to token
+channel._004=# - default is true
+channel._005=# channel.blocksize=242
+channel._006=# channel.defKeyVersion=0
+channel._007=# channel.defKeyIndex=0
+channel._008=#
+channel._009=# Config the size of memory managed memory in the applet
+channel._010=# Default is 5000, try not go get close to the instanceSize
+channel._011=# which defaults to 18000:
+channel._012=#
+channel._013=# * channel.instanceSize=18000
+channel._014=# * channel.appletMemorySize=5000
+channel._015=#########################################
+channel.encryption=true
+channel.blocksize=248
+channel.defKeyVersion=0
+channel.defKeyIndex=0
+cms.product.version=@APPLICATION_VERSION@
+cms.version=@APPLICATION_VERSION_MAJOR@.@APPLICATION_VERSION_MINOR@
+config.Generals.General.state=Enabled
+config.Generals.General.timestamp=1280283607424406
+configurationRoot=/[PKI_SUBSYSTEM_TYPE]/conf/
+cs.state=0
+cs.type=TPS
+dbs.ldap=internaldb
+dbs.newSchemaEntryAdded=true
+debug.append=true
+debug.enabled=true
+debug.filename=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/debug
+debug.hashkeytypes=
+debug.level=0
+debug.showcaller=false
+failover.pod.enable=false
+general.applet_ext=ijc
+general.pwlength.min=16
+general.search.sizelimit.default=100
+general.search.sizelimit.max=2000
+general.search.timelimit.default=10
+general.search.timelimit.max=10
+general.verifyProof=1
+installDate=[INSTALL_TIME]
+instanceId=[PKI_INSTANCE_NAME]
+instanceRoot=[PKI_INSTANCE_PATH]
+internaldb._000=##
+internaldb._001=## Internal Database
+internaldb._002=##
+internaldb.ldapauth.authtype=BasicAuth
+internaldb.ldapauth.bindDN=cn=Directory Manager
+internaldb.ldapauth.bindPWPrompt=Internal LDAP Database
+internaldb.ldapauth.clientCertNickname=
+internaldb.ldapconn.host=
+internaldb.ldapconn.port=
+internaldb.ldapconn.secureConn=false
+internaldb.maxConns=15
+internaldb.minConns=3
+internaldb.multipleSuffix.enable=false
+jss._000=##
+jss._001=## JSS
+jss._002=##
+jss.configDir=[PKI_INSTANCE_PATH]/alias/
+jss.enable=true
+jss.ocspcheck.enable=false
+jss.secmodName=secmod.db
+jss.ssl.cipherfortezza=true
+jss.ssl.cipherpref=
+jss.ssl.cipherversion=cipherdomestic
+keys.ecc.curve.default=nistp256
+keys.ecc.curve.display.list=nistp256 (secp256r1),nistp384 (secp384r1),nistp521 (secp521r1),nistk163 (sect163k1),sect163r1,nistb163 (sect163r2),sect193r1,sect193r2,nistk233 (sect233k1),nistb233 (sect233r1),sect239k1,nistk283 (sect283k1),nistb283 (sect283r1),nistk409 (sect409k1),nistb409 (sect409r1),nistk571 (sect571k1),nistb571 (sect571r1),secp160k1,secp160r1,secp160r2,secp192k1,nistp192 (secp192r1, prime192v1),secp224k1,nistp224 (secp224r1),secp256k1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,c2pnb163v1,c2pnb163v2,c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359w1,c2pnb368w1,c2tnb431r1,secp112r1,secp112r2,secp128r1,secp128r2,sect113r1,sect113r2,sect131r1,sect131r2
+keys.ecc.curve.list=nistp256,nistp384,nistp521,sect163k1,nistk163,sect163r1,sect163r2,nistb163,sect193r1,sect193r2,sect233k1,nistk233,sect233r1,nistb233,sect239k1,sect283k1,nistk283,sect283r1,nistb283,sect409k1,nistk409,sect409r1,nistb409,sect571k1,nistk571,sect571r1,nistb571,secp160k1,secp160r1,secp160r2,secp192k1,secp192r1,nistp192,secp224k1,secp224r1,nistp224,secp256k1,secp256r1,secp384r1,secp521r1,prime192v1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,c2pnb163v1,c2pnb163v2,c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359w1,c2pnb368w1,c2tnb431r1,secp112r1,secp112r2,secp128r1,secp128r2,sect113r1,sect113r2,sect131r1,sect131r2
+keys.rsa.keysize.default=2048
+log._000=##
+log._001=## Logging
+log._002=##
+logAudit.fileName=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/access
+logError.fileName=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/error
+log.impl.file.class=com.netscape.cms.logging.RollingLogFile
+log.instance.SignedAudit._000=##
+log.instance.SignedAudit._001=## Signed Audit Logging
+log.instance.SignedAudit._002=##
+log.instance.SignedAudit._003=##
+log.instance.SignedAudit._004=## Available Audit events:
+log.instance.SignedAudit._005=## AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,ROLE_ASSUME,CONFIG_CERT_POLICY,CONFIG_CERT_PROFILE,CONFIG_CRL_PROFILE,CONFIG_OCSP_PROFILE,CONFIG_AUTH,CONFIG_ROLE,CONFIG_ACL,CONFIG_SIGNED_AUDIT,CONFIG_ENCRYPTION,CONFIG_TRUSTED_PUBLIC_KEY,CONFIG_DRM,SELFTESTS_EXECUTION,AUDIT_LOG_DELETE,LOG_PATH_CHANGE,LOG_EXPIRATION_CHANGE,PRIVATE_KEY_ARCHIVE_REQUEST,PRIVATE_KEY_ARCHIVE_REQUEST_PROCESSED,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS,PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE,KEY_RECOVERY_REQUEST,KEY_RECOVERY_REQUEST_ASYNC,KEY_RECOVERY_AGENT_LOGIN,KEY_RECOVERY_REQUEST_PROCESSED,KEY_RECOVERY_REQUEST_PROCESSED_ASYNC,KEY_GEN_ASYMMETRIC,NON_PROFILE_CERT_REQUEST,PROFILE_CERT_REQUEST,CERT_REQUEST_PROCESSED,CERT_STATUS_CHANGE_REQUEST,CERT_STATUS_CHANGE_REQUEST_PROCESSED,AUTHZ_SUCCESS,AUTHZ_FAIL,INTER_BOUNDARY,AUTH_FAIL,AUTH_SUCCESS,CERT_PROFILE_APPROVAL,PROOF_OF_POSSESSION,CRL_RETRIEVAL,CRL_VALIDATION,CMC_SIGNED_REQUEST_SIG_VERIFY,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_FAILURE,SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS,SERVER_SIDE_KEYGEN_REQUEST,COMPUTE_SESSION_KEY_REQUEST,COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE,DIVERSIFY_KEY_REQUEST,DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE,ENCRYPT_DATA_REQUEST,ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS,ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE,OCSP_ADD_CA_REQUEST,OCSP_ADD_CA_REQUEST_PROCESSED,OCSP_REMOVE_CA_REQUEST,OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS,OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE,COMPUTE_RANDOM_DATA_REQUEST,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS,COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE,CIMC_CERT_VERIFICATION,SECURITY_DOMAIN_UPDATE,CONFIG_SERIAL_NUMBER,TOKEN_CERT_ENROLLMENT,TOKEN_CERT_RENEWAL,TOKEN_CERT_STATUS_CHANGE_REQUEST,TOKEN_PIN_RESET_REQUEST,TOKEN_FORMAT_REQUEST,TOKEN_APPLET_UPGRADE,TOKEN_KEY_CHANGEOVER,CONFIG_TOKEN_PROFILE,CONFIG_TOKEN_GENERAL,TOKEN_STATE_CHANGE
+log.instance.SignedAudit._006=##
+log.instance.SignedAudit.bufferSize=512
+log.instance.SignedAudit.enable=true
+log.instance.SignedAudit.events=SELFTESTS_EXECUTION,AUTHZ_SUCCESS,AUTHZ_FAIL,AUTH_FAIL,AUTH_SUCCESS,AUTH_FAIL,ROLE_ASSUME,AUTHZ_SUCCESS,AUTHZ_FAIL,CIMC_CERT_VERIFICATION,CONFIG_SIGNED_AUDIT,CONFIG_ROLE,CONFIG_AUTH,TOKEN_CERT_ENROLLMENT,TOKEN_CERT_RENEWAL,TOKEN_CERT_STATUS_CHANGE_REQUEST,TOKEN_PIN_RESET_REQUEST,TOKEN_FORMAT_REQUEST,TOKEN_APPLET_UPGRADE,TOKEN_KEY_CHANGEOVER,CONFIG_TOKEN_PROFILE,CONFIG_TOKEN_GENERAL,TOKEN_STATE_CHANGE
+log.instance.SignedAudit.unselected.events=
+log.instance.SignedAudit.mandatory.events=AUDIT_LOG_STARTUP,AUDIT_LOG_SHUTDOWN,LOGGING_SIGNED_AUDIT_SIGNING
+log.instance.SignedAudit.expirationTime=0
+log.instance.SignedAudit.fileName=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/signedAudit/tps_cert-tps_audit
+log.instance.SignedAudit.flushInterval=5
+log.instance.SignedAudit.level=1
+log.instance.SignedAudit.logSigning=false
+log.instance.SignedAudit.maxFileSize=2000
+log.instance.SignedAudit.pluginName=file
+log.instance.SignedAudit.rolloverInterval=2592000
+log.instance.SignedAudit.signedAudit:_000=##
+log.instance.SignedAudit.signedAudit:_001=## Fill in the nickname of a trusted signing certificate to allow TPS audit logs to be signed
+log.instance.SignedAudit.signedAudit:_002=##
+log.instance.SignedAudit.signedAuditCertNickname=auditSigningCert cert-[PKI_INSTANCE_NAME]
+log.instance.SignedAudit.type=signedAudit
+log.instance.System._000=##
+log.instance.System._001=## System Logging
+log.instance.System._002=##
+log.instance.System.bufferSize=512
+log.instance.System.enable=true
+log.instance.System.expirationTime=0
+log.instance.System.fileName=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/system
+log.instance.System.flushInterval=5
+log.instance.System.level=3
+log.instance.System.maxFileSize=2000
+log.instance.System.pluginName=file
+log.instance.System.rolloverInterval=2592000
+log.instance.System.type=system
+log.instance.Transactions._000=##
+log.instance.Transactions._001=## Transaction Logging
+log.instance.Transactions._002=##
+log.instance.Transactions.bufferSize=512
+log.instance.Transactions.enable=true
+log.instance.Transactions.expirationTime=0
+log.instance.Transactions.fileName=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/transactions
+log.instance.Transactions.flushInterval=5
+log.instance.Transactions.level=1
+log.instance.Transactions.maxFileSize=2000
+log.instance.Transactions.pluginName=file
+log.instance.Transactions.rolloverInterval=2592000
+log.instance.Transactions.type=transaction
+machineName=[PKI_HOSTNAME]
+multiroles._000=##
+multiroles._001=## multiroles
+multiroles._002=##
+multiroles.enable=true
+multiroles.false.groupEnforceList=Administrators,Auditors,Trusted Managers,Certificate Manager Agents,Registration Manager Agents,Data Recovery Manager Agents,Online Certificate Status Manager Agents,Token Key Service Manager Agents,Enterprise CA Administrators,Enterprise KRA Administrators,Enterprise OCSP Administrators,Enterprise RA Administrators,Enterprise TKS Administrators,Enterprise TPS Administrators,Security Domain Administrators,Subsystem Group,ClonedSubsystems
+multiroles.false.groupEnforceList=Administrators,Auditors,Trusted Managers,Certificate Manager Agents,Registration Manager Agents,Data Recovery Manager Agents,Online Certificate Status Manager Agents,Token Key Service Manager Agents,Enterprise CA Administrators,Enterprise KRA Adminstrators,Enterprise OCSP Administrators,Enterprise RA Administrators,Enterprise TKS Administrators,Enterprise TPS Administrators,Security Domain Administrators,Subsystem Group
+multiroles=true
+op.enroll._000=#########################################
+op.enroll._001=# Default Operations
+op.enroll._002=#
+op.enroll._003=# op.<op>.mapping.order=<n>,<n>,<n>
+op.enroll._004=# - contains at least one value or a series
+op.enroll._005=# of comma-separated mapping values which
+op.enroll._006=# are checked in sequential order
+op.enroll._007=# op.<op>.mapping.<n>.filter.tokenType=userKey
+op.enroll._008=# - can be either empty or token type
+op.enroll._009=# specified by the client
+op.enroll._010=# op.<op>.mapping.<n>.filter.tokenATR=
+op.enroll._011=# - can be either empty or token ATR
+op.enroll._012=# specified by the client
+op.enroll._013=# op.<op>.mapping.<n>.filter.appletMajorVersion=1
+op.enroll._014=# - can be either empty or applet major version
+op.enroll._015=# specified by the client
+op.enroll._016=# op.<op>.mapping.<n>.filter.appletMinorVersion=
+op.enroll._017=# - can be either empty or applet minor version
+op.enroll._018=# specified by the client
+op.enroll._019=# - if major and minor versions are both zero, this
+op.enroll._020=# indicate there is no applet on the token.
+op.enroll._021=# op.<op>.mapping.<n>.target.tokenType=userKey
+op.enroll._022=# - if tokenType, tokenATR, appletMajorVersion,
+op.enroll._023=# and appletMinorVersion are matched, value in
+op.enroll._024=# targetTokenType will be used to locate
+op.enroll._025=# the corresponding token profile to
+op.enroll._026=# process the request.
+op.enroll._027=#
+op.enroll._028=# where
+op.enroll._029=# <op> - operation; enroll,pinReset,format
+op.enroll._030=# <n> - mapping ID; order is specifiable
+op.enroll._031=#
+op.enroll._032=# Token ATR:
+op.enroll._033=# Web Store - 3B759400006202020201
+op.enroll._034=#########################################
+op.enroll.allowUnknownToken=true
+op.enroll.tokenProfileResolver=enrollMappingResolver
+op.enroll.soKey.auth.enable=true
+op.enroll.soKey.auth.id=ldap2
+op.enroll.soKey.cardmgr_instance=A0000000030000
+op.enroll.soKey.issuerinfo.enable=true
+op.enroll.soKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome
+op.enroll.soKey.keyGen.encryption.ca.conn=ca1
+op.enroll.soKey.keyGen.encryption.ca.profileId=caTokenUserEncryptionKeyEnrollment
+op.enroll.soKey.keyGen.encryption.certAttrId=c2
+op.enroll.soKey.keyGen.encryption.certId=C2
+op.enroll.soKey.keyGen.encryption.cuid_label=$cuid$
+op.enroll.soKey.keyGen.encryption.keySize=1024
+op.enroll.soKey.keyGen.encryption.keyUsage=0
+op.enroll.soKey.keyGen.encryption.keyUser=0
+op.enroll.soKey.keyGen.encryption.label=encryption key for $userid$
+op.enroll.soKey.keyGen.encryption.overwrite=true
+op.enroll.soKey.keyGen.encryption.privateKeyAttrId=k4
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.decrypt=true
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.derive=false
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.encrypt=false
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.private=true
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.sensitive=true
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.sign=false
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.signRecover=false
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.token=true
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.unwrap=true
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.verify=false
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.verifyRecover=false
+op.enroll.soKey.keyGen.encryption.private.keyCapabilities.wrap=false
+op.enroll.soKey.keyGen.encryption.privateKeyNumber=4
+op.enroll.soKey.keyGen.encryption.publicKeyAttrId=k5
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.decrypt=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.derive=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.encrypt=true
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.private=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.sensitive=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.sign=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.signRecover=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.token=true
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.unwrap=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.verify=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.verifyRecover=false
+op.enroll.soKey.keyGen.encryption.public.keyCapabilities.wrap=true
+op.enroll.soKey.keyGen.encryption.publicKeyNumber=5
+op.enroll.soKey.keyGen.encryption.recovery.destroyed.revokeCert=false
+op.enroll.soKey.keyGen.encryption.recovery.destroyed.revokeCert.reason=0
+op.enroll.soKey.keyGen.encryption.recovery.destroyed.scheme=RecoverLast
+op.enroll.soKey.keyGen.encryption.recovery.keyCompromise.revokeCert.reason=1
+op.enroll.soKey.keyGen.encryption.recovery.keyCompromise.revokeCert=true
+op.enroll.soKey.keyGen.encryption.recovery.keyCompromise.scheme=GenerateNewKey
+op.enroll.soKey.keyGen.encryption.recovery.onHold.revokeCert.reason=6
+op.enroll.soKey.keyGen.encryption.recovery.onHold.revokeCert=true
+op.enroll.soKey.keyGen.encryption.recovery.onHold.scheme=GenerateNewKey
+op.enroll.soKey.keyGen.encryption.serverKeygen.archive=true
+op.enroll.soKey.keyGen.encryption.serverKeygen.drm.conn=kra1
+op.enroll.soKey.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN]
+op.enroll.soKey.keyGen.keyType.num=2
+op.enroll.soKey.keyGen.keyType.value.0=signing
+op.enroll.soKey.keyGen.keyType.value.1=encryption
+op.enroll.soKey.keyGen.recovery.destroyed.keyType.num=2
+op.enroll.soKey.keyGen.recovery.destroyed.keyType.value.0=signing
+op.enroll.soKey.keyGen.recovery.destroyed.keyType.value.1=encryption
+op.enroll.soKey.keyGen.recovery.keyCompromise.keyType.num=2
+op.enroll.soKey.keyGen.recovery.keyCompromise.keyType.value.0=signing
+op.enroll.soKey.keyGen.recovery.keyCompromise.keyType.value.1=encryption
+op.enroll.soKey.keyGen.recovery.onHold.keyType.num=2
+op.enroll.soKey.keyGen.recovery.onHold.keyType.value.0=signing
+op.enroll.soKey.keyGen.recovery.onHold.keyType.value.1=encryption
+op.enroll.soKey.keyGen.signing.ca.conn=ca1
+op.enroll.soKey.keyGen.signing.ca.profileId=caTokenUserSigningKeyEnrollment
+op.enroll.soKey.keyGen.signing.certAttrId=c1
+op.enroll.soKey.keyGen.signing.certId=C1
+op.enroll.soKey.keyGen.signing.cuid_label=$cuid$
+op.enroll.soKey.keyGen.signing.keySize=1024
+op.enroll.soKey.keyGen.signing.keyUsage=0
+op.enroll.soKey.keyGen.signing.keyUser=0
+op.enroll.soKey.keyGen.signing.label=signing key for $userid$
+op.enroll.soKey.keyGen.signing.overwrite=true
+op.enroll.soKey.keyGen.signing.privateKeyAttrId=k2
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.decrypt=false
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.derive=false
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.encrypt=false
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.private=true
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.sensitive=true
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.signRecover=true
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.sign=true
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.token=true
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.unwrap=false
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.verify=false
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.verifyRecover=false
+op.enroll.soKey.keyGen.signing.private.keyCapabilities.wrap=false
+op.enroll.soKey.keyGen.signing.privateKeyNumber=2
+op.enroll.soKey.keyGen.signing.publicKeyAttrId=k3
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.decrypt=false
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.derive=false
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.encrypt=false
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.private=false
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.sensitive=false
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.sign=false
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.signRecover=false
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.token=true
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.unwrap=false
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.verifyRecover=true
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.verify=true
+op.enroll.soKey.keyGen.signing.public.keyCapabilities.wrap=false
+op.enroll.soKey.keyGen.signing.publicKeyNumber=3
+op.enroll.soKey.keyGen.signing.recovery.destroyed.revokeCert.reason=0
+op.enroll.soKey.keyGen.signing.recovery.destroyed.revokeCert=true
+op.enroll.soKey.keyGen.signing.recovery.destroyed.scheme=GenerateNewKey
+op.enroll.soKey.keyGen.signing.recovery.keyCompromise.revokeCert.reason=1
+op.enroll.soKey.keyGen.signing.recovery.keyCompromise.revokeCert=true
+op.enroll.soKey.keyGen.signing.recovery.keyCompromise.scheme=GenerateNewKey
+op.enroll.soKey.keyGen.signing.recovery.onHold.revokeCert.reason=6
+op.enroll.soKey.keyGen.signing.recovery.onHold.revokeCert=true
+op.enroll.soKey.keyGen.signing.recovery.onHold.scheme=GenerateNewKey
+op.enroll.soKey.keyGen.tokenName=$auth.cn$
+op.enroll.soKey.loginRequest.enable=true
+op.enroll.soKey.pinReset.enable=true
+op.enroll.soKey.pinReset.pin.maxLen=10
+op.enroll.soKey.pinReset.pin.maxRetries=127
+op.enroll.soKey.pinReset.pin.minLen=4
+op.enroll.soKey.pkcs11obj.compress.enable=true
+op.enroll.soKey.pkcs11obj.enable=true
+op.enroll.soKeyTemporary.auth.enable=true
+op.enroll.soKeyTemporary.auth.id=ldap2
+op.enroll.soKeyTemporary.cardmgr_instance=A0000000030000
+op.enroll.soKeyTemporary.keyGen.auth.ca.conn=ca1
+op.enroll.soKeyTemporary.keyGen.auth.ca.profileId=caTempTokenDeviceKeyEnrollment
+op.enroll.soKeyTemporary.keyGen.auth.certAttrId=c0
+op.enroll.soKeyTemporary.keyGen.auth.certId=C0
+op.enroll.soKeyTemporary.keyGen.auth.cuid_label=$cuid$
+op.enroll.soKeyTemporary.keyGen.auth.keySize=1024
+op.enroll.soKeyTemporary.keyGen.auth.keyUsage=0
+op.enroll.soKeyTemporary.keyGen.auth.keyUser=15
+op.enroll.soKeyTemporary.keyGen.auth.label=Temporary Key for $userid$
+op.enroll.soKeyTemporary.keyGen.auth.overwrite=false
+op.enroll.soKeyTemporary.keyGen.auth.privateKeyAttrId=k0
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.decrypt=false
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.derive=false
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.encrypt=false
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.private=false
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.sensitive=true
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.signRecover=true
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.sign=true
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.token=true
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.unwrap=false
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.verifyRecover=true
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.verify=true
+op.enroll.soKeyTemporary.keyGen.auth.private.keyCapabilities.wrap=false
+op.enroll.soKeyTemporary.keyGen.auth.privateKeyNumber=0
+op.enroll.soKeyTemporary.keyGen.auth.publicKeyAttrId=k1
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.decrypt=false
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.derive=false
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.encrypt=false
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.private=false
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.sensitive=true
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.signRecover=true
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.sign=true
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.token=true
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.unwrap=false
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.verifyRecover=true
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.verify=true
+op.enroll.soKeyTemporary.keyGen.auth.public.keyCapabilities.wrap=false
+op.enroll.soKeyTemporary.keyGen.auth.publicKeyNumber=1
+op.enroll.soKeyTemporary.keyGen.encryption.ca.conn=ca1
+op.enroll.soKeyTemporary.keyGen.encryption.ca.profileId=caTempTokenUserEncryptionKeyEnrollment
+op.enroll.soKeyTemporary.keyGen.encryption.certAttrId=c2
+op.enroll.soKeyTemporary.keyGen.encryption.certId=C2
+op.enroll.soKeyTemporary.keyGen.encryption.cuid_label=$cuid$
+op.enroll.soKeyTemporary.keyGen.encryption.keySize=1024
+op.enroll.soKeyTemporary.keyGen.encryption.keyUsage=0
+op.enroll.soKeyTemporary.keyGen.encryption.keyUser=0
+op.enroll.soKeyTemporary.keyGen.encryption.label=encryption key for $userid$
+op.enroll.soKeyTemporary.keyGen.encryption.overwrite=true
+op.enroll.soKeyTemporary.keyGen.encryption.privateKeyAttrId=k4
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.decrypt=true
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.derive=false
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.encrypt=false
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.private=true
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.sensitive=true
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.sign=false
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.signRecover=false
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.token=true
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.unwrap=true
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.verify=false
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.verifyRecover=false
+op.enroll.soKeyTemporary.keyGen.encryption.private.keyCapabilities.wrap=false
+op.enroll.soKeyTemporary.keyGen.encryption.privateKeyNumber=4
+op.enroll.soKeyTemporary.keyGen.encryption.publicKeyAttrId=k5
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.decrypt=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.derive=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.encrypt=true
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.private=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.sensitive=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.sign=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.signRecover=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.token=true
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.unwrap=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.verify=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.verifyRecover=false
+op.enroll.soKeyTemporary.keyGen.encryption.public.keyCapabilities.wrap=true
+op.enroll.soKeyTemporary.keyGen.encryption.publicKeyNumber=5
+op.enroll.soKeyTemporary.keyGen.encryption.recovery.onHold.revokeCert.reason=0
+op.enroll.soKeyTemporary.keyGen.encryption.recovery.onHold.revokeCert=true
+op.enroll.soKeyTemporary.keyGen.encryption.recovery.onHold.scheme=RecoverLast
+op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.archive=true
+op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.drm.conn=kra1
+op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.enable=true
+op.enroll.soKeyTemporary.keyGen.keyType.num=3
+op.enroll.soKeyTemporary.keyGen.keyType.value.0=auth
+op.enroll.soKeyTemporary.keyGen.keyType.value.1=signing
+op.enroll.soKeyTemporary.keyGen.keyType.value.2=encryption
+op.enroll.soKeyTemporary.keyGen.recovery.onHold.keyType.num=2
+op.enroll.soKeyTemporary.keyGen.recovery.onHold.keyType.value.0=signing
+op.enroll.soKeyTemporary.keyGen.recovery.onHold.keyType.value.1=encryption
+op.enroll.soKeyTemporary.keyGen.signing.ca.conn=ca1
+op.enroll.soKeyTemporary.keyGen.signing.ca.profileId=caTempTokenUserSigningKeyEnrollment
+op.enroll.soKeyTemporary.keyGen.signing.certAttrId=c1
+op.enroll.soKeyTemporary.keyGen.signing.certId=C1
+op.enroll.soKeyTemporary.keyGen.signing.cuid_label=$cuid$
+op.enroll.soKeyTemporary.keyGen.signing.keySize=1024
+op.enroll.soKeyTemporary.keyGen.signing.keyUsage=0
+op.enroll.soKeyTemporary.keyGen.signing.keyUser=0
+op.enroll.soKeyTemporary.keyGen.signing.label=signing key for $userid$
+op.enroll.soKeyTemporary.keyGen.signing.overwrite=true
+op.enroll.soKeyTemporary.keyGen.signing.privateKeyAttrId=k2
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.decrypt=false
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.derive=false
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.encrypt=false
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.private=true
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.sensitive=true
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.signRecover=true
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.sign=true
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.token=true
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.unwrap=false
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.verify=false
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.verifyRecover=false
+op.enroll.soKeyTemporary.keyGen.signing.private.keyCapabilities.wrap=false
+op.enroll.soKeyTemporary.keyGen.signing.privateKeyNumber=2
+op.enroll.soKeyTemporary.keyGen.signing.publicKeyAttrId=k3
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.decrypt=false
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.derive=false
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.encrypt=false
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.private=false
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.sensitive=false
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.sign=false
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.signRecover=false
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.token=true
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.unwrap=false
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.verifyRecover=true
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.verify=true
+op.enroll.soKeyTemporary.keyGen.signing.public.keyCapabilities.wrap=false
+op.enroll.soKeyTemporary.keyGen.signing.publicKeyNumber=3
+op.enroll.soKeyTemporary.keyGen.signing.recovery.onHold.revokeCert.reason=0
+op.enroll.soKeyTemporary.keyGen.signing.recovery.onHold.revokeCert=true
+op.enroll.soKeyTemporary.keyGen.signing.recovery.onHold.scheme=GenerateNewKey
+op.enroll.soKeyTemporary.keyGen.tokenName=$auth.cn$ (Temporary)
+op.enroll.soKeyTemporary.loginRequest.enable=true
+op.enroll.soKeyTemporary.pinReset.enable=true
+op.enroll.soKeyTemporary.pinReset.pin.maxLen=10
+op.enroll.soKeyTemporary.pinReset.pin.maxRetries=127
+op.enroll.soKeyTemporary.pinReset.pin.minLen=4
+op.enroll.soKeyTemporary.pkcs11obj.compress.enable=true
+op.enroll.soKeyTemporary.pkcs11obj.enable=true
+op.enroll.soKeyTemporary.tks.conn=tks1
+op.enroll.soKeyTemporary.tks.keySet=defKeyset
+op.enroll.soKey.temporaryToken.tokenType=soKeyTemporary
+op.enroll.soKeyTemporary.update.applet.directory=[TPS_DIR]/applets
+op.enroll.soKeyTemporary.update.applet.emptyToken.enable=true
+op.enroll.soKeyTemporary.update.applet.enable=true
+op.enroll.soKeyTemporary.update.applet.encryption=true
+op.enroll.soKeyTemporary.update.applet.requiredVersion=1.4.4d40a449
+op.enroll.soKeyTemporary.update.symmetricKeys.enable=false
+op.enroll.soKeyTemporary.update.symmetricKeys.requiredVersion=1
+op.enroll.soKey.tks.conn=tks1
+op.enroll.soKey.update.applet.directory=[TPS_DIR]/applets
+op.enroll.soKey.update.applet.emptyToken.enable=true
+op.enroll.soKey.update.applet.enable=true
+op.enroll.soKey.update.applet.encryption=true
+op.enroll.soKey.update.applet.requiredVersion=1.4.4d40a449
+op.enroll.soKey.update.symmetricKeys.enable=false
+op.enroll.soKey.update.symmetricKeys.requiredVersion=1
+op.enroll.userKey.auth.enable=true
+op.enroll.userKey.auth.id=ldap1
+op.enroll.userKey.cardmgr_instance=A0000000030000
+op.enroll.userKey.issuerinfo.enable=true
+op.enroll.userKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome
+op.enroll.userKey.keyGen.encryption.ca.conn=ca1
+op.enroll.userKey.keyGen.encryption.ca.profileId=caTokenUserEncryptionKeyEnrollment
+op.enroll.userKey.keyGen.encryption.certAttrId=c2
+op.enroll.userKey.keyGen.encryption.certId=C2
+op.enroll.userKey.keyGen.encryption.cuid_label=$cuid$
+op.enroll.userKey.keyGen.encryption.keySize=1024
+op.enroll.userKey.keyGen.encryption.keyUsage=0
+op.enroll.userKey.keyGen.encryption.keyUser=0
+op.enroll.userKey.keyGen.encryption.label=encryption key for $userid$
+op.enroll.userKey.keyGen.encryption.overwrite=true
+op.enroll.userKey.keyGen.encryption.privateKeyAttrId=k4
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.decrypt=true
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.derive=false
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.encrypt=false
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.private=true
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.sensitive=true
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.sign=false
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.signRecover=false
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.token=true
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.unwrap=true
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.verify=false
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.verifyRecover=false
+op.enroll.userKey.keyGen.encryption.private.keyCapabilities.wrap=false
+op.enroll.userKey.keyGen.encryption.privateKeyNumber=4
+op.enroll.userKey.keyGen.encryption.publicKeyAttrId=k5
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.decrypt=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.derive=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.encrypt=true
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.private=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.sensitive=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.sign=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.signRecover=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.token=true
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.unwrap=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.verify=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.verifyRecover=false
+op.enroll.userKey.keyGen.encryption.public.keyCapabilities.wrap=true
+op.enroll.userKey.keyGen.encryption.publicKeyNumber=5
+op.enroll.userKey.keyGen.encryption.recovery.destroyed.revokeCert=false
+op.enroll.userKey.keyGen.encryption.recovery.destroyed.revokeCert.reason=0
+op.enroll.userKey.keyGen.encryption.recovery.destroyed.scheme=RecoverLast
+op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.revokeCert.reason=1
+op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.revokeCert=true
+op.enroll.userKey.keyGen.encryption.recovery.keyCompromise.scheme=GenerateNewKey
+op.enroll.userKey.keyGen.encryption.recovery.onHold.revokeCert.reason=6
+op.enroll.userKey.keyGen.encryption.recovery.onHold.revokeCert=true
+op.enroll.userKey.keyGen.encryption.recovery.onHold.scheme=GenerateNewKey
+op.enroll.userKey.keyGen.encryption.serverKeygen.archive=true
+op.enroll.userKey.keyGen.encryption.serverKeygen.drm.conn=kra1
+op.enroll.userKey.keyGen.encryption.serverKeygen.enable=[SERVER_KEYGEN]
+op.enroll.userKey.keyGen.keyType.num=2
+op.enroll.userKey.keyGen.keyType.value.0=signing
+op.enroll.userKey.keyGen.keyType.value.1=encryption
+op.enroll.userKey.keyGen.recovery.destroyed.keyType.num=2
+op.enroll.userKey.keyGen.recovery.destroyed.keyType.value.0=signing
+op.enroll.userKey.keyGen.recovery.destroyed.keyType.value.1=encryption
+op.enroll.userKey.keyGen.recovery.keyCompromise.keyType.num=2
+op.enroll.userKey.keyGen.recovery.keyCompromise.keyType.value.0=signing
+op.enroll.userKey.keyGen.recovery.keyCompromise.keyType.value.1=encryption
+op.enroll.userKey.keyGen.recovery.onHold.keyType.num=2
+op.enroll.userKey.keyGen.recovery.onHold.keyType.value.0=signing
+op.enroll.userKey.keyGen.recovery.onHold.keyType.value.1=encryption
+op.enroll.userKey.keyGen.signing.ca.conn=ca1
+op.enroll.userKey.keyGen.signing.ca.profileId=caTokenUserSigningKeyEnrollment
+op.enroll.userKey.keyGen.signing.certAttrId=c1
+op.enroll.userKey.keyGen.signing.certId=C1
+op.enroll.userKey.keyGen.signing.cuid_label=$cuid$
+op.enroll.userKey.keyGen.signing.keySize=1024
+op.enroll.userKey.keyGen.signing.keyUsage=0
+op.enroll.userKey.keyGen.signing.keyUser=0
+op.enroll.userKey.keyGen.signing.label=signing key for $userid$
+op.enroll.userKey.keyGen.signing.overwrite=true
+op.enroll.userKey.keyGen.signing.privateKeyAttrId=k2
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.decrypt=false
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.derive=false
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.encrypt=false
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.private=true
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.sensitive=true
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.signRecover=true
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.sign=true
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.token=true
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.unwrap=false
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.verify=false
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.verifyRecover=false
+op.enroll.userKey.keyGen.signing.private.keyCapabilities.wrap=false
+op.enroll.userKey.keyGen.signing.privateKeyNumber=2
+op.enroll.userKey.keyGen.signing.publicKeyAttrId=k3
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.decrypt=false
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.derive=false
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.encrypt=false
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.private=false
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.sensitive=false
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.sign=false
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.signRecover=false
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.token=true
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.unwrap=false
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.verifyRecover=true
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.verify=true
+op.enroll.userKey.keyGen.signing.public.keyCapabilities.wrap=false
+op.enroll.userKey.keyGen.signing.publicKeyNumber=3
+op.enroll.userKey.keyGen.signing.recovery.destroyed.revokeCert.reason=0
+op.enroll.userKey.keyGen.signing.recovery.destroyed.revokeCert=true
+op.enroll.userKey.keyGen.signing.recovery.destroyed.scheme=GenerateNewKey
+op.enroll.userKey.keyGen.signing.recovery.keyCompromise.revokeCert.reason=1
+op.enroll.userKey.keyGen.signing.recovery.keyCompromise.revokeCert=true
+op.enroll.userKey.keyGen.signing.recovery.keyCompromise.scheme=GenerateNewKey
+op.enroll.userKey.keyGen.signing.recovery.onHold.revokeCert.reason=6
+op.enroll.userKey.keyGen.signing.recovery.onHold.revokeCert=true
+op.enroll.userKey.keyGen.signing.recovery.onHold.scheme=GenerateNewKey
+op.enroll.userKey.keyGen.tokenName=$auth.cn$
+op.enroll.userKey.loginRequest.enable=true
+op.enroll.userKey.pinReset.enable=true
+op.enroll.userKey.pinReset.pin.maxLen=10
+op.enroll.userKey.pinReset.pin.maxRetries=127
+op.enroll.userKey.pinReset.pin.minLen=4
+op.enroll.userKey.pkcs11obj.compress.enable=true
+op.enroll.userKey.pkcs11obj.enable=true
+op.enroll.userKey.renewal.encryption.ca.conn=ca1
+op.enroll.userKey.renewal.encryption.ca.profileId=caTokenUserEncryptionKeyRenewal
+op.enroll.userKey.renewal.encryption.certAttrId=c2
+op.enroll.userKey.renewal.encryption.certId=C2
+op.enroll.userKey.renewal.encryption.enable=true
+op.enroll.userKey.renewal.encryption.gracePeriod.after=30
+op.enroll.userKey.renewal.encryption.gracePeriod.before=30
+op.enroll.userKey.renewal.encryption.gracePeriod.enable=false
+op.enroll.userKey.renewal.keyType.num=2
+op.enroll.userKey.renewal.keyType.value.0=signing
+op.enroll.userKey.renewal.keyType.value.1=encryption
+op.enroll.userKey.renewal.signing.ca.conn=ca1
+op.enroll.userKey.renewal.signing.ca.profileId=caTokenUserSigningKeyRenewal
+op.enroll.userKey.renewal.signing.certAttrId=c1
+op.enroll.userKey.renewal.signing.certId=C1
+op.enroll.userKey.renewal.signing.enable=true
+op.enroll.userKey.renewal.signing.gracePeriod.after=30
+op.enroll.userKey.renewal.signing.gracePeriod.before=30
+op.enroll.userKey.renewal.signing.gracePeriod.enable=false
+op.enroll.userKeyTemporary.auth.enable=true
+op.enroll.userKeyTemporary.auth.id=ldap1
+op.enroll.userKeyTemporary.cardmgr_instance=A0000000030000
+op.enroll.userKeyTemporary.keyGen.auth.ca.conn=ca1
+op.enroll.userKeyTemporary.keyGen.auth.ca.profileId=caTempTokenDeviceKeyEnrollment
+op.enroll.userKeyTemporary.keyGen.auth.certAttrId=c0
+op.enroll.userKeyTemporary.keyGen.auth.certId=C0
+op.enroll.userKeyTemporary.keyGen.auth.cuid_label=$cuid$
+op.enroll.userKeyTemporary.keyGen.auth.keySize=1024
+op.enroll.userKeyTemporary.keyGen.auth.keyUsage=0
+op.enroll.userKeyTemporary.keyGen.auth.keyUser=15
+op.enroll.userKeyTemporary.keyGen.auth.label=Temporary Key for $userid$
+op.enroll.userKeyTemporary.keyGen.auth.overwrite=false
+op.enroll.userKeyTemporary.keyGen.auth.privateKeyAttrId=k0
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.decrypt=false
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.derive=false
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.encrypt=false
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.private=false
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.sensitive=true
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.signRecover=true
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.sign=true
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.token=true
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.unwrap=false
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.verifyRecover=true
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.verify=true
+op.enroll.userKeyTemporary.keyGen.auth.private.keyCapabilities.wrap=false
+op.enroll.userKeyTemporary.keyGen.auth.privateKeyNumber=0
+op.enroll.userKeyTemporary.keyGen.auth.publicKeyAttrId=k1
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.decrypt=false
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.derive=false
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.encrypt=false
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.private=false
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.sensitive=true
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.signRecover=true
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.sign=true
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.token=true
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.unwrap=false
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.verifyRecover=true
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.verify=true
+op.enroll.userKeyTemporary.keyGen.auth.public.keyCapabilities.wrap=false
+op.enroll.userKeyTemporary.keyGen.auth.publicKeyNumber=1
+op.enroll.userKeyTemporary.keyGen.encryption.ca.conn=ca1
+op.enroll.userKeyTemporary.keyGen.encryption.ca.profileId=caTempTokenUserEncryptionKeyEnrollment
+op.enroll.userKeyTemporary.keyGen.encryption.certAttrId=c2
+op.enroll.userKeyTemporary.keyGen.encryption.certId=C2
+op.enroll.userKeyTemporary.keyGen.encryption.cuid_label=$cuid$
+op.enroll.userKeyTemporary.keyGen.encryption.keySize=1024
+op.enroll.userKeyTemporary.keyGen.encryption.keyUsage=0
+op.enroll.userKeyTemporary.keyGen.encryption.keyUser=0
+op.enroll.userKeyTemporary.keyGen.encryption.label=encryption key for $userid$
+op.enroll.userKeyTemporary.keyGen.encryption.overwrite=true
+op.enroll.userKeyTemporary.keyGen.encryption.privateKeyAttrId=k4
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.decrypt=true
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.derive=false
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.encrypt=false
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.private=true
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.sensitive=true
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.sign=false
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.signRecover=false
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.token=true
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.unwrap=true
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.verify=false
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.verifyRecover=false
+op.enroll.userKeyTemporary.keyGen.encryption.private.keyCapabilities.wrap=false
+op.enroll.userKeyTemporary.keyGen.encryption.privateKeyNumber=4
+op.enroll.userKeyTemporary.keyGen.encryption.publicKeyAttrId=k5
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.decrypt=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.derive=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.encrypt=true
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.private=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.sensitive=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.sign=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.signRecover=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.token=true
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.unwrap=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.verify=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.verifyRecover=false
+op.enroll.userKeyTemporary.keyGen.encryption.public.keyCapabilities.wrap=true
+op.enroll.userKeyTemporary.keyGen.encryption.publicKeyNumber=5
+op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.revokeCert.reason=0
+op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.revokeCert=true
+op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.scheme=RecoverLast
+op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.archive=true
+op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.drm.conn=kra1
+op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.enable=true
+op.enroll.userKeyTemporary.keyGen.keyType.num=3
+op.enroll.userKeyTemporary.keyGen.keyType.value.0=auth
+op.enroll.userKeyTemporary.keyGen.keyType.value.1=signing
+op.enroll.userKeyTemporary.keyGen.keyType.value.2=encryption
+op.enroll.userKeyTemporary.keyGen.recovery.onHold.keyType.num=2
+op.enroll.userKeyTemporary.keyGen.recovery.onHold.keyType.value.0=signing
+op.enroll.userKeyTemporary.keyGen.recovery.onHold.keyType.value.1=encryption
+op.enroll.userKeyTemporary.keyGen.signing.ca.conn=ca1
+op.enroll.userKeyTemporary.keyGen.signing.ca.profileId=caTempTokenUserSigningKeyEnrollment
+op.enroll.userKeyTemporary.keyGen.signing.certAttrId=c1
+op.enroll.userKeyTemporary.keyGen.signing.certId=C1
+op.enroll.userKeyTemporary.keyGen.signing.cuid_label=$cuid$
+op.enroll.userKeyTemporary.keyGen.signing.keySize=1024
+op.enroll.userKeyTemporary.keyGen.signing.keyUsage=0
+op.enroll.userKeyTemporary.keyGen.signing.keyUser=0
+op.enroll.userKeyTemporary.keyGen.signing.label=signing key for $userid$
+op.enroll.userKeyTemporary.keyGen.signing.overwrite=true
+op.enroll.userKeyTemporary.keyGen.signing.privateKeyAttrId=k2
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.decrypt=false
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.derive=false
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.encrypt=false
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.private=true
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.sensitive=true
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.signRecover=true
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.sign=true
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.token=true
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.unwrap=false
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.verify=false
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.verifyRecover=false
+op.enroll.userKeyTemporary.keyGen.signing.private.keyCapabilities.wrap=false
+op.enroll.userKeyTemporary.keyGen.signing.privateKeyNumber=2
+op.enroll.userKeyTemporary.keyGen.signing.publicKeyAttrId=k3
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.decrypt=false
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.derive=false
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.encrypt=false
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.private=false
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.sensitive=false
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.sign=false
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.signRecover=false
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.token=true
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.unwrap=false
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.verifyRecover=true
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.verify=true
+op.enroll.userKeyTemporary.keyGen.signing.public.keyCapabilities.wrap=false
+op.enroll.userKeyTemporary.keyGen.signing.publicKeyNumber=3
+op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.revokeCert.reason=0
+op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.revokeCert=true
+op.enroll.userKeyTemporary.keyGen.signing.recovery.onHold.scheme=GenerateNewKey
+op.enroll.userKeyTemporary.keyGen.tokenName=$auth.cn$ (Temporary)
+op.enroll.userKeyTemporary.loginRequest.enable=true
+op.enroll.userKeyTemporary.pinReset.enable=true
+op.enroll.userKeyTemporary.pinReset.pin.maxLen=10
+op.enroll.userKeyTemporary.pinReset.pin.maxRetries=127
+op.enroll.userKeyTemporary.pinReset.pin.minLen=4
+op.enroll.userKeyTemporary.pkcs11obj.compress.enable=true
+op.enroll.userKeyTemporary.pkcs11obj.enable=true
+op.enroll.userKeyTemporary.tks.conn=tks1
+op.enroll.userKey.temporaryToken.tokenType=userKeyTemporary
+op.enroll.userKeyTemporary.update.applet.directory=[TPS_DIR]/applets
+op.enroll.userKeyTemporary.update.applet.emptyToken.enable=true
+op.enroll.userKeyTemporary.update.applet.enable=true
+op.enroll.userKeyTemporary.update.applet.encryption=true
+op.enroll.userKeyTemporary.update.applet.requiredVersion=1.4.4d40a449
+op.enroll.userKeyTemporary.update.symmetricKeys.enable=false
+op.enroll.userKeyTemporary.update.symmetricKeys.requiredVersion=1
+op.enroll.userKey.tks.conn=tks1
+op.enroll.userKey.update.applet.directory=[TPS_DIR]/applets
+op.enroll.userKey.update.applet.emptyToken.enable=true
+op.enroll.userKey.update.applet.enable=true
+op.enroll.userKey.update.applet.encryption=true
+op.enroll.userKey.update.applet.requiredVersion=1.4.4d40a449
+op.enroll.userKey.update.symmetricKeys.enable=false
+op.enroll.userKey.update.symmetricKeys.requiredVersion=1
+op.format.allowUnknownToken=true
+op.format.tokenProfileResolver=formatMappingResolver
+op.format.cleanToken.auth.enable=false
+op.format.cleanToken.auth.id=ldap1
+op.format.cleanToken.ca.conn=ca1
+op.format.cleanToken.cardmgr_instance=A0000000030000
+op.format.cleanToken.issuerinfo.enable=true
+op.format.cleanToken.issuerinfo.value=
+op.format.cleanToken.loginRequest.enable=true
+op.format.cleanToken.revokeCert=true
+op.format.cleanToken.tks.conn=tks1
+op.format.cleanToken.update.applet.directory=[TPS_DIR]/applets
+op.format.cleanToken.update.applet.emptyToken.enable=true
+op.format.cleanToken.update.applet.encryption=true
+op.format.cleanToken.update.applet.requiredVersion=1.4.4d40a449
+op.format.cleanToken.update.symmetricKeys.enable=false
+op.format.cleanToken.update.symmetricKeys.requiredVersion=1
+op.format.soCleanSOToken.auth.enable=false
+op.format.soCleanSOToken.auth.id=ldap1
+op.format.soCleanSOToken.ca.conn=ca1
+op.format.soCleanSOToken.cardmgr_instance=A0000000030000
+op.format.soCleanSOToken.issuerinfo.enable=true
+op.format.soCleanSOToken.issuerinfo.value=
+op.format.soCleanSOToken.loginRequest.enable=false
+op.format.soCleanSOToken.revokeCert=true
+op.format.soCleanSOToken.tks.conn=tks1
+op.format.soCleanSOToken.update.applet.directory=[TPS_DIR]/applets
+op.format.soCleanSOToken.update.applet.emptyToken.enable=true
+op.format.soCleanSOToken.update.applet.encryption=true
+op.format.soCleanSOToken.update.applet.requiredVersion=1.4.4d40a449
+op.format.soCleanSOToken.update.symmetricKeys.enable=false
+op.format.soCleanSOToken.update.symmetricKeys.requiredVersion=1
+op.format.soCleanUserToken.auth.enable=false
+op.format.soCleanUserToken.auth.id=ldap1
+op.format.soCleanUserToken.ca.conn=ca1
+op.format.soCleanUserToken.cardmgr_instance=A0000000030000
+op.format.soCleanUserToken.issuerinfo.enable=true
+op.format.soCleanUserToken.issuerinfo.value=
+op.format.soCleanUserToken.loginRequest.enable=false
+op.format.soCleanUserToken.revokeCert=true
+op.format.soCleanUserToken.tks.conn=tks1
+op.format.soCleanUserToken.update.applet.directory=[TPS_DIR]/applets
+op.format.soCleanUserToken.update.applet.emptyToken.enable=true
+op.format.soCleanUserToken.update.applet.encryption=true
+op.format.soCleanUserToken.update.applet.requiredVersion=1.4.4d40a449
+op.format.soCleanUserToken.update.symmetricKeys.enable=false
+op.format.soCleanUserToken.update.symmetricKeys.requiredVersion=1
+op.format.soKey.auth.enable=true
+op.format.soKey.auth.id=ldap2
+op.format.soKey.ca.conn=ca1
+op.format.soKey.cardmgr_instance=A0000000030000
+op.format.soKey.issuerinfo.enable=true
+op.format.soKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome
+op.format.soKey.loginRequest.enable=true
+op.format.soKey.revokeCert=true
+op.format.soKey.tks.conn=tks1
+op.format.soKey.update.applet.directory=[TPS_DIR]/applets
+op.format.soKey.update.applet.emptyToken.enable=true
+op.format.soKey.update.applet.encryption=true
+op.format.soKey.update.applet.requiredVersion=1.4.4d40a449
+op.format.soKey.update.symmetricKeys.enable=false
+op.format.soKey.update.symmetricKeys.requiredVersion=1
+op.format.soUserKey.auth.enable=false
+op.format.soUserKey.auth.id=ldap1
+op.format.soUserKey.ca.conn=ca1
+op.format.soUserKey.cardmgr_instance=A0000000030000
+op.format.soUserKey.issuerinfo.enable=true
+op.format.soUserKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome
+op.format.soUserKey.loginRequest.enable=false
+op.format.soUserKey.revokeCert=true
+op.format.soUserKey.tks.conn=tks1
+op.format.soUserKey.update.applet.directory=[TPS_DIR]/applets
+op.format.soUserKey.update.applet.emptyToken.enable=true
+op.format.soUserKey.update.applet.encryption=true
+op.format.soUserKey.update.applet.requiredVersion=1.4.4d40a449
+op.format.soUserKey.update.symmetricKeys.enable=false
+op.format.soUserKey.update.symmetricKeys.requiredVersion=1
+op.format.tokenKey.auth.enable=true
+op.format.tokenKey.auth.id=ldap1
+op.format.tokenKey.ca.conn=ca1
+op.format.tokenKey.cardmgr_instance=A0000000030000
+op.format.tokenKey.issuerinfo.enable=true
+op.format.tokenKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome
+op.format.tokenKey.loginRequest.enable=true
+op.format.tokenKey.revokeCert=true
+op.format.tokenKey.tks.conn=tks1
+op.format.tokenKey.update.applet.directory=[TPS_DIR]/applets
+op.format.tokenKey.update.applet.emptyToken.enable=true
+op.format.tokenKey.update.applet.encryption=true
+op.format.tokenKey.update.applet.requiredVersion=1.4.4d40a449
+op.format.tokenKey.update.symmetricKeys.enable=false
+op.format.tokenKey.update.symmetricKeys.requiredVersion=1
+op.format.userKey.auth.enable=true
+op.format.userKey.auth.id=ldap1
+op.format.userKey.ca.conn=ca1
+op.format.userKey.cardmgr_instance=A0000000030000
+op.format.userKey.issuerinfo.enable=true
+op.format.userKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome
+op.format.userKey.loginRequest.enable=true
+op.format.userKey.revokeCert=true
+op.format.userKey.tks.conn=tks1
+op.format.userKey.update.applet.directory=[TPS_DIR]/applets
+op.format.userKey.update.applet.emptyToken.enable=true
+op.format.userKey.update.applet.encryption=true
+op.format.userKey.update.applet.requiredVersion=1.4.4d40a449
+op.format.userKey.update.symmetricKeys.enable=false
+op.format.userKey.update.symmetricKeys.requiredVersion=1
+op.pinReset.tokenProfileResolver=pinResetMappingResolver
+op.pinReset.userKey.auth.enable=true
+op.pinReset.userKey.auth.id=ldap1
+op.pinReset.userKey.cardmgr_instance=A0000000030000
+op.pinReset.userKey.loginRequest.enable=true
+op.pinReset.userKey.pinReset.pin.maxLen=10
+op.pinReset.userKey.pinReset.pin.minLen=4
+op.pinReset.userKey.tks.conn=tks1
+op.pinReset.userKey.update.applet.directory=[TPS_DIR]/applets
+op.pinReset.userKey.update.applet.emptyToken.enable=true
+op.pinReset.userKey.update.applet.enable=false
+op.pinReset.userKey.update.applet.encryption=true
+op.pinReset.userKey.update.applet.requiredVersion=1.4.4d40a449
+op.pinReset.userKey.update.symmetricKeys.enable=false
+op.pinReset.userKey.update.symmetricKeys.requiredVersion=1
+os.serverName=cert-[PKI_INSTANCE_NAME]
+os.userid=nobody
+passwordClass=com.netscape.cmsutil.password.PlainPasswordFile
+passwordFile=[PKI_INSTANCE_PATH]/conf/password.conf
+pidDir=[PKI_PIDDIR]
+pkicreate.admin_secure_port=[PKI_ADMIN_SECURE_PORT]
+pkicreate.agent_secure_port=[PKI_AGENT_SECURE_PORT]
+pkicreate.ee_secure_port=[PKI_EE_SECURE_PORT]
+pkicreate.group=[PKI_GROUP]
+pkicreate.pki_instance_name=[PKI_INSTANCE_NAME]
+pkicreate.pki_instance_root=[PKI_INSTANCE_ROOT]
+pkicreate.secure_port=[PKI_SECURE_PORT]
+pkicreate.subsystem_type=[PKI_SUBSYSTEM_TYPE]
+pkicreate.systemd.servicename=[PKI_SYSTEMD_SERVICENAME]
+pkicreate.tomcat_server_port=[TOMCAT_SERVER_PORT]
+pkicreate.unsecure_port=[PKI_UNSECURE_PORT]
+pkicreate.user=[PKI_USER]
+pkiremove.cert.subsystem.nickname=subsystemCert cert-[PKI_INSTANCE_NAME]
+preop.admincert.profile=caAdminCert
+preop.admin.group=TPS Agents,TPS Operators,Administrators,TPS Officers
+preop.admin.name=Token Processing Service Manager Administrator
+preop.cert.admin.defaultSigningAlgorithm=SHA256withRSA
+preop.cert.admin.dn=uid=admin,cn=admin
+preop.cert.admin.keysize.custom_size=2048
+preop.cert.admin.keysize.size=2048
+preop.cert.admin.profile=adminCert.profile
+preop.cert.audit_signing.cncomponent.override=true
+preop.cert.audit_signing.defaultSigningAlgorithm=SHA256withRSA
+preop.cert.audit_signing.dn=CN=TPS Audit Signing Certificate
+preop.cert.audit_signing.enable=true
+preop.cert.audit_signing.keysize.custom_size=2048
+preop.cert.audit_signing.keysize.size=2048
+preop.cert.audit_signing.nickname=auditSigningCert cert-[PKI_INSTANCE_NAME]
+preop.cert.audit_signing.profile=caInternalAuthAuditSigningCert
+preop.cert.audit_signing.signing.required=false
+preop.cert.audit_signing.subsystem=tps
+preop.cert.audit_signing.type=remote
+preop.cert.audit_signing.userfriendlyname=TPS Audit Signing Certificate
+preop.cert.list=sslserver,subsystem,audit_signing
+preop.cert.rsalist=audit_signing
+preop.cert.sslserver.cncomponent.override=false
+preop.cert.sslserver.defaultSigningAlgorithm=SHA256withRSA
+preop.cert.sslserver.dn=CN=[PKI_HOSTNAME]
+preop.cert.sslserver.enable=true
+preop.cert.sslserver.keysize.custom_size=2048
+preop.cert.sslserver.keysize.size=2048
+preop.cert.sslserver.nickname=[PKI_SSL_SERVER_NICKNAME]
+preop.cert.sslserver.profile=caInternalAuthServerCert
+preop.cert.sslserver.signing.required=false
+preop.cert.sslserver.subsystem=tps
+preop.cert.sslserver.type=remote
+preop.cert.sslserver.userfriendlyname=SSL Server Certificate
+preop.cert.subsystem.cncomponent.override=true
+preop.cert.subsystem.defaultSigningAlgorithm=SHA256withRSA
+preop.cert.subsystem.dn=CN=TPS Subsystem Certificate
+preop.cert.subsystem.enable=true
+preop.cert.subsystem.keysize.custom_size=2048
+preop.cert.subsystem.keysize.size=2048
+preop.cert.subsystem.nickname=subsystemCert cert-[PKI_INSTANCE_NAME]
+preop.cert.subsystem.profile=caInternalAuthSubsystemCert
+preop.cert.subsystem.signing.required=false
+preop.cert.subsystem.subsystem=tps
+preop.cert.subsystem.type=remote
+preop.cert.subsystem.userfriendlyname=Subsystem Certificate
+preop.configModules.count=3
+preop.configModules.module0.commonName=NSS Internal PKCS #11 Module
+preop.configModules.module0.imagePath=/pki/images/clearpixel.gif
+preop.configModules.module0.userFriendlyName=NSS Internal PKCS #11 Module
+preop.configModules.module1.commonName=nfast
+preop.configModules.module1.imagePath=/pki/images/clearpixel.gif
+preop.configModules.module1.userFriendlyName=nCipher's nFast Token Hardware Module
+preop.configModules.module2.commonName=lunasa
+preop.configModules.module2.imagePath=/pki/images/clearpixel.gif
+preop.configModules.module2.userFriendlyName=SafeNet's LunaSA Token Hardware Module
+preop.hierarchy.profile=caCert.profile
+preop.internaldb.data_ldif=/usr/share/pki/tps/conf/db.ldif,/usr/share/pki/tps/conf/acl.ldif
+preop.internaldb.index_ldif=/usr/share/pki/tps/conf/index.ldif
+preop.internaldb.ldif=/usr/share/pki/tps/conf/database.ldif
+preop.internaldb.manager_ldif=/usr/share/pki/tps/conf/manager.ldif
+preop.internaldb.post_ldif=/usr/share/pki/tps/conf/vlv.ldif,/usr/share/pki/tps/conf/vlvtasks.ldif
+preop.internaldb.schema.ldif=/usr/share/pki/tps/conf/schema.ldif
+preop.internaldb.wait_dn=cn=index1160528734, cn=index, cn=tasks, cn=config
+preop.module.token=Internal Key Storage Token
+preop.pin=[PKI_RANDOM_NUMBER]
+preop.product.name=CS
+preop.securitydomain.admin_url=https://[PKI_HOSTNAME]:8443
+preop.system.fullname=Token Processing Service
+preop.system.name=TPS
+preop.wizard.name=TPS Setup Wizard
+proxy.securePort=[PKI_PROXY_SECURE_PORT]
+proxy.unsecurePort=[PKI_PROXY_UNSECURE_PORT]
+tokenProfileResolver.list=formatMappingResolver,enrollMappingResolver,pinResetMappingResolver
+tokenProfileResolver.enrollMappingResolver.class_id=mappingTokenProfileResolverImpl
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.appletMajorVersion=1
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.appletMinorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.tokenATR=
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.tokenCUID.end=
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.tokenCUID.start=
+tokenProfileResolver.enrollMappingResolver.mapping.0.filter.tokenType=userKey
+tokenProfileResolver.enrollMappingResolver.mapping.0.target.tokenType=userKey
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.appletMajorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.appletMinorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.tokenATR=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.tokenCUID.end=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.tokenCUID.start=
+tokenProfileResolver.enrollMappingResolver.mapping.1.filter.tokenType=soKey
+tokenProfileResolver.enrollMappingResolver.mapping.1.target.tokenType=soKey
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.appletMajorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.appletMinorVersion=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.tokenATR=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.tokenCUID.end=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.tokenCUID.start=
+tokenProfileResolver.enrollMappingResolver.mapping.2.filter.tokenType=
+tokenProfileResolver.enrollMappingResolver.mapping.2.target.tokenType=userKey
+tokenProfileResolver.enrollMappingResolver.mapping.order=0,1,2
+tokenProfileResolver.formatMappingResolver.class_id=mappingTokenProfileResolverImpl
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.0.filter.tokenType=soCleanUserToken
+tokenProfileResolver.formatMappingResolver.mapping.0.target.tokenType=soCleanUserToken
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.1.filter.tokenType=soUserKey
+tokenProfileResolver.formatMappingResolver.mapping.1.target.tokenType=soUserKey
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.2.filter.tokenType=soKey
+tokenProfileResolver.formatMappingResolver.mapping.2.target.tokenType=soKey
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.3.filter.tokenType=userKey
+tokenProfileResolver.formatMappingResolver.mapping.3.target.tokenType=userKey
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.4.filter.tokenType=soCleanSOToken
+tokenProfileResolver.formatMappingResolver.mapping.4.target.tokenType=soCleanSOToken
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.5.filter.tokenType=cleanToken
+tokenProfileResolver.formatMappingResolver.mapping.5.target.tokenType=cleanToken
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.appletMajorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.appletMinorVersion=
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.tokenATR=
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.tokenCUID.end=
+tokenProfileResolver.formatMappingResolver.mapping.6.filter.tokenCUID.start=
+tokenProfileResolver.formatMappingResolver.mapping.6.target.tokenType=tokenKey
+tokenProfileResolver.formatMappingResolver.mapping.order=0,1,2,3,4,5,6
+tokenProfileResolver.pinResetMappingResolver.class_id=mappingTokenProfileResolverImpl
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.appletMajorVersion=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.appletMinorVersion=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.tokenATR=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.tokenCUID.end=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.tokenCUID.start=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.filter.tokenType=
+tokenProfileResolver.pinResetMappingResolver.mapping.0.target.tokenType=userKey
+tokenProfileResolver.pinResetMappingResolver.mapping.order=0
+registry.file=[PKI_INSTANCE_PATH]/conf/tps/registry.cfg
+selftests._000=##
+selftests._001=## Self Tests
+selftests._002=##
+selftests._003=## The Self-Test plugin TPSSystemCertsVerification uses the
+selftests._004=## following parameters (where certusage is optional):
+selftests._005=## tps.cert.list = <list of cert tag names deliminated by ",">
+selftests._006=## tps.cert.<cert tag name>.nickname
+selftests._007=## tps.cert.<cert tag name>.certusage
+selftests._008=##
+selftests.container.instance.TPSPresence=org.dogtagpki.server.tps.selftests.TPSPresence
+selftests.container.instance.TPSValidity=org.dogtagpki.server.tps.selftests.TPSValidity
+selftests.container.instance.SystemCertsVerification=com.netscape.cms.selftests.common.SystemCertsVerification
+selftests.container.logger.bufferSize=512
+selftests.container.logger.class=com.netscape.cms.logging.RollingLogFile
+selftests.container.logger.enable=true
+selftests.container.logger.expirationTime=0
+selftests.container.logger.fileName=[PKI_INSTANCE_PATH]/logs/[PKI_SUBSYSTEM_TYPE]/selftests.log
+selftests.container.logger.flushInterval=5
+selftests.container.logger.level=1
+selftests.container.logger.maxFileSize=2000
+selftests.container.logger.register=false
+selftests.container.logger.rolloverInterval=2592000
+selftests.container.logger.type=transaction
+selftests.container.order.onDemand=TPSPresence:critical, SystemCertsVerification:critical, TPSValidity:critical
+selftests.container.order.startup=TPSPresence:critical, SystemCertsVerification:critical
+selftests.plugin.TPSPresence.TpsSubId=tps
+selftests.plugin.TPSValidity.TpsSubId=tps
+selftests.plugin.SystemCertsVerification.SubId=tps
+service.instanceDir=[PKI_INSTANCE_ROOT]
+service.instanceID=[PKI_INSTANCE_NAME]
+service.machineName=[PKI_HOSTNAME]
+service.non_clientauth_securePort=[PKI_EE_SECURE_PORT]
+service.securePort=[PKI_AGENT_SECURE_PORT]
+service.unsecurePort=[PKI_UNSECURE_PORT]
+smtp.host=localhost
+smtp.port=25
+subsystem.0.class=org.dogtagpki.server.tps.TPSSubsystem
+subsystem.0.id=tps
+subsystem.1.class=com.netscape.cmscore.selftests.SelfTestSubsystem
+subsystem.1.id=selftests
+subsystem.2.class=com.netscape.cmscore.util.StatsSubsystem
+subsystem.2.id=stats
+target._000=#########################################
+target._001=# entries to enable configuration of parameter sets through the TPS UI agent and admin tabs
+target._002=#
+target._003=# target.configure.list = comma separated lists of all parameter sets that can be configured by the admin.
+target._004=# Each entry will show up (with underscore replaced by space) under Advanced Configuration on the admin tab.
+target._005=#
+target._006=# target.agent_approve.list = comma separated subset of above list. Parameter sets in this list
+target._007=# will show up in the agent tab (under advanced configuration) and will require agent involvement
+target._008=# (enable/ disable) to be edited.
+target._009=#
+target._010=# For the wording to display correctly, the values in the above list should be plurals.
+target._011=#
+target._012=# Each parameter set in the lists above requires three parameters:
+target._013=# target.<type name>.list : list of choices of this parameter set type (will display in the drop down box)
+target._014=# target.<type name>.pattern : the regular expression to select parameters in CS.cfg for this parameter set.
+target._015=# target.<type_name>.displayname: used in the UI display text. This should be the singular form of <type_name>.
+target._016=#
+target._017=# The exception is the parameter set Generals, which has only a pattern and displayname defined.
+target._018=#
+target._019=########################################
+target.agent_approve.list=Profiles
+target.Authentication_Sources.displayname=Authentication Source
+target.Authentication_Sources.list=ldap1
+target.Authentication_Sources.pattern=auths\.instance\.$name\..*
+target.configure.list=Profiles,Subsystem_Connections,Profile_Mappings,Authentication_Sources
+target.Generals.displayname=General
+target.Generals.pattern=^applet\..*\|^general\..*\|^failover.pod.enable\|^channel\..*
+target.Profile_Mappings.displayname=Token Profile Mapping Resolvers
+target.Profile_Mappings.list=enrollMappingResolver,formatMappingResolver,pinResetMappingResolver
+target.Profile_Mappings.pattern=tokenProfileResolver\.$name\.mapping\..*
+target.Profiles.displayname=Token Profile
+target.Profiles.list=userKey,soKey,soCleanUserToken,soUserKey,cleanToken,soCleanSoToken,tokenKey
+target.Profiles.pattern=op\..*\.$name\..*
+target.Subsystem_Connections.displayname=Subsystem Connection
+target.Subsystem_Connections.list=
+target.Subsystem_Connections.pattern=tps.connector\.$name\..*
+tokendb._000=#########################################
+tokendb._001=# tokendb.auditLog:
+tokendb._002=# - audit log path
+tokendb._003=# tokendb.host:
+tokendb._004=# - tokendb host name
+tokendb._005=# tokendb.port:
+tokendb._006=# - tokendb port number
+tokendb._007=# tokendb.bindDN:
+tokendb._008=# - tokendb administration DN (i.e. cn=Directory Manager)
+tokendb._009=# tokendb.bindPassPath:
+tokendb._010=# - tokendb administration password file path
+tokendb._011=# tokendb.templateDir
+tokendb._012=# - directory where all the tokendb templates are located
+tokendb._013=# tokendb.userBaseDN:
+tokendb._014=# - directory base DN for users and groups
+tokendb._015=# tokendb.baseDN:
+tokendb._016=# - directory base DN for tokens
+tokendb._017=# tokendb.activityBaseDN:
+tokendb._018=# - directory base DN for activities
+tokendb._019=# tokendb.indexTemplate=index.template
+tokendb._020=# - index template
+tokendb._021=# tokendb.newTemplate=new.template
+tokendb._022=# - add template
+tokendb._023=# tokendb.showTemplate=show.template
+tokendb._024=# - show template
+tokendb._025=# tokendb.errorTemplate=error.template
+tokendb._026=# - error template
+tokendb._027=# tokendb.searchTemplate=search.template
+tokendb._028=# - search template
+tokendb._029=# tokendb.searchResultTemplate=searchResults.template
+tokendb._030=# - search result template
+tokendb._031=# tokendb.editTemplate=edit.template
+tokendb._032=# - edit template
+tokendb._033=# tokendb.editResultTemplate=editResults.template
+tokendb._034=# - edit result template
+tokendb._035=# tokendb.addResultTemplate=addResults.template
+tokendb._036=# - add result template
+tokendb._037=# tokendb.deleteResultTemplate=deleteResults.template
+tokendb._038=# - delete result template
+tokendb._039=# tokendb.searchActivityTemplate=searchActivity.template
+tokendb._040=# - search activity template
+tokendb._041=# tokendb.searchActivityResultTemplate=searchActivityResults.template
+tokendb._042=# - search activity result template
+tokendb._043=# tokendb.showAdminTemplate=showAdmin.template
+tokendb._044=# - show admin template
+tokendb._045=# tokendb.editAdminTemplate=editAdmin.template
+tokendb._046=# - edit admin template
+tokendb._047=# tokendb.editAdminResultTemplate=editAdminResults.template
+tokendb._048=# - edit admin result template
+tokendb._049=# tokendb.searchAdminTemplate=searchAdmin.template
+tokendb._050=# - search admin template
+tokendb._051=# tokendb.searchAdminResultTemplate=searchAdminResults.template
+tokendb._052=# - search admin result template
+tokendb._053=# tokendb.defaultPolicy:
+tokendb._054=# Supported Policy (Separated by ; [Semicolon]):
+tokendb._055=# For example, PIN_RESET=YES|NO;RE_ENROLL=YES|NO
+tokendb._056=# PIN_RESET=YES|NO
+tokendb._057=# - If not present, pin reset by user is allowed.
+tokendb._058=# - If present and agent change PIN_RESET from NO
+tokendb._059=# to YES, user is allowed to do pin reset. This
+tokendb._060=# policy will be changed back to NO after pin reset.
+tokendb._061=# RE_ENROLL=YES|NO
+tokendb._062=# - If not present, re-enrollment is allowed.
+tokendb._063=# - If present, re-enrollment is allowed when RE_ENROLL
+tokendb._064=# is set to YES. Otherwise, re-enrollment is not
+tokendb._065=# allowed.
+tokendb._066=# tokendb.allowedTransitions:
+tokendb._067=# - has transitions between the following states
+tokendb._068=# TOKEN_UNINITIALIZED = 0,
+tokendb._069=# TOKEN_DAMAGED =1,
+tokendb._070=# TOKEN_PERM_LOST=2,
+tokendb._071=# TOKEN_TEMP_LOST=3,
+tokendb._072=# TOKEN_FOUND =4,
+tokendb._073=# TOKEN_TEMP_LOST_PERM_LOST =5,
+tokendb._074=# TOKEN_TERMINATED = 6
+tokendb._075=#########################################
+tokendb.activityBaseDN=ou=Activities,[TOKENDB_ROOT]
+tokendb.addConfigTemplate=addConfig.template
+tokendb.addResultTemplate=addResults.template
+tokendb.agentSelectConfigTemplate=agentSelectConfig.template
+tokendb.agentViewConfigTemplate=agentViewConfig.template
+tokendb.allowedTransitions=0:1,0:2,0:3,0:4,0:5,0:6,3:4,3:5,3:6,4:1,4:2,4:3,4:6
+tokendb.auditAdminTemplate=auditAdmin.template
+tokendb.auditLog=[PKI_INSTANCE_PATH]/logs/tokendb-audit.log
+tokendb.baseDN=ou=Tokens,[TOKENDB_ROOT]
+tokendb.bindDN=cn=Directory Manager
+tokendb.bindPassPath=[PKI_INSTANCE_PATH]/conf/password.conf
+tokendb.certBaseDN=ou=Certificates,[TOKENDB_ROOT]
+tokendb.confirmConfigChangesTemplate=confirmConfigChanges.template
+tokendb.confirmDeleteConfigTemplate=confirmDeleteConfig.template
+tokendb.defaultPolicy=RE_ENROLL=YES;RENEW=NO;FORCE_FORMAT=NO;PIN_RESET=NO;RESET_PIN_RESET_TO_NO=NO
+tokendb.deleteResultTemplate=deleteResults.template
+tokendb.deleteTemplate=delete.template
+tokendb.doTokenConfirmTemplate=doTokenConfirm.template
+tokendb.doTokenTemplate=doToken.template
+tokendb.editConfigTemplate=editConfig.template
+tokendb.editResultTemplate=editResults.template
+tokendb.editTemplate=edit.template
+tokendb.editUserTemplate=editUser.template
+tokendb.errorTemplate=error.template
+tokendb.hostport=[TOKENDB_HOST]:[TOKENDB_PORT]
+tokendb.indexAdminTemplate=indexAdmin.template
+tokendb.indexOperatorTemplate=indexOperator.template
+tokendb.indexTemplate=index.template
+tokendb.newTemplate=new.template
+tokendb.newUserTemplate=newUser.template
+tokendb.revokeTemplate=revoke.template
+tokendb.searchActivityAdminResultTemplate=searchActivityAdminResults.template
+tokendb.searchActivityAdminTemplate=searchActivityAdmin.template
+tokendb.searchActivityResultTemplate=searchActivityResults.template
+tokendb.searchActivityTemplate=searchActivity.template
+tokendb.searchAdminResultTemplate=searchAdminResults.template
+tokendb.searchAdminTemplate=searchAdmin.template
+tokendb.searchCertificateResultTemplate=searchCertificateResults.template
+tokendb.searchCertificateTemplate=searchCertificate.template
+tokendb.searchResultTemplate=searchResults.template
+tokendb.searchTemplate=search.template
+tokendb.searchUserResultTemplate=searchUserResults.template
+tokendb.searchUserTemplate=searchUser.template
+tokendb.selectConfigTemplate=selectConfig.template
+tokendb.selfTestResultsTemplate=selfTestResults.template
+tokendb.selfTestTemplate=selfTest.template
+tokendb.showAdminTemplate=showAdmin.template
+tokendb.showCertTemplate=showCert.template
+tokendb.showTemplate=show.template
+tokendb.ssl=false
+tokendb.templateDir=[PKI_INSTANCE_PATH]/docroot/tus
+tokendb.userBaseDN=[TOKENDB_ROOT]
+tokendb.userDeleteTemplate=userDelete.template
+tps._000=########################################
+tps._001=# For verifying system certificates
+tps._002=# tps.cert.list=sslserver,subsystem,audit_signing
+tps._003=# tps.cert.sslserver.nickname=xxx
+tps._005=# tps.cert.subsystem.nickname=xxx
+tps._007=# tps.cert.audit_signing.nickname=xxx
+tps._008=# operations.allowedTransitions:
+tps._009=# - token operations, like formatting and enrollment have transitions between the following states
+tps._010=# TOKEN_UNINITIALIZED = 0,
+tps._011=# TOKEN_DAMAGED =1,
+tps._012=# TOKEN_PERM_LOST=2,
+tps._013=# TOKEN_TEMP_LOST=3,
+tps._014=# TOKEN_FOUND =4,
+tps._015=# TOKEN_TEMP_LOST_PERM_LOST =5,
+tps._016=# TOKEN_TERMINATED = 6
+tps._017=# Sample: tps.operations.allowedTransitions=0:0,0:4,4:6,6:0
+tps._018=########################################
+tps.cert.audit_signing.certusage=ObjectSigner
+tps.cert.audit_signing.nickname=[HSM_LABEL][NICKNAME]
+tps.cert.list=sslserver,subsystem,audit_signing
+tps.cert.sslserver.certusage=SSLServer
+tps.cert.subsystem.certusage=SSLClient
+tps.operations.allowedTransitions=0:0,0:4,4:0
+usrgrp._000=##
+usrgrp._001=## User/Group
+usrgrp._002=##
+usrgrp.ldap=internaldb
diff --git a/base/tps/shared/conf/Catalina/localhost/tps.xml b/base/tps/shared/conf/Catalina/localhost/tps.xml
new file mode 100644
index 000000000..d80c1296d
--- /dev/null
+++ b/base/tps/shared/conf/Catalina/localhost/tps.xml
@@ -0,0 +1,37 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- BEGIN COPYRIGHT BLOCK
+ Copyright (C) 2012 Red Hat, Inc.
+ All rights reserved.
+ Modifications: configuration parameters
+ END COPYRIGHT BLOCK
+-->
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<Context docBase="/usr/share/pki/tps/webapps/tps" crossContext="true" allowLinking="true">
+
+ <Manager
+ secureRandomProvider="Mozilla-JSS" secureRandomAlgorithm="pkcs11prng"/>
+
+ <Valve className="com.netscape.cms.tomcat.SSLAuthenticatorWithFallback"
+ alwaysUseSession="true"
+ secureRandomProvider="Mozilla-JSS"
+ secureRandomAlgorithm="pkcs11prng"/>
+
+ <Realm className="com.netscape.cms.tomcat.ProxyRealm" />
+
+</Context>
diff --git a/base/tps/shared/conf/acl.ldif b/base/tps/shared/conf/acl.ldif
new file mode 100644
index 000000000..41b38137b
--- /dev/null
+++ b/base/tps/shared/conf/acl.ldif
@@ -0,0 +1,33 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+dn: cn=aclResources,{rootSuffix}
+objectClass: top
+objectClass: CertACLS
+cn: aclResources
+resourceACLS: certServer.general.configuration:read,modify,delete:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents";allow (modify,delete) group="Administrators":Administrators, auditors, and agents are allowed to read CMS general configuration but only administrators are allowed to modify and delete
+resourceACLS: certServer.acl.configuration:read,modify:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents";allow (modify) group="Administrators":Administrators, agents and auditors are allowed to read ACL configuration but only administrators allowed to modify
+resourceACLS: certServer.log.configuration:read,modify:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents";allow (modify) group="Administrators":Administrators, Agents, and auditors are allowed to read the log configuration but only administrators are allowed to modify
+resourceACLS: certServer.log.configuration.fileName:read,modify:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents";deny (modify) user=anybody:Nobody is allowed to modify a fileName parameter
+#resourceACLS: certServer.log.configuration.signedAudit.expirationTime:read,modify:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents";deny (modify) user=anybody:Nobody is allowed to modify an expirationTime parameter
+resourceACLS: certServer.log.content.signedAudit:read:allow (read) group="Auditors":Only auditor is allowed to read the signed audit log
+resourceACLS: certServer.log.content.system:read:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents":Administrators, auditors, and agents are allowed to read the log content
+resourceACLS: certServer.log.content.transactions:read:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents":Administrators, auditors, and agents are allowed to read the log content
+resourceACLS: certServer.auth.configuration:read,modify:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents";allow (modify) group="Administrators":Administrators, agents, and auditors are allowed to read authentication configuration but only administrators allowed to modify
+resourceACLS: certServer.registry.configuration:read,modify:allow (read) group="Administrators" || group="Auditors" || group="Token Processing Service Manager Agents";allow (modify) group="Administrators":this acl is shared by all admin servlets
+resourceACLS: certServer.admin.certificate:import:allow (import) user="anybody":Any user may import a certificate
+resourceACLS: certServer.admin.request.enrollment:submit,read,execute:allow (submit) user="anybody":Anybody may submit an enrollment request
+resourceACLS: certServer.clone.configuration:read,modify:allow (modify,read) group="Enterprise CA Administrators" || group="Enterprise KRA Administrators" || group="Enterprise OCSP Administrators" || group="Enterprise TPS Administrators":Only Enterprise Administrators are allowed to clone the configuration.
+resourceACLS: certServer.tps.account:login,logout:allow (login,logout) user="anybody":Anybody can login and logout
+resourceACLS: certServer.tps.authenticators:read,add,modify,approve,remove:allow (read,add,modify,approve,remove) group="Administrators":Only admins can access authenticators.
+resourceACLS: certServer.tps.audit:read,modify:allow (read,modify) group="Administrators":Only admins can access configuration.
+resourceACLS: certServer.tps.config:read,modify:allow (read,modify) group="Administrators":Only admins can access configuration.
+resourceACLS: certServer.tps.connectors:read,add,modify,approve,remove:allow (read,add,modify,approve,remove) group="Administrators":Only admins can access connectors.
+resourceACLS: certServer.tps.groups:execute:allow (execute) group="Administrators":Admins may execute group operations
+resourceACLS: certServer.tps.users:execute:allow (execute) group="Administrators":Admins may execute user operations
+resourceACLS: certServer.tps.profiles:read,add,modify,approve,remove:allow (read) group="Administrators" || group="TPS Agents" ; allow (add,modify,remove) group="Administrators" ; allow (approve) group="TPS Agents":Admins and agents can read, but only admins can add, modify, and remove, and only agents can approve.
+resourceACLS: certServer.tps.profile-mappings:read,add,modify,approve,remove:allow (read,add,modify,approve,remove) group="Administrators" :Only admins can access profile mappings.
+resourceACLS: certServer.tps.selftests:read,execute:allow (read,execute) group="Administrators":Only admins can access selftests.
+resourceACLS: certServer.tps.tokens:read,add,modify,remove:allow (read) group="Administrators" || group="TPS Agents" || group="TPS Operators"; allow (add,remove) group="Administrators" ; allow (modify) group="TPS Agents":Admins, agents, operators can read tokens, but only admins can add and remove tokens, and only agents can modify tokens.
diff --git a/base/tps/shared/conf/acl.properties b/base/tps/shared/conf/acl.properties
new file mode 100644
index 000000000..840c0610e
--- /dev/null
+++ b/base/tps/shared/conf/acl.properties
@@ -0,0 +1,42 @@
+# ACL mapping
+#
+# Format:
+# <mapping name> = <resource ID>,<operation>
+# Example:
+# users = certServer.ca.users,execute
+
+
+account.login = certServer.tps.account,login
+account.logout = certServer.tps.account,logout
+audit.read = certServer.tps.audit,read
+audit.modify = certServer.tps.audit,modify
+authenticators.read = certServer.tps.authenticators,read
+authenticators.add = certServer.tps.authenticators,add
+authenticators.modify = certServer.tps.authenticators,modify
+authenticators.approve = certServer.tps.authenticators,approve
+authenticators.remove = certServer.tps.authenticators,remove
+config.read = certServer.tps.config,read
+config.modify = certServer.tps.config,modify
+connectors.read = certServer.tps.connectors,read
+connectors.add = certServer.tps.connectors,add
+connectors.modify = certServer.tps.connectors,modify
+connectors.approve = certServer.tps.connectors,approve
+connectors.remove = certServer.tps.connectors,remove
+groups = certServer.tps.groups,execute
+profiles.read = certServer.tps.profiles,read
+profiles.add = certServer.tps.profiles,add
+profiles.modify = certServer.tps.profiles,modify
+profiles.approve = certServer.tps.profiles,approve
+profiles.remove = certServer.tps.profiles,remove
+profile-mappings.read = certServer.tps.profile-mappings,read
+profile-mappings.add = certServer.tps.profile-mappings,add
+profile-mappings.modify = certServer.tps.profile-mappings,modify
+profile-mappings.approve = certServer.tps.profiles-mappings,approve
+profile-mappings.remove = certServer.tps.profile-mappings,remove
+selftests.read = certServer.tps.selftests,read
+selftests.execute = certServer.tps.selftests,execute
+tokens.read = certServer.tps.tokens,read
+tokens.add = certServer.tps.tokens,add
+tokens.modify = certServer.tps.tokens,modify
+tokens.remove = certServer.tps.tokens,remove
+users = certServer.tps.users,execute
diff --git a/base/tps/shared/conf/auth-method.properties b/base/tps/shared/conf/auth-method.properties
new file mode 100644
index 000000000..4a97df1c6
--- /dev/null
+++ b/base/tps/shared/conf/auth-method.properties
@@ -0,0 +1,27 @@
+# Authentication method mapping
+#
+# Format:
+# <mapping name> = <authentication manager>,...
+# Example:
+# default = *
+# account = certUserDBAuthMgr,passwdUserDBAuthMgr
+
+default = *
+account = certUserDBAuthMgr,passwdUserDBAuthMgr
+audit = certUserDBAuthMgr
+authenticators = certUserDBAuthMgr
+certs = certUserDBAuthMgr
+certrequests = certUserDBAuthMgr
+config = certUserDBAuthMgr
+connectors = certUserDBAuthMgr
+groups = certUserDBAuthMgr
+keys = certUserDBAuthMgr
+keyrequests = certUserDBAuthMgr
+kraconnectors = certUserDBAuthMgr
+profiles = certUserDBAuthMgr
+profile-mappings = certUserDBAuthMgr
+securityDomain.installToken = passwdUserDBAuthMgr
+selftests = certUserDBAuthMgr
+tokens = certUserDBAuthMgr
+tpsconnectors = certUserDBAuthMgr
+users = certUserDBAuthMgr
diff --git a/base/tps/shared/conf/catalina.policy b/base/tps/shared/conf/catalina.policy
new file mode 100644
index 000000000..5ccc7959e
--- /dev/null
+++ b/base/tps/shared/conf/catalina.policy
@@ -0,0 +1,182 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// Copyright (C) 2006-2010 Red Hat, Inc.
+// All rights reserved.
+// Modifications: configuration parameters
+// --- END COPYRIGHT BLOCK ---
+
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ============================================================================
+// catalina.corepolicy - Security Policy Permissions for Tomcat 6
+//
+// This file contains a default set of security policies to be enforced (by the
+// JVM) when Catalina is executed with the "-security" option. In addition
+// to the permissions granted here, the following additional permissions are
+// granted to the codebase specific to each web application:
+//
+// * Read access to the document root directory
+//
+// $Id$
+// ============================================================================
+
+
+// ========== SYSTEM CODE PERMISSIONS =========================================
+
+
+// These permissions apply to javac
+grant codeBase "file:${java.home}/lib/-" {
+ permission java.security.AllPermission;
+};
+
+// These permissions apply to all shared system extensions
+grant codeBase "file:${java.home}/jre/lib/ext/-" {
+ permission java.security.AllPermission;
+};
+
+// These permissions apply to javac when ${java.home] points at $JAVA_HOME/jre
+grant codeBase "file:${java.home}/../lib/-" {
+ permission java.security.AllPermission;
+};
+
+// These permissions apply to all shared system extensions when
+// ${java.home} points at $JAVA_HOME/jre
+grant codeBase "file:${java.home}/lib/ext/-" {
+ permission java.security.AllPermission;
+};
+
+
+// ========== CATALINA CODE PERMISSIONS =======================================
+
+
+// These permissions apply to the daemon code
+grant codeBase "file:${catalina.home}/bin/commons-daemon.jar" {
+ permission java.security.AllPermission;
+};
+
+// These permissions apply to the logging API
+grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {
+ permission java.util.PropertyPermission "java.util.logging.config.class", "read";
+ permission java.util.PropertyPermission "java.util.logging.config.file", "read";
+ permission java.io.FilePermission "${java.home}${file.separator}lib${file.separator}logging.properties", "read";
+ permission java.lang.RuntimePermission "shutdownHooks";
+ permission java.io.FilePermission "${catalina.base}${file.separator}conf${file.separator}logging.properties", "read";
+ permission java.util.PropertyPermission "catalina.base", "read";
+ permission java.util.logging.LoggingPermission "control";
+ permission java.io.FilePermission "${catalina.base}${file.separator}logs", "read, write";
+ permission java.io.FilePermission "${catalina.base}${file.separator}logs${file.separator}*", "read, write";
+ permission java.lang.RuntimePermission "getClassLoader";
+ // To enable per context logging configuration, permit read access to the appropriate file.
+ // Be sure that the logging configuration is secure before enabling such access
+ // eg for the examples web application:
+ // permission java.io.FilePermission "${catalina.base}${file.separator}webapps${file.separator}examples${file.separator}WEB-INF${file.separator}classes${file.separator}logging.properties", "read";
+};
+
+// These permissions apply to the server startup code
+grant codeBase "file:${catalina.home}/bin/bootstrap.jar" {
+ permission java.security.AllPermission;
+};
+
+// These permissions apply to the servlet API classes
+// and those that are shared across all class loaders
+// located in the "lib" directory
+grant codeBase "file:${catalina.home}/lib/-" {
+ permission java.security.AllPermission;
+};
+
+
+// ========== WEB APPLICATION PERMISSIONS =====================================
+
+
+// These permissions are granted by default to all web applications
+// In addition, a web application will be given a read FilePermission
+// and JndiPermission for all files and directories in its document root.
+grant {
+ // Required for JNDI lookup of named JDBC DataSource's and
+ // javamail named MimePart DataSource used to send mail
+ permission java.util.PropertyPermission "java.home", "read";
+ permission java.util.PropertyPermission "java.naming.*", "read";
+ permission java.util.PropertyPermission "javax.sql.*", "read";
+
+ // OS Specific properties to allow read access
+ permission java.util.PropertyPermission "os.name", "read";
+ permission java.util.PropertyPermission "os.version", "read";
+ permission java.util.PropertyPermission "os.arch", "read";
+ permission java.util.PropertyPermission "file.separator", "read";
+ permission java.util.PropertyPermission "path.separator", "read";
+ permission java.util.PropertyPermission "line.separator", "read";
+
+ // JVM properties to allow read access
+ permission java.util.PropertyPermission "java.version", "read";
+ permission java.util.PropertyPermission "java.vendor", "read";
+ permission java.util.PropertyPermission "java.vendor.url", "read";
+ permission java.util.PropertyPermission "java.class.version", "read";
+ permission java.util.PropertyPermission "java.specification.version", "read";
+ permission java.util.PropertyPermission "java.specification.vendor", "read";
+ permission java.util.PropertyPermission "java.specification.name", "read";
+
+ permission java.util.PropertyPermission "java.vm.specification.version", "read";
+ permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
+ permission java.util.PropertyPermission "java.vm.specification.name", "read";
+ permission java.util.PropertyPermission "java.vm.version", "read";
+ permission java.util.PropertyPermission "java.vm.vendor", "read";
+ permission java.util.PropertyPermission "java.vm.name", "read";
+
+ // Required for OpenJMX
+ permission java.lang.RuntimePermission "getAttribute";
+
+ // Allow read of JAXP compliant XML parser debug
+ permission java.util.PropertyPermission "jaxp.debug", "read";
+
+ // Precompiled JSPs need access to this package.
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime.*";
+
+ // Precompiled JSPs need access to this system property.
+ permission java.util.PropertyPermission "org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER", "read";
+};
+
+
+// You can assign additional permissions to particular web applications by
+// adding additional "grant" entries here, based on the code base for that
+// application, /WEB-INF/classes/, or /WEB-INF/lib/ jar files.
+//
+// Different permissions can be granted to JSP pages, classes loaded from
+// the /WEB-INF/classes/ directory, all jar files in the /WEB-INF/lib/
+// directory, or even to individual jar files in the /WEB-INF/lib/ directory.
+//
+// For instance, assume that the standard "examples" application
+// included a JDBC driver that needed to establish a network connection to the
+// corresponding database and used the scrape taglib to get the weather from
+// the NOAA web server. You might create a "grant" entries like this:
+//
+// The permissions granted to the context root directory apply to JSP pages.
+// grant codeBase "file:${catalina.home}/webapps/examples/-" {
+// permission java.net.SocketPermission "dbhost.mycompany.com:5432", "connect";
+// permission java.net.SocketPermission "*.noaa.gov:80", "connect";
+// };
+//
+// The permissions granted to the context WEB-INF/classes directory
+// grant codeBase "file:${catalina.home}/webapps/examples/WEB-INF/classes/-" {
+// };
+//
+// The permission granted to your JDBC driver
+// grant codeBase "jar:file:${catalina.home}/webapps/examples/WEB-INF/lib/driver.jar!/-" {
+// permission java.net.SocketPermission "dbhost.mycompany.com:5432", "connect";
+// };
+// The permission granted to the scrape taglib
+// grant codeBase "jar:file:${catalina.home}/webapps/examples/WEB-INF/lib/scrape.jar!/-" {
+// permission java.net.SocketPermission "*.noaa.gov:80", "connect";
+// };
diff --git a/base/tps/shared/conf/catalina.properties b/base/tps/shared/conf/catalina.properties
new file mode 100644
index 000000000..f6d1d1415
--- /dev/null
+++ b/base/tps/shared/conf/catalina.properties
@@ -0,0 +1,87 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006-2010 Red Hat, Inc.
+# All rights reserved.
+# Modifications: configuration parameters
+# --- END COPYRIGHT BLOCK ---
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# List of comma-separated packages that start with or equal this string
+# will cause a security exception to be thrown when
+# passed to checkPackageAccess unless the
+# corresponding RuntimePermission ("accessClassInPackage."+package) has
+# been granted.
+package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.,sun.beans.
+#
+# List of comma-separated packages that start with or equal this string
+# will cause a security exception to be thrown when
+# passed to checkPackageDefinition unless the
+# corresponding RuntimePermission ("defineClassInPackage."+package) has
+# been granted.
+#
+# by default, no packages are restricted for definition, and none of
+# the class loaders supplied with the JDK call checkPackageDefinition.
+#
+package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.
+
+#
+#
+# List of comma-separated paths defining the contents of the "common"
+# classloader. Prefixes should be used to define what is the repository type.
+# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
+# If left as blank,the JVM system loader will be used as Catalina's "common"
+# loader.
+# Examples:
+# "foo": Add this folder as a class repository
+# "foo/*.jar": Add all the JARs of the specified folder as class
+# repositories
+# "foo/bar.jar": Add bar.jar as a class repository
+common.loader=${catalina.home}/lib,${catalina.home}/lib/*.jar,[TOMCAT_INSTANCE_COMMON_LIB]
+
+#
+# List of comma-separated paths defining the contents of the "server"
+# classloader. Prefixes should be used to define what is the repository type.
+# Path may be relative to the CATALINA_HOME or CATALINA_BASE path or absolute.
+# If left as blank, the "common" loader will be used as Catalina's "server"
+# loader.
+# Examples:
+# "foo": Add this folder as a class repository
+# "foo/*.jar": Add all the JARs of the specified folder as class
+# repositories
+# "foo/bar.jar": Add bar.jar as a class repository
+server.loader=
+
+#
+# List of comma-separated paths defining the contents of the "shared"
+# classloader. Prefixes should be used to define what is the repository type.
+# Path may be relative to the CATALINA_BASE path or absolute. If left as blank,
+# the "common" loader will be used as Catalina's "shared" loader.
+# Examples:
+# "foo": Add this folder as a class repository
+# "foo/*.jar": Add all the JARs of the specified folder as class
+# repositories
+# "foo/bar.jar": Add bar.jar as a class repository
+# Please note that for single jars, e.g. bar.jar, you need the URL form
+# starting with file:.
+shared.loader=
+
+#
+# String cache configuration.
+tomcat.util.buf.StringCache.byte.enabled=true
+#tomcat.util.buf.StringCache.char.enabled=true
+#tomcat.util.buf.StringCache.trainThreshold=500000
+#tomcat.util.buf.StringCache.cacheSize=5000
diff --git a/base/tps/shared/conf/database.ldif b/base/tps/shared/conf/database.ldif
new file mode 100644
index 000000000..d3c5f9e68
--- /dev/null
+++ b/base/tps/shared/conf/database.ldif
@@ -0,0 +1,9 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+dn: cn=config
+changetype: modify
+replace: nsslapd-maxbersize
+nsslapd-maxbersize: 209715200
diff --git a/base/tps/shared/conf/db.ldif b/base/tps/shared/conf/db.ldif
new file mode 100644
index 000000000..afa0c3920
--- /dev/null
+++ b/base/tps/shared/conf/db.ldif
@@ -0,0 +1,54 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+dn: ou=Tokens,{rootSuffix}
+objectclass: top
+objectclass: organizationalunit
+ou: Tokens
+
+dn: ou=Activities,{rootSuffix}
+objectclass: top
+objectclass: organizationalunit
+ou: Activities
+
+dn: ou=Certificates,{rootSuffix}
+objectclass: top
+objectclass: organizationalunit
+ou: Certificates
+
+dn: ou=People,{rootSuffix}
+objectclass: top
+objectclass: organizationalunit
+ou: People
+aci: (targetattr!="userPassword")(version 3.0; acl "Enable anonymous access"; allow (read, search, compare)userdn="ldap:///anyone";)
+
+dn: ou=Groups,{rootSuffix}
+objectclass: top
+objectclass: organizationalunit
+ou: Groups
+
+dn: cn=TPS Agents,ou=Groups,{rootSuffix}
+objectClass: top
+objectClass: groupOfUniqueNames
+cn: TPS Agents
+description: Agents for TPS
+
+dn: cn=TPS Officers,ou=Groups,{rootSuffix}
+objectClass: top
+objectClass: groupOfUniqueNames
+cn: TPS Officers
+description: Security Officers for TPS
+
+dn: cn=Administrators,ou=Groups,{rootSuffix}
+objectClass: top
+objectClass: groupOfUniqueNames
+cn: Administrators
+description: Administrators for TPS
+
+dn: cn=TPS Operators,ou=Groups,{rootSuffix}
+objectClass: top
+objectClass: groupOfUniqueNames
+cn: TPS Operators
+description: Operators for TPS
diff --git a/base/tps/shared/conf/index.ldif b/base/tps/shared/conf/index.ldif
new file mode 100644
index 000000000..defe17a63
--- /dev/null
+++ b/base/tps/shared/conf/index.ldif
@@ -0,0 +1,84 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# This library 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;
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# Copyright (C) 2007 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+dn: cn=tokenUserID,cn=index,cn={database},cn=ldbm database,cn=plugins,cn=config
+objectclass: top
+objectclass: nsIndex
+cn: tokenUserID
+nsindextype: eq
+nsindextype: pres
+nsindextype: sub
+nssystemindex: false
+
+dn: cn=tokenID,cn=index,cn={database},cn=ldbm database,cn=plugins,cn=config
+objectclass: top
+objectclass: nsIndex
+cn: tokenID
+nsindextype: eq
+nsindextype: pres
+nsindextype: sub
+nssystemindex: false
+
+dn: cn=dateOfCreate,cn=index,cn={database},cn=ldbm database,cn=plugins,cn=config
+objectclass: top
+objectclass: nsIndex
+cn: dateOfCreate
+nsindextype: eq
+nsindextype: pres
+nsindextype: sub
+nssystemindex: false
+
+dn: cn=dateOfModify,cn=index,cn={database},cn=ldbm database,cn=plugins,cn=config
+objectclass: top
+objectclass: nsIndex
+cn: dateOfModify
+nsindextype: eq
+nsindextype: pres
+nsindextype: sub
+nssystemindex: false
+
+dn: cn=userCertificate,cn=index,cn={database},cn=ldbm database,cn=plugins,cn=config
+objectclass: top
+objectclass: nsIndex
+cn: userCertificate
+nsindextype: eq
+nssystemindex: false
+
+dn: cn=tokenSerial,cn=index,cn={database},cn=ldbm database,cn=plugins,cn=config
+objectclass: top
+objectclass: nsIndex
+cn: tokenSerial
+nsindextype: eq
+nssystemindex: false
+
+dn: cn=tokenKeyType,cn=index,cn={database},cn=ldbm database,cn=plugins,cn=config
+objectclass: top
+objectclass: nsIndex
+cn: tokenKeyType
+nsindextype: eq
+nssystemindex: false
+
+dn: cn=description,cn=index,cn={database},cn=ldbm database, cn=plugins, cn=config
+objectClass: top
+objectClass: nsIndex
+nsIndexType: eq
+nsIndexType: pres
+nsSystemIndex: false
+cn: description
diff --git a/base/tps/shared/conf/jk2.manifest b/base/tps/shared/conf/jk2.manifest
new file mode 100644
index 000000000..986d7b874
--- /dev/null
+++ b/base/tps/shared/conf/jk2.manifest
@@ -0,0 +1,2 @@
+Main-Class: org.apache.jk.apr.TomcatStarter
+Class-Path: ../lib/tomcat.jar log4j.jar log4j-core.jar ../lib/common/log4j.jar ../lib/common/log4j-core.jar ../lib/common/classes ../lib/common/commons-logging.jar bootstrap.jar ../server/lib/commons-logging.jar ../server/lib/jmx.jar jmx.jar commons-logging-api.jar
diff --git a/base/tps/shared/conf/jk2.properties b/base/tps/shared/conf/jk2.properties
new file mode 100644
index 000000000..934d6ed54
--- /dev/null
+++ b/base/tps/shared/conf/jk2.properties
@@ -0,0 +1,31 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+## THIS FILE MAY BE OVERRIDEN AT RUNTIME. MAKE SURE TOMCAT IS STOPED
+## WHEN YOU EDIT THE FILE.
+
+## COMMENTS WILL BE _LOST_
+
+## DOCUMENTATION OF THE FORMAT IN JkMain javadoc.
+
+# Set the desired handler list
+# handler.list=apr,request,channelJni
+#
+# Override the default port for the socketChannel
+# channelSocket.port=8019
+# Default:
+# channelUnix.file=${jkHome}/work/jk2.socket
+# Just to check if the the config is working
+# shm.file=${jkHome}/work/jk2.shm
+
+# In order to enable jni use any channelJni directive
+# channelJni.disabled = 0
+# And one of the following directives:
+
+# apr.jniModeSo=/opt/apache2/modules/mod_jk2.so
+
+# If set to inprocess the mod_jk2 will Register natives itself
+# This will enable the starting of the Tomcat from mod_jk2
+# apr.jniModeSo=inprocess
diff --git a/base/tps/shared/conf/jkconf.ant.xml b/base/tps/shared/conf/jkconf.ant.xml
new file mode 100644
index 000000000..48396f1b7
--- /dev/null
+++ b/base/tps/shared/conf/jkconf.ant.xml
@@ -0,0 +1,55 @@
+<!-- BEGIN COPYRIGHT BLOCK
+ Copyright (C) 2006 Red Hat, Inc.
+ All rights reserved.
+ END COPYRIGHT BLOCK -->
+<project name="jkconf" default="main" basedir=".">
+
+ <target name="init-3x" if="33.detect">
+ <taskdef name="jkconf"
+ classname="org.apache.jk.config.WebXml2Jk" >
+ <classpath>
+ <!-- 3.3 support -->
+ <pathelement location="/ws/jtc/jk/build/classes" />
+ <pathelement location="${tomcat.home}/lib/container/tomcat-jk2.jar" />
+ <pathelement location="${tomcat.home}/lib/container/crimson.jar"/>
+ <pathelement location="${tomcat.home}/lib/common/commons-logging.jar"/>
+ </classpath>
+ </taskdef>
+ </target>
+
+ <target name="init-4x" if="4x.detect" >
+ <path id="main.classpath">
+ <!-- 3.3 support -->
+ <fileset dir="${tomcat.home}/lib" includes="*.jar" />
+ <fileset dir="${tomcat.home}/server/lib" includes="*.jar" />
+ <fileset dir="${tomcat.home}/common/lib" includes="*.jar" />
+ </path>
+
+ <taskdef name="jkconf" classpathref="main.classpath"
+ classname="org.apache.jk.config.WebXml2Jk" />
+ </target>
+
+ <target name="detect" >
+ <property file="build.properties"/>
+ <property file="${user.home}/build.properties"/>
+ <property file="${user.home}/.build.properties"/>
+
+ <!-- default locations, overrident by properties.
+ This file must be installed in conf/ -->
+ <property name="tomcat.home" location=".." />
+
+ <available property="33.detect" file="${tomcat.home}/lib/container" />
+ <available property="4x.detect" file="${tomcat.home}/server/lib" />
+ </target>
+
+ <target name="init" depends="detect,init-3x,init-4x" />
+
+ <!-- ==================== Detection and reports ==================== -->
+
+
+ <target name="main" depends="init">
+ <jkconf docBase="${tomcat.home}/webapps/examples"
+ context="/examples" />
+ </target>
+
+</project>
diff --git a/base/tps/shared/conf/jkconfig.manifest b/base/tps/shared/conf/jkconfig.manifest
new file mode 100644
index 000000000..3ba1f2e3e
--- /dev/null
+++ b/base/tps/shared/conf/jkconfig.manifest
@@ -0,0 +1,2 @@
+Main-Class: org.apache.jk.config.WebXml2Jk
+Class-Path: tomcat-jk2.jar commons-logging.jar crimson.jar xercesImpl.jar xmlApis.jar tomcat-util.jar log4j.jar log4j-core.jar
diff --git a/base/tps/shared/conf/logging.properties b/base/tps/shared/conf/logging.properties
new file mode 100644
index 000000000..796cfc071
--- /dev/null
+++ b/base/tps/shared/conf/logging.properties
@@ -0,0 +1,70 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006-2010 Red Hat, Inc.
+# All rights reserved.
+# Modifications: configuration parameters
+# --- END COPYRIGHT BLOCK ---
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+
+.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+1catalina.org.apache.juli.FileHandler.level = FINE
+1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+1catalina.org.apache.juli.FileHandler.prefix = catalina.
+
+2localhost.org.apache.juli.FileHandler.level = FINE
+2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+2localhost.org.apache.juli.FileHandler.prefix = localhost.
+
+3manager.org.apache.juli.FileHandler.level = FINE
+3manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+3manager.org.apache.juli.FileHandler.prefix = manager.
+
+4host-manager.org.apache.juli.FileHandler.level = FINE
+4host-manager.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+4host-manager.org.apache.juli.FileHandler.prefix = host-manager.
+
+java.util.logging.ConsoleHandler.level = FINE
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+
+
+############################################################
+# Facility specific properties.
+# Provides extra control for each logger.
+############################################################
+
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler
+
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.FileHandler
+
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO
+org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 4host-manager.org.apache.juli.FileHandler
+
+# For example, set the com.xyz.foo logger to only log SEVERE
+# messages:
+#org.apache.catalina.startup.ContextConfig.level = FINE
+#org.apache.catalina.startup.HostConfig.level = FINE
+#org.apache.catalina.session.ManagerBase.level = FINE
+#org.apache.catalina.core.AprLifecycleListener.level=FINE
diff --git a/base/tps/shared/conf/manager.ldif b/base/tps/shared/conf/manager.ldif
new file mode 100644
index 000000000..18700dd4b
--- /dev/null
+++ b/base/tps/shared/conf/manager.ldif
@@ -0,0 +1,46 @@
+# acis for cert manager
+
+dn: ou=csusers,cn=config
+objectClass: top
+objectClass: organizationalUnit
+ou: csusers
+
+dn: {rootSuffix}
+changetype: modify
+add: aci
+aci: (targetattr=*)(version 3.0; acl "cert manager access v2"; allow (all) userdn = "ldap:///{dbuser}";)
+
+dn: cn=ldbm database,cn=plugins,cn=config
+changetype: modify
+add: aci
+aci: (targetattr=*)(version 3.0; acl "Cert Manager access for VLV searches"; allow (read) userdn="ldap:///{dbuser}";)
+
+dn: cn=config
+changetype: modify
+add: aci
+aci: (targetattr != aci)(version 3.0; aci "cert manager read access"; allow (read, search, compare) userdn = "ldap:///{dbuser}";)
+
+dn: ou=csusers,cn=config
+changetype: modify
+add: aci
+aci: (targetattr != aci)(version 3.0; aci "cert manager manage replication users"; allow (all) userdn = "ldap:///{dbuser}";)
+
+dn: cn="{rootSuffix}",cn=mapping tree,cn=config
+changetype: modify
+add: aci
+aci: (targetattr=*)(version 3.0;acl "cert manager: Add Replication Agreements";allow (add) userdn = "ldap:///{dbuser}";)
+
+dn: cn="{rootSuffix}",cn=mapping tree,cn=config
+changetype: modify
+add: aci
+aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5Replica)(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement)(objectClass=nsMappingTree))")(version 3.0; acl "cert manager: Modify Replication Agreements"; allow (read, write, search) userdn = "ldap:///{dbuser}";)
+
+dn: cn="{rootSuffix}",cn=mapping tree,cn=config
+changetype: modify
+add: aci
+aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement))")(version 3.0;acl "cert manager: Remove Replication Agreements";allow (delete) userdn = "ldap:///{dbuser}";)
+
+dn: cn=tasks,cn=config
+changetype: modify
+add: aci
+aci: (targetattr=*)(version 3.0; acl "cert manager: Run tasks after replica re-initialization"; allow (add) userdn = "ldap:///{dbuser}";)
diff --git a/base/tps/shared/conf/phoneHome.xml b/base/tps/shared/conf/phoneHome.xml
new file mode 100644
index 000000000..314e1bb64
--- /dev/null
+++ b/base/tps/shared/conf/phoneHome.xml
@@ -0,0 +1,10 @@
+<ServiceInfo>
+<IssuerName>FedoraProject</IssuerName>
+<Services>
+<Operation>https://[PKI_HOSTNAME]:[PKI_SECURE_PORT]/tps/tps</Operation>
+<UI></UI>
+<EnrolledTokenBrowserURL>http://fedoraproject.org</EnrolledTokenBrowserURL>
+<EnrolledTokenURL></EnrolledTokenURL>
+<TokenType>userKey</TokenType>
+</Services>
+</ServiceInfo>
diff --git a/base/tps/shared/conf/registry.cfg b/base/tps/shared/conf/registry.cfg
new file mode 100644
index 000000000..dc26ae861
--- /dev/null
+++ b/base/tps/shared/conf/registry.cfg
@@ -0,0 +1,5 @@
+types=tpsTokenProfileResolver
+tpsTokenProfileResolver.ids=mappingTokenProfileResolverImpl
+tpsTokenProfileResolver.mappingTokenProfileResolverImpl.class=org.dogtagpki.server.tps.profile.MappingTokenProfileResolver
+tpsTokenProfileResolver.mappingTokenProfileResolverImpl.desc=Mapping-based Token profile resolver
+tpsTokenProfileResolver.mappingTokenProfileResolverImpl.name=Mapping-based Token profile resolver
diff --git a/base/tps/shared/conf/schema.ldif b/base/tps/shared/conf/schema.ldif
new file mode 100644
index 000000000..bde045630
--- /dev/null
+++ b/base/tps/shared/conf/schema.ldif
@@ -0,0 +1,58 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# This library 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;
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# Copyright (C) 2007 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+dn: cn=schema
+changetype: modify
+add: attributeTypes
+attributeTypes: ( dateOfCreate-oid NAME 'dateOfCreate' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( dateOfModify-oid NAME 'dateOfModify' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( modified-oid NAME 'modified' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenUserID-oid NAME 'tokenUserID' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenStatus-oid NAME 'tokenStatus' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenAppletID-oid NAME 'tokenAppletID' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( keyInfo-oid NAME 'keyInfo' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( numberOfResets-oid NAME 'numberOfResets' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 X-ORIGIN 'user defined' )
+attributeTypes: ( numberOfEnrollments-oid NAME 'numberOfEnrollments' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 X-ORIGIN 'user defined' )
+attributeTypes: ( numberOfRenewals-oid NAME 'numberOfRenewals' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 X-ORIGIN 'user defined' )
+attributeTypes: ( numberOfRecoveries-oid NAME 'numberOfRecoveries' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 X-ORIGIN 'user defined' )
+attributeTypes: ( allowPinReset-oid NAME 'allowPinReset' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( extensions-oid NAME 'extensions' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenOp-oid NAME 'tokenOp' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenID-oid NAME 'tokenID' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenMsg-oid NAME 'tokenMsg' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenResult-oid NAME 'tokenResult' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenIP-oid NAME 'tokenIP' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenPolicy-oid NAME 'tokenPolicy' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenIssuer-oid NAME 'tokenIssuer' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenSubject-oid NAME 'tokenSubject' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenSerial-oid NAME 'tokenSerial' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenOrigin-oid NAME 'tokenOrigin' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenType-oid NAME 'tokenType' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenKeyType-oid NAME 'tokenKeyType' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenReason-oid NAME 'tokenReason' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenNotBefore-oid NAME 'tokenNotBefore' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( tokenNotAfter-oid NAME 'tokenNotAfter' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+attributeTypes: ( profileID-oid NAME 'profileID' DESC 'CMS defined attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' )
+-
+add: objectClasses
+objectClasses: ( tokenRecord-oid NAME 'tokenRecord' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( dateOfCreate $ dateOfModify $ modified $ tokenReason $ tokenUserID $ tokenStatus $ tokenAppletID $ keyInfo $ tokenPolicy $ extensions $ numberOfResets $ numberOfEnrollments $ numberOfRenewals $ numberOfRecoveries $ userCertificate $ tokenType ) X-ORIGIN 'user defined' )
+objectClasses: ( tokenActivity-oid NAME 'tokenActivity' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( dateOfCreate $ dateOfModify $ tokenOp $ tokenIP $ tokenResult $ tokenID $ tokenUserID $ tokenMsg $ extensions $ tokenType ) X-ORIGIN 'user defined' )
+objectClasses: ( tokenCert-oid NAME 'tokenCert' DESC 'CMS defined class' SUP top STRUCTURAL MUST cn MAY ( dateOfCreate $ dateOfModify $ userCertificate $ tokenUserID $ tokenID $ tokenIssuer $ tokenOrigin $ tokenSubject $ tokenSerial $ tokenStatus $ tokenType $ tokenKeyType $ tokenNotBefore $ tokenNotAfter $ extensions ) X-ORIGIN 'user defined' )
+objectClasses: ( tpsProfileID-oid NAME 'tpsProfileID' DESC 'CMS defined class' SUP top AUXILIARY MAY ( profileID ) X-ORIGIN 'user-defined' )
diff --git a/base/tps/shared/conf/server-minimal.xml b/base/tps/shared/conf/server-minimal.xml
new file mode 100644
index 000000000..fc855c6e3
--- /dev/null
+++ b/base/tps/shared/conf/server-minimal.xml
@@ -0,0 +1,29 @@
+<!-- BEGIN COPYRIGHT BLOCK
+ Copyright (C) 2006 Red Hat, Inc.
+ All rights reserved.
+ END COPYRIGHT BLOCK -->
+<Server port="8005" shutdown="SHUTDOWN">
+
+ <GlobalNamingResources>
+ <!-- Used by Manager webapp -->
+ <Resource name="UserDatabase" auth="Container"
+ type="org.apache.catalina.UserDatabase"
+ description="User database that can be updated and saved"
+ factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
+ pathname="conf/tomcat-users.xml" />
+ </GlobalNamingResources>
+
+ <Service name="Catalina">
+ <Connector port="8080" />
+
+ <!-- This is here for compatibility only, not required -->
+ <Connector port="8009" protocol="AJP/1.3" />
+
+ <Engine name="Catalina" defaultHost="localhost">
+ <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
+ resourceName="UserDatabase" />
+ <Host name="localhost" appBase="webapps" />
+ </Engine>
+
+ </Service>
+</Server>
diff --git a/base/tps/shared/conf/server.xml b/base/tps/shared/conf/server.xml
new file mode 100644
index 000000000..23e4f5fde
--- /dev/null
+++ b/base/tps/shared/conf/server.xml
@@ -0,0 +1,258 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- BEGIN COPYRIGHT BLOCK
+ Copyright (C) 2006-2010 Red Hat, Inc.
+ All rights reserved.
+ Modifications: configuration parameters
+ END COPYRIGHT BLOCK -->
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- Note: A "Server" is not itself a "Container", so you may not
+ define subcomponents such as "Valves" at this level.
+ Documentation at /docs/config/server.html
+ -->
+
+<!-- DO NOT REMOVE - Begin PKI Status Definitions -->
+<!--
+Unsecure URL = http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/[PKI_SUBSYSTEM_TYPE]/ee/[PKI_SUBSYSTEM_TYPE]
+Secure Agent URL = https://[PKI_HOSTNAME]:[PKI_AGENT_SECURE_PORT]/[PKI_SUBSYSTEM_TYPE]/agent/[PKI_SUBSYSTEM_TYPE]
+Secure EE URL = https://[PKI_HOSTNAME]:[PKI_EE_SECURE_PORT]/[PKI_SUBSYSTEM_TYPE]/ee/[PKI_SUBSYSTEM_TYPE]
+Secure Admin URL = https://[PKI_HOSTNAME]:[PKI_ADMIN_SECURE_PORT]/[PKI_SUBSYSTEM_TYPE]/services
+PKI Console Command = pkiconsole https://[PKI_HOSTNAME]:[PKI_ADMIN_SECURE_PORT]/[PKI_SUBSYSTEM_TYPE]
+Tomcat Port = [TOMCAT_SERVER_PORT] (for shutdown)
+-->
+<!-- DO NOT REMOVE - End PKI Status Definitions -->
+
+<Server port="[TOMCAT_SERVER_PORT]" shutdown="SHUTDOWN">
+
+ <!--APR library loader. Documentation at /docs/apr.html -->
+ <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
+ <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
+ <Listener className="org.apache.catalina.core.JasperListener" />
+ <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
+ <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
+ <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
+
+ <!-- Global JNDI resources
+ Documentation at /docs/jndi-resources-howto.html
+ -->
+ <GlobalNamingResources>
+ <!-- Editable user database that can also be used by
+ UserDatabaseRealm to authenticate users
+ -->
+ <Resource name="UserDatabase" auth="Container"
+ type="org.apache.catalina.UserDatabase"
+ description="User database that can be updated and saved"
+ factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
+ pathname="conf/tomcat-users.xml" />
+ </GlobalNamingResources>
+
+ <!-- A "Service" is a collection of one or more "Connectors" that share
+ a single "Container" Note: A "Service" is not itself a "Container",
+ so you may not define subcomponents such as "Valves" at this level.
+ Documentation at /docs/config/service.html
+ -->
+ <Service name="Catalina">
+
+ <!--The connectors can use a shared executor, you can define one or more named thread pools-->
+ <!--
+ <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
+ maxThreads="150" minSpareThreads="4"/>
+ -->
+
+
+ <!-- A "Connector" represents an endpoint by which requests are received
+ and responses are returned. Documentation at :
+ Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
+ Java AJP Connector: /docs/config/ajp.html
+ APR (HTTP/AJP) Connector: /docs/apr.html
+ Define a non-SSL HTTP/1.1 Connector on port 8080
+ -->
+
+ [PKI_UNSECURE_PORT_SERVER_COMMENT]
+ <Connector name="[PKI_UNSECURE_PORT_CONNECTOR_NAME]" port="[PKI_UNSECURE_PORT]" protocol="HTTP/1.1" redirectPort="8443"
+ maxHttpHeaderSize="8192"
+ acceptCount="100" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
+ enableLookups="false" connectionTimeout="20000" disableUploadTimeout="true"
+ />
+
+ <!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
+ [PKI_SECURE_PORT_SERVER_COMMENT]
+ <!-- DO NOT REMOVE - Begin define PKI secure port
+ NOTE: The OCSP settings take effect globally, so it should only be set once.
+
+ In setup where SSL clientAuth="true", OCSP can be turned on by
+ setting enableOCSP to true like the following:
+ enableOCSP="true"
+ along with changes to related settings, especially:
+ ocspResponderURL=<see example in connector definition below>
+ ocspResponderCertNickname=<see example in connector definition below>
+ Here are the definition to all the OCSP-related settings:
+ enableOCSP - turns on/off the ocsp check
+ ocspResponderURL - sets the url where the ocsp requests are sent
+ ocspResponderCertNickname - sets the nickname of the cert that is
+ either CA's signing certificate or the OCSP server's signing
+ certificate.
+ The CA's signing certificate should already be in the db, in
+ case of the same security domain.
+ In case of an ocsp signing certificate, one must import the cert
+ into the subsystem's nss db and set trust. e.g.:
+ certutil -d . -A -n "ocspSigningCert cert-pki-ca" -t "C,," -a -i ocspCert.b64
+ ocspCacheSize - sets max cache entries
+ ocspMinCacheEntryDuration - sets minimum seconds to next fetch attempt
+ ocspMaxCacheEntryDuration - sets maximum seconds to next fetch attempt
+ ocspTimeout -sets OCSP timeout in seconds
+ -->
+ <Connector name="[PKI_SECURE_PORT_CONNECTOR_NAME]" port="[PKI_SECURE_PORT]" protocol="HTTP/1.1" SSLEnabled="true" sslProtocol="SSL" scheme="https" secure="true"
+ maxHttpHeaderSize="8192"
+ acceptCount="100" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
+ enableLookups="false" disableUploadTimeout="true"
+ SSLImplementation="org.apache.tomcat.util.net.jss.JSSImplementation"
+ enableOCSP="false"
+ ocspResponderURL="http://[PKI_HOSTNAME]:9080/ca/ocsp"
+ ocspResponderCertNickname="ocspSigningCert cert-pki-ca"
+ ocspCacheSize="1000"
+ ocspMinCacheEntryDuration="60"
+ ocspMaxCacheEntryDuration="120"
+ ocspTimeout="10"
+ strictCiphers="false"
+ clientAuth="[PKI_AGENT_CLIENTAUTH]"
+ sslOptions="[TOMCAT_SSL_OPTIONS]"
+ ssl2Ciphers="[TOMCAT_SSL2_CIPHERS]"
+ ssl3Ciphers="[TOMCAT_SSL3_CIPHERS]"
+ tlsCiphers="[TOMCAT_TLS_CIPHERS]"
+ serverCertNickFile="[PKI_INSTANCE_PATH]/conf/serverCertNick.conf"
+ passwordFile="[PKI_INSTANCE_PATH]/conf/password.conf"
+ passwordClass="org.apache.tomcat.util.net.jss.PlainPasswordFile"
+ certdbDir="[PKI_INSTANCE_PATH]/alias"
+ />
+ <!-- DO NOT REMOVE - End define PKI secure port -->
+
+ [PKI_OPEN_SEPARATE_PORTS_SERVER_COMMENT][PKI_ADMIN_SECURE_PORT_SERVER_COMMENT]
+ <Connector name="[PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME]" port="[PKI_ADMIN_SECURE_PORT]" SSLEnabled="true" sslProtocol="SSL" scheme="https" secure="true"
+ maxHttpHeaderSize="8192"
+ acceptCount="100" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
+ enableLookups="false" disableUploadTimeout="true"
+ SSLImplementation="org.apache.tomcat.util.net.jss.JSSImplementation"
+ strictCiphers="false"
+ clientAuth="false"
+ sslOptions="[TOMCAT_SSL_OPTIONS]"
+ ssl2Ciphers="[TOMCAT_SSL2_CIPHERS]"
+ ssl3Ciphers="[TOMCAT_SSL3_CIPHERS]"
+ tlsCiphers="[TOMCAT_TLS_CIPHERS]"
+ serverCertNickFile="[PKI_INSTANCE_PATH]/conf/serverCertNick.conf"
+ passwordFile="[PKI_INSTANCE_PATH]/conf/password.conf"
+ passwordClass="org.apache.tomcat.util.net.jss.PlainPasswordFile"
+ certdbDir="[PKI_INSTANCE_PATH]/alias"/>
+ [PKI_CLOSE_SEPARATE_PORTS_SERVER_COMMENT]
+
+ [PKI_OPEN_SEPARATE_PORTS_SERVER_COMMENT][PKI_EE_SECURE_PORT_SERVER_COMMENT]
+ <Connector name="[PKI_EE_SECURE_PORT_CONNECTOR_NAME]" port="[PKI_EE_SECURE_PORT]" SSLEnabled="true" sslProtocol="SSL" scheme="https" secure="true"
+ maxHttpHeaderSize="8192"
+ acceptCount="100" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
+ enableLookups="false" disableUploadTimeout="true"
+ SSLImplementation="org.apache.tomcat.util.net.jss.JSSImplementation"
+ strictCiphers="false"
+ clientAuth="false"
+ sslOptions="[TOMCAT_SSL_OPTIONS]"
+ ssl2Ciphers="[TOMCAT_SSL2_CIPHERS]"
+ ssl3Ciphers="[TOMCAT_SSL3_CIPHERS]"
+ tlsCiphers="[TOMCAT_TLS_CIPHERS]"
+ serverCertNickFile="[PKI_INSTANCE_PATH]/conf/serverCertNick.conf"
+ passwordFile="[PKI_INSTANCE_PATH]/conf/password.conf"
+ passwordClass="org.apache.tomcat.util.net.jss.PlainPasswordFile"
+ certdbDir="[PKI_INSTANCE_PATH]/alias"/>
+ [PKI_CLOSE_SEPARATE_PORTS_SERVER_COMMENT]
+
+ <!-- A "Connector" using the shared thread pool-->
+ <!--
+ <Connector executor="tomcatThreadPool"
+ port="8080" protocol="HTTP/1.1"
+ connectionTimeout="20000"
+ redirectPort="8443" />
+ -->
+ <!-- Define a SSL HTTP/1.1 Connector on port 8443
+ This connector uses the JSSE configuration, when using APR, the
+ connector should be using the OpenSSL style configuration
+ described in the APR documentation -->
+ <!--
+ <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
+ maxThreads="150" scheme="https" secure="true"
+ clientAuth="false" sslProtocol="TLS" />
+ -->
+
+ <!-- Define an AJP 1.3 Connector on port [PKI_AJP_PORT] -->
+[PKI_OPEN_AJP_PORT_COMMENT]
+ <Connector port="[PKI_AJP_PORT]" protocol="AJP/1.3" redirectPort="[PKI_AJP_REDIRECT_PORT]" address="127.0.0.1" />
+[PKI_CLOSE_AJP_PORT_COMMENT]
+
+
+ <!-- An Engine represents the entry point (within Catalina) that processes
+ every request. The Engine implementation for Tomcat stand alone
+ analyzes the HTTP headers included with the request, and passes them
+ on to the appropriate Host (virtual host).
+ Documentation at /docs/config/engine.html -->
+
+ <!-- You should set jvmRoute to support load-balancing via AJP ie :
+ <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
+ -->
+ <Engine name="Catalina" defaultHost="localhost">
+
+ <!--For clustering, please take a look at documentation at:
+ /docs/cluster-howto.html (simple how to)
+ /docs/config/cluster.html (reference documentation) -->
+ <!--
+ <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
+ -->
+
+ <!-- The request dumper valve dumps useful debugging information about
+ the request and response data received and sent by Tomcat.
+ Documentation at: /docs/config/valve.html -->
+ <!--
+ <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
+ -->
+
+ <!-- This Realm uses the UserDatabase configured in the global JNDI
+ resources under the key "UserDatabase". Any edits
+ that are performed against this UserDatabase are immediately
+ available for use by the Realm. -->
+ <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
+ resourceName="UserDatabase"/>
+
+ <!-- Define the default virtual host
+ Note: XML Schema validation will not work with Xerces 2.2.
+ -->
+ <Host name="localhost" appBase="webapps"
+ unpackWARs="true" autoDeploy="false"
+ xmlValidation="false" xmlNamespaceAware="false">
+
+ <!-- SingleSignOn valve, share authentication between web applications
+ Documentation at: /docs/config/valve.html -->
+ <!--
+ <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
+ -->
+
+ <!-- Access log processes all example.
+ Documentation at: /docs/config/valve.html -->
+ [PKI_OPEN_TOMCAT_ACCESS_LOG_COMMENT]
+ <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
+ prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
+ [PKI_CLOSE_TOMCAT_ACCESS_LOG_COMMENT]
+
+ </Host>
+ </Engine>
+ </Service>
+</Server>
diff --git a/base/tps/shared/conf/shm.manifest b/base/tps/shared/conf/shm.manifest
new file mode 100644
index 000000000..0505c085b
--- /dev/null
+++ b/base/tps/shared/conf/shm.manifest
@@ -0,0 +1,2 @@
+Main-Class: org.apache.jk.common.Shm
+Class-Path: tomcat-jk2.jar commons-logging.jar tomcat-util.jar log4j.jar log4j-core.jar
diff --git a/base/tps/shared/conf/tomcat-jk2.manifest b/base/tps/shared/conf/tomcat-jk2.manifest
new file mode 100644
index 000000000..acfef4a90
--- /dev/null
+++ b/base/tps/shared/conf/tomcat-jk2.manifest
@@ -0,0 +1,7 @@
+Manifest-version: 1.0
+Extension-Name: org.apache.jk
+Specification-Vendor: Apache Software Foundation
+Specification-Version: 2.0
+Implementation-Vendor-Id: org.apache
+Implementation-Vendor: Apache Software Foundation
+Implementation-Version: 2.1
diff --git a/base/tps/shared/conf/tomcat-users.xml b/base/tps/shared/conf/tomcat-users.xml
new file mode 100644
index 000000000..daa9260cc
--- /dev/null
+++ b/base/tps/shared/conf/tomcat-users.xml
@@ -0,0 +1,45 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!-- BEGIN COPYRIGHT BLOCK
+ Copyright (C) 2006-2010 Red Hat, Inc.
+ All rights reserved.
+ Modifications: configuration parameters
+ END COPYRIGHT BLOCK -->
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+ <role rolename="tomcat"/>
+ <role rolename="role1"/>
+ <user username="tomcat" password="tomcat" roles="tomcat"/>
+ <user username="both" password="tomcat" roles="tomcat,role1"/>
+ <user username="role1" password="tomcat" roles="role1"/>
+-->
+
+<!-- The host manager webapp is restricted to users with role "admin" -->
+<!--<user name="tomcat" password="password" roles="admin" />-->
+<!-- The manager webapp is restricted to users with role "manager" -->
+<!--<user name="tomcat" password="password" roles="manager" />-->
+<tomcat-users>
+ <role rolename="pkiuser"/>
+ <role rolename="tomcat"/>
+ <role rolename="manager"/>
+ <role rolename="admin"/>
+
+ <user username="pkiuser" password="pkiuser" roles="pkiuser"/>
+ <user username="tomcat" password="tomcat" roles="tomcat"/>
+ <user username="admin" password="netscape" roles="admin,manager"/>
+</tomcat-users>
diff --git a/base/tps/shared/conf/tomcat6.conf b/base/tps/shared/conf/tomcat6.conf
new file mode 100644
index 000000000..2d7def5ec
--- /dev/null
+++ b/base/tps/shared/conf/tomcat6.conf
@@ -0,0 +1,58 @@
+# Service-specific configuration file for tomcat6. This will be sourced by
+# the SysV init script after the global configuration file
+# /etc/tomcat6/tomcat6.conf, thus allowing values to be overridden in
+# a per-service manner.
+#
+# NEVER change the init script itself. To change values for all services make
+# your changes in /etc/tomcat6/tomcat6.conf
+#
+# To change values for a specific service make your edits here.
+# To create a new service create a link from /etc/init.d/<your new service> to
+# /etc/init.d/tomcat6 (do not copy the init script) and make a copy of the
+# /etc/sysconfig/tomcat6 file to /etc/sysconfig/<your new service> and change
+# the property values so the two services won't conflict. Register the new
+# service in the system as usual (see chkconfig and similars).
+#
+
+# Where your java installation lives
+#JAVA_HOME="/usr/lib/jvm/java"
+
+# Where your tomcat installation lives
+CATALINA_BASE="[PKI_INSTANCE_PATH]"
+#CATALINA_HOME="/usr/share/tomcat6"
+#JASPER_HOME="/usr/share/tomcat6"
+#CATALINA_TMPDIR="/var/cache/tomcat6/temp"
+
+# You can pass some parameters to java here if you wish to
+#JAVA_OPTS="-Xminf0.1 -Xmaxf0.3"
+
+# Use JAVA_OPTS to set java.library.path for libtcnative.so
+#JAVA_OPTS="-Djava.library.path=/usr/lib64"
+
+# What user should run tomcat
+TOMCAT_USER="[PKI_USER]"
+
+# You can change your tomcat locale here
+#LANG="en_US"
+
+# Run tomcat under the Java Security Manager
+#SECURITY_MANAGER="false"
+
+# Time to wait in seconds, before killing process
+#SHUTDOWN_WAIT="30"
+
+# Whether to annoy the user with "attempting to shut down" messages or not
+#SHUTDOWN_VERBOSE="false"
+
+# Set the TOMCAT_PID location
+CATALINA_PID="[TOMCAT_PIDFILE]"
+
+# Set the tomcat log file
+TOMCAT_LOG="[TOMCAT_LOG_DIR]/tomcat-initd.log"
+
+# Connector port is 8080 for this tomcat6 instance
+#CONNECTOR_PORT="8080"
+
+# If you wish to further customize your tomcat environment,
+# put your own definitions here
+# (i.e. LD_LIBRARY_PATH for some jdbc drivers)
diff --git a/base/tps/shared/conf/uriworkermap.properties b/base/tps/shared/conf/uriworkermap.properties
new file mode 100644
index 000000000..c89dd82a6
--- /dev/null
+++ b/base/tps/shared/conf/uriworkermap.properties
@@ -0,0 +1,18 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+# uriworkermap.properties - IIS
+#
+# This file provides sample mappings for example ajp13w
+# worker defined in workermap.properties.minimal
+# The general sytax for this file is:
+# [URL]=[Worker name]
+
+/servlet-examples/*=ajp13w
+
+# Optionally filter out all .jpeg files inside that context
+# For no mapping the url has to start with exclamation (!)
+
+!/servlet-examples/*.jpeg=ajp13w
diff --git a/base/tps/shared/conf/vlv.ldif b/base/tps/shared/conf/vlv.ldif
new file mode 100644
index 000000000..db7988e36
--- /dev/null
+++ b/base/tps/shared/conf/vlv.ldif
@@ -0,0 +1,51 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# This library 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;
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# Copyright (C) 2007 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+dn: cn=tus-listTokens-vlv,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+cn: tus-listtokens-vlv
+objectClass: top
+objectClass: vlvsearch
+vlvBase: ou=Tokens,{rootSuffix}
+vlvFilter: (&(cn=*)(tokenUserID=*))
+vlvScope: 2
+
+dn: cn=tus-listActivities-vlv,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+cn: tus-listActivities-vlv
+objectClass: top
+objectClass: vlvsearch
+vlvBase: ou=Activities,{rootSuffix}
+vlvFilter: (&(tokenID=*)(tokenUserID=*))
+vlvScope: 2
+
+dn: cn=listTokensIndex,cn=tus-listTokens-vlv,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+cn: listTokensIndex
+objectClass: top
+objectClass: vlvindex
+vlvSort: -dateOfModify
+vlvEnabled: 1
+vlvUses: 0
+
+dn: cn=listActivitiesIndex,cn=tus-listActivities-vlv,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+cn: listActivitiesIndex
+objectClass: top
+objectClass: vlvindex
+vlvSort: -dateOfCreate
+vlvEnabled: 1
+vlvUses: 0
diff --git a/base/tps/shared/conf/vlvtasks.ldif b/base/tps/shared/conf/vlvtasks.ldif
new file mode 100644
index 000000000..b1b93aabf
--- /dev/null
+++ b/base/tps/shared/conf/vlvtasks.ldif
@@ -0,0 +1,28 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# This library 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;
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301 USA
+#
+# Copyright (C) 2007 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+dn: cn=index1160528734, cn=index, cn=tasks, cn=config
+objectclass: top
+objectclass: extensibleObject
+cn: index1160528734
+ttl: 4
+nsinstance: userRoot
+nsindexVLVAttribute: listTokensIndex
+nsindexVLVAttribute: listActivitiesIndex
diff --git a/base/tps/shared/conf/web.xml b/base/tps/shared/conf/web.xml
new file mode 100644
index 000000000..8330ecca8
--- /dev/null
+++ b/base/tps/shared/conf/web.xml
@@ -0,0 +1,993 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- BEGIN COPYRIGHT BLOCK
+ Copyright (C) 2006 Red Hat, Inc.
+ All rights reserved.
+ END COPYRIGHT BLOCK -->
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+ version="2.4">
+
+ <!-- ======================== Introduction ============================== -->
+ <!-- This document defines default values for *all* web applications -->
+ <!-- loaded into this instance of Tomcat. As each application is -->
+ <!-- deployed, this file is processed, followed by the -->
+ <!-- "/WEB-INF/web.xml" deployment descriptor from your own -->
+ <!-- applications. -->
+ <!-- -->
+ <!-- WARNING: Do not configure application-specific resources here! -->
+ <!-- They should go in the "/WEB-INF/web.xml" file in your application. -->
+
+
+ <!-- ================== Built In Servlet Definitions ==================== -->
+
+
+ <!-- The default servlet for all web applications, that serves static -->
+ <!-- resources. It processes all requests that are not mapped to other -->
+ <!-- servlets with servlet mappings (defined either here or in your own -->
+ <!-- web.xml file. This servlet supports the following initialization -->
+ <!-- parameters (default values are in square brackets): -->
+ <!-- -->
+ <!-- debug Debugging detail level for messages logged -->
+ <!-- by this servlet. [0] -->
+ <!-- -->
+ <!-- fileEncoding Encoding to be used to read static resources -->
+ <!-- [platform default] -->
+ <!-- -->
+ <!-- input Input buffer size (in bytes) when reading -->
+ <!-- resources to be served. [2048] -->
+ <!-- -->
+ <!-- listings Should directory listings be produced if there -->
+ <!-- is no welcome file in this directory? [true] -->
+ <!-- -->
+ <!-- output Output buffer size (in bytes) when writing -->
+ <!-- resources to be served. [2048] -->
+ <!-- -->
+ <!-- readonly Is this context "read only", so HTTP -->
+ <!-- commands like PUT and DELETE are -->
+ <!-- rejected? [true] -->
+ <!-- -->
+ <!-- readmeFile File name to display with the directory -->
+ <!-- contents. [null] -->
+ <!-- -->
+ <!-- For directory listing customization. Checks localXsltFile, then -->
+ <!-- globalXsltFile, then defaults to original behavior. -->
+ <!-- -->
+ <!-- localXsltFile Make directory listings an XML doc and -->
+ <!-- pass the result to this style sheet residing -->
+ <!-- in that directory. This overrides -->
+ <!-- globalXsltFile[null] -->
+ <!-- -->
+ <!-- globalXsltFile Site wide configuration version of -->
+ <!-- localXsltFile This argument is expected -->
+ <!-- to be a physical file. [null] -->
+ <!-- -->
+ <!-- -->
+
+ <servlet>
+ <servlet-name>default</servlet-name>
+ <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
+ <init-param>
+ <param-name>debug</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <init-param>
+ <param-name>listings</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+
+ <!-- The "invoker" servlet, which executes anonymous servlet classes -->
+ <!-- that have not been defined in a web.xml file. Traditionally, this -->
+ <!-- servlet is mapped to the URL pattern "/servlet/*", but you can map -->
+ <!-- it to other patterns as well. The extra path info portion of such a -->
+ <!-- request must be the fully qualified class name of a Java class that -->
+ <!-- implements Servlet (or extends HttpServlet), or the servlet name -->
+ <!-- of an existing servlet definition. This servlet supports the -->
+ <!-- following initialization parameters (default values are in square -->
+ <!-- brackets): -->
+ <!-- -->
+ <!-- debug Debugging detail level for messages logged -->
+ <!-- by this servlet. [0] -->
+
+<!--
+ <servlet>
+ <servlet-name>invoker</servlet-name>
+ <servlet-class>
+ org.apache.catalina.servlets.InvokerServlet
+ </servlet-class>
+ <init-param>
+ <param-name>debug</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+-->
+
+
+ <!-- The JSP page compiler and execution servlet, which is the mechanism -->
+ <!-- used by Tomcat to support JSP pages. Traditionally, this servlet -->
+ <!-- is mapped to the URL pattern "*.jsp". This servlet supports the -->
+ <!-- following initialization parameters (default values are in square -->
+ <!-- brackets): -->
+ <!-- -->
+ <!-- checkInterval If development is false and checkInterval is -->
+ <!-- greater than zero, background compilations are -->
+ <!-- enabled. checkInterval is the time in seconds -->
+ <!-- between checks to see if a JSP page needs to -->
+ <!-- be recompiled. [0] -->
+ <!-- -->
+ <!-- modificationTestInterval -->
+ <!-- Causes a JSP (and its dependent files) to not -->
+ <!-- be checked for modification during the -->
+ <!-- specified time interval (in seconds) from the -->
+ <!-- last time the JSP was checked for -->
+ <!-- modification. A value of 0 will cause the JSP -->
+ <!-- to be checked on every access. -->
+ <!-- Used in development mode only. [4] -->
+ <!-- -->
+ <!-- compiler Which compiler Ant should use to compile JSP -->
+ <!-- pages. See the Ant documentation for more -->
+ <!-- information. [javac] -->
+ <!-- -->
+ <!-- classdebuginfo Should the class file be compiled with -->
+ <!-- debugging information? [true] -->
+ <!-- -->
+ <!-- classpath What class path should I use while compiling -->
+ <!-- generated servlets? [Created dynamically -->
+ <!-- based on the current web application] -->
+ <!-- -->
+ <!-- development Is Jasper used in development mode? If true, -->
+ <!-- the frequency at which JSPs are checked for -->
+ <!-- modification may be specified via the -->
+ <!-- modificationTestInterval parameter. [true] -->
+ <!-- -->
+ <!-- enablePooling Determines whether tag handler pooling is -->
+ <!-- enabled [true] -->
+ <!-- -->
+ <!-- fork Tell Ant to fork compiles of JSP pages so that -->
+ <!-- a separate JVM is used for JSP page compiles -->
+ <!-- from the one Tomcat is running in. [true] -->
+ <!-- -->
+ <!-- ieClassId The class-id value to be sent to Internet -->
+ <!-- Explorer when using <jsp:plugin> tags. -->
+ <!-- [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93] -->
+ <!-- -->
+ <!-- javaEncoding Java file encoding to use for generating java -->
+ <!-- source files. [UTF8] -->
+ <!-- -->
+ <!-- keepgenerated Should we keep the generated Java source code -->
+ <!-- for each page instead of deleting it? [true] -->
+ <!-- -->
+ <!-- mappedfile Should we generate static content with one -->
+ <!-- print statement per input line, to ease -->
+ <!-- debugging? [true] -->
+ <!-- -->
+ <!-- trimSpaces Should white spaces in template text between -->
+ <!-- actions or directives be trimmed? [false] -->
+ <!-- -->
+ <!-- suppressSmap Should the generation of SMAP info for JSR45 -->
+ <!-- debugging be suppressed? [false] -->
+ <!-- -->
+ <!-- dumpSmap Should the SMAP info for JSR45 debugging be -->
+ <!-- dumped to a file? [false] -->
+ <!-- False if suppressSmap is true -->
+ <!-- -->
+ <!-- genStrAsCharArray Should text strings be generated as char -->
+ <!-- arrays, to improve performance in some cases? -->
+ <!-- [false] -->
+ <!-- -->
+ <!-- errorOnUseBeanInvalidClassAttribute -->
+ <!-- Should Jasper issue an error when the value of -->
+ <!-- the class attribute in an useBean action is -->
+ <!-- not a valid bean class? [true] -->
+ <!-- -->
+ <!-- scratchdir What scratch directory should we use when -->
+ <!-- compiling JSP pages? [default work directory -->
+ <!-- for the current web application] -->
+ <!-- -->
+ <!-- xpoweredBy Determines whether X-Powered-By response -->
+ <!-- header is added by generated servlet [false] -->
+ <!-- -->
+ <!-- If you wish to use Jikes to compile JSP pages: -->
+ <!-- Please see the "Using Jikes" section of the Jasper-HowTo -->
+ <!-- page in the Tomcat documentation. -->
+
+ <servlet>
+ <servlet-name>jsp</servlet-name>
+ <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+ <init-param>
+ <param-name>fork</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>xpoweredBy</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <load-on-startup>3</load-on-startup>
+ </servlet>
+
+
+ <!-- Server Side Includes processing servlet, which processes SSI -->
+ <!-- directives in HTML pages consistent with similar support in web -->
+ <!-- servers like Apache. Traditionally, this servlet is mapped to the -->
+ <!-- URL pattern "*.shtml". This servlet supports the following -->
+ <!-- initialization parameters (default values are in square brackets): -->
+ <!-- -->
+ <!-- buffered Should output from this servlet be buffered? -->
+ <!-- (0=false, 1=true) [0] -->
+ <!-- -->
+ <!-- debug Debugging detail level for messages logged -->
+ <!-- by this servlet. [0] -->
+ <!-- -->
+ <!-- expires The number of seconds before a page with SSI -->
+ <!-- directives will expire. [No default] -->
+ <!-- -->
+ <!-- isVirtualWebappRelative -->
+ <!-- Should "virtual" paths be interpreted as -->
+ <!-- relative to the context root, instead of -->
+ <!-- the server root? (0=false, 1=true) [0] -->
+ <!-- -->
+ <!-- -->
+ <!-- IMPORTANT: To use the SSI servlet, you also need to rename the -->
+ <!-- $CATALINA_HOME/server/lib/servlets-ssi.renametojar file -->
+ <!-- to $CATALINA_HOME/server/lib/servlets-ssi.jar -->
+
+<!--
+ <servlet>
+ <servlet-name>ssi</servlet-name>
+ <servlet-class>
+ org.apache.catalina.ssi.SSIServlet
+ </servlet-class>
+ <init-param>
+ <param-name>buffered</param-name>
+ <param-value>1</param-value>
+ </init-param>
+ <init-param>
+ <param-name>debug</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <init-param>
+ <param-name>expires</param-name>
+ <param-value>666</param-value>
+ </init-param>
+ <init-param>
+ <param-name>isVirtualWebappRelative</param-name>
+ <param-value>0</param-value>
+ </init-param>
+ <load-on-startup>4</load-on-startup>
+ </servlet>
+-->
+
+
+ <!-- Common Gateway Includes (CGI) processing servlet, which supports -->
+ <!-- execution of external applications that conform to the CGI spec -->
+ <!-- requirements. Typically, this servlet is mapped to the URL pattern -->
+ <!-- "/cgi-bin/*", which means that any CGI applications that are -->
+ <!-- executed must be present within the web application. This servlet -->
+ <!-- supports the following initialization parameters (default values -->
+ <!-- are in square brackets): -->
+ <!-- -->
+ <!-- cgiPathPrefix The CGI search path will start at -->
+ <!-- webAppRootDir + File.separator + this prefix. -->
+ <!-- [WEB-INF/cgi] -->
+ <!-- -->
+ <!-- debug Debugging detail level for messages logged -->
+ <!-- by this servlet. [0] -->
+ <!-- -->
+ <!-- executable Name of the exectuable used to run the -->
+ <!-- script. [perl] -->
+ <!-- -->
+ <!-- parameterEncoding Name of parameter encoding to be used with -->
+ <!-- CGI servlet. -->
+ <!-- [System.getProperty("file.encoding","UTF-8")] -->
+ <!-- -->
+ <!-- passShellEnvironment Should the shell environment variables (if -->
+ <!-- any) be passed to the CGI script? [false] -->
+ <!-- -->
+ <!-- IMPORTANT: To use the CGI servlet, you also need to rename the -->
+ <!-- $CATALINA_HOME/server/lib/servlets-cgi.renametojar file -->
+ <!-- to $CATALINA_HOME/server/lib/servlets-cgi.jar -->
+
+<!--
+ <servlet>
+ <servlet-name>cgi</servlet-name>
+ <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
+ <init-param>
+ <param-name>debug</param-name>
+ <param-value>6</param-value>
+ </init-param>
+ <init-param>
+ <param-name>cgiPathPrefix</param-name>
+ <param-value>WEB-INF/cgi</param-value>
+ </init-param>
+ <load-on-startup>5</load-on-startup>
+ </servlet>
+-->
+
+
+ <!-- ================ Built In Servlet Mappings ========================= -->
+
+
+ <!-- The servlet mappings for the built in servlets defined above. Note -->
+ <!-- that, by default, the CGI and SSI servlets are *not* mapped. You -->
+ <!-- must uncomment these mappings (or add them to your application's own -->
+ <!-- web.xml deployment descriptor) to enable these services -->
+
+ <!-- The mapping for the default servlet -->
+ <servlet-mapping>
+ <servlet-name>default</servlet-name>
+ <url-pattern>/</url-pattern>
+ </servlet-mapping>
+
+ <!-- The mapping for the invoker servlet -->
+<!--
+ <servlet-mapping>
+ <servlet-name>invoker</servlet-name>
+ <url-pattern>/servlet/*</url-pattern>
+ </servlet-mapping>
+-->
+
+ <!-- The mapping for the JSP servlet -->
+ <servlet-mapping>
+ <servlet-name>jsp</servlet-name>
+ <url-pattern>*.jsp</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>jsp</servlet-name>
+ <url-pattern>*.jspx</url-pattern>
+ </servlet-mapping>
+
+ <!-- The mapping for the SSI servlet -->
+<!--
+ <servlet-mapping>
+ <servlet-name>ssi</servlet-name>
+ <url-pattern>*.shtml</url-pattern>
+ </servlet-mapping>
+-->
+
+ <!-- The mapping for the CGI Gateway servlet -->
+
+<!--
+ <servlet-mapping>
+ <servlet-name>cgi</servlet-name>
+ <url-pattern>/cgi-bin/*</url-pattern>
+ </servlet-mapping>
+-->
+
+
+ <!-- ==================== Default Session Configuration ================= -->
+ <!-- You can set the default session timeout (in minutes) for all newly -->
+ <!-- created sessions by modifying the value below. -->
+
+ <session-config>
+ <session-timeout>30</session-timeout>
+ </session-config>
+
+
+ <!-- ===================== Default MIME Type Mappings =================== -->
+ <!-- When serving static resources, Tomcat will automatically generate -->
+ <!-- a "Content-Type" header based on the resource's filename extension, -->
+ <!-- based on these mappings. Additional mappings can be added here (to -->
+ <!-- apply to all web applications), or in your own application's web.xml -->
+ <!-- deployment descriptor. -->
+
+ <mime-mapping>
+ <extension>abs</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ai</extension>
+ <mime-type>application/postscript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aif</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aifc</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aiff</extension>
+ <mime-type>audio/x-aiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>aim</extension>
+ <mime-type>application/x-aim</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>art</extension>
+ <mime-type>image/x-jg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>asf</extension>
+ <mime-type>video/x-ms-asf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>asx</extension>
+ <mime-type>video/x-ms-asf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>au</extension>
+ <mime-type>audio/basic</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>avi</extension>
+ <mime-type>video/x-msvideo</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>avx</extension>
+ <mime-type>video/x-rad-screenplay</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>bcpio</extension>
+ <mime-type>application/x-bcpio</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>bin</extension>
+ <mime-type>application/octet-stream</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>bmp</extension>
+ <mime-type>image/bmp</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>body</extension>
+ <mime-type>text/html</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>cdf</extension>
+ <mime-type>application/x-cdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>cer</extension>
+ <mime-type>application/x-x509-ca-cert</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>class</extension>
+ <mime-type>application/java</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>cpio</extension>
+ <mime-type>application/x-cpio</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>csh</extension>
+ <mime-type>application/x-csh</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>css</extension>
+ <mime-type>text/css</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>dib</extension>
+ <mime-type>image/bmp</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>doc</extension>
+ <mime-type>application/msword</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>dtd</extension>
+ <mime-type>application/xml-dtd</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>dv</extension>
+ <mime-type>video/x-dv</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>dvi</extension>
+ <mime-type>application/x-dvi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>eps</extension>
+ <mime-type>application/postscript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>etx</extension>
+ <mime-type>text/x-setext</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>exe</extension>
+ <mime-type>application/octet-stream</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>gif</extension>
+ <mime-type>image/gif</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>gtar</extension>
+ <mime-type>application/x-gtar</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>gz</extension>
+ <mime-type>application/x-gzip</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>hdf</extension>
+ <mime-type>application/x-hdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>hqx</extension>
+ <mime-type>application/mac-binhex40</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>htc</extension>
+ <mime-type>text/x-component</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>htm</extension>
+ <mime-type>text/html</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>html</extension>
+ <mime-type>text/html</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>hqx</extension>
+ <mime-type>application/mac-binhex40</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ief</extension>
+ <mime-type>image/ief</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jad</extension>
+ <mime-type>text/vnd.sun.j2me.app-descriptor</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jar</extension>
+ <mime-type>application/java-archive</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>java</extension>
+ <mime-type>text/plain</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jnlp</extension>
+ <mime-type>application/x-java-jnlp-file</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jpe</extension>
+ <mime-type>image/jpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jpeg</extension>
+ <mime-type>image/jpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jpg</extension>
+ <mime-type>image/jpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>js</extension>
+ <mime-type>text/javascript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jsf</extension>
+ <mime-type>text/plain</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>jspf</extension>
+ <mime-type>text/plain</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>kar</extension>
+ <mime-type>audio/x-midi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>latex</extension>
+ <mime-type>application/x-latex</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>m3u</extension>
+ <mime-type>audio/x-mpegurl</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mac</extension>
+ <mime-type>image/x-macpaint</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>man</extension>
+ <mime-type>application/x-troff-man</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mathml</extension>
+ <mime-type>application/mathml+xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>me</extension>
+ <mime-type>application/x-troff-me</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mid</extension>
+ <mime-type>audio/x-midi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>midi</extension>
+ <mime-type>audio/x-midi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mif</extension>
+ <mime-type>application/x-mif</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mov</extension>
+ <mime-type>video/quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>movie</extension>
+ <mime-type>video/x-sgi-movie</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mp1</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mp2</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mp3</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpa</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpe</extension>
+ <mime-type>video/mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpeg</extension>
+ <mime-type>video/mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpega</extension>
+ <mime-type>audio/x-mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpg</extension>
+ <mime-type>video/mpeg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>mpv2</extension>
+ <mime-type>video/mpeg2</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ms</extension>
+ <mime-type>application/x-wais-source</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>nc</extension>
+ <mime-type>application/x-netcdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>oda</extension>
+ <mime-type>application/oda</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ogg</extension>
+ <mime-type>application/ogg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pbm</extension>
+ <mime-type>image/x-portable-bitmap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pct</extension>
+ <mime-type>image/pict</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pdf</extension>
+ <mime-type>application/pdf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pgm</extension>
+ <mime-type>image/x-portable-graymap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pic</extension>
+ <mime-type>image/pict</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pict</extension>
+ <mime-type>image/pict</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pls</extension>
+ <mime-type>audio/x-scpls</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>png</extension>
+ <mime-type>image/png</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pnm</extension>
+ <mime-type>image/x-portable-anymap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>pnt</extension>
+ <mime-type>image/x-macpaint</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ppm</extension>
+ <mime-type>image/x-portable-pixmap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ppt</extension>
+ <mime-type>application/powerpoint</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ps</extension>
+ <mime-type>application/postscript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>psd</extension>
+ <mime-type>image/x-photoshop</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>qt</extension>
+ <mime-type>video/quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>qti</extension>
+ <mime-type>image/x-quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>qtif</extension>
+ <mime-type>image/x-quicktime</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ras</extension>
+ <mime-type>image/x-cmu-raster</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rdf</extension>
+ <mime-type>application/rdf+xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rgb</extension>
+ <mime-type>image/x-rgb</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rm</extension>
+ <mime-type>application/vnd.rn-realmedia</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>roff</extension>
+ <mime-type>application/x-troff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rtf</extension>
+ <mime-type>application/rtf</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>rtx</extension>
+ <mime-type>text/richtext</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>sh</extension>
+ <mime-type>application/x-sh</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>shar</extension>
+ <mime-type>application/x-shar</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>smf</extension>
+ <mime-type>audio/x-midi</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>sit</extension>
+ <mime-type>application/x-stuffit</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>snd</extension>
+ <mime-type>audio/basic</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>src</extension>
+ <mime-type>application/x-wais-source</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>sv4cpio</extension>
+ <mime-type>application/x-sv4cpio</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>sv4crc</extension>
+ <mime-type>application/x-sv4crc</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>svg</extension>
+ <mime-type>image/svg+xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>swf</extension>
+ <mime-type>application/x-shockwave-flash</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>t</extension>
+ <mime-type>application/x-troff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tar</extension>
+ <mime-type>application/x-tar</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tcl</extension>
+ <mime-type>application/x-tcl</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tex</extension>
+ <mime-type>application/x-tex</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>texi</extension>
+ <mime-type>application/x-texinfo</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>texinfo</extension>
+ <mime-type>application/x-texinfo</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tif</extension>
+ <mime-type>image/tiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tiff</extension>
+ <mime-type>image/tiff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tr</extension>
+ <mime-type>application/x-troff</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>tsv</extension>
+ <mime-type>text/tab-separated-values</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>txt</extension>
+ <mime-type>text/plain</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ulw</extension>
+ <mime-type>audio/basic</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>ustar</extension>
+ <mime-type>application/x-ustar</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>vxml</extension>
+ <mime-type>application/voicexml+xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xbm</extension>
+ <mime-type>image/x-xbitmap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xht</extension>
+ <mime-type>application/xhtml+xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xhtml</extension>
+ <mime-type>application/xhtml+xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xml</extension>
+ <mime-type>application/xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xpm</extension>
+ <mime-type>image/x-xpixmap</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xsl</extension>
+ <mime-type>application/xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xslt</extension>
+ <mime-type>application/xslt+xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xul</extension>
+ <mime-type>application/vnd.mozilla.xul+xml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>xwd</extension>
+ <mime-type>image/x-xwindowdump</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>wav</extension>
+ <mime-type>audio/x-wav</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>svg</extension>
+ <mime-type>image/svg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>svgz</extension>
+ <mime-type>image/svg</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>vsd</extension>
+ <mime-type>application/x-visio</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <!-- Wireless Bitmap -->
+ <extension>wbmp</extension>
+ <mime-type>image/vnd.wap.wbmp</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <!-- WML Source -->
+ <extension>wml</extension>
+ <mime-type>text/vnd.wap.wml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <!-- Compiled WML -->
+ <extension>wmlc</extension>
+ <mime-type>application/vnd.wap.wmlc</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <!-- WML Script Source -->
+ <extension>wmls</extension>
+ <mime-type>text/vnd.wap.wmlscript</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <!-- Compiled WML Script -->
+ <extension>wmlscriptc</extension>
+ <mime-type>application/vnd.wap.wmlscriptc</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>wrl</extension>
+ <mime-type>x-world/x-vrml</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>Z</extension>
+ <mime-type>application/x-compress</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>z</extension>
+ <mime-type>application/x-compress</mime-type>
+ </mime-mapping>
+ <mime-mapping>
+ <extension>zip</extension>
+ <mime-type>application/zip</mime-type>
+ </mime-mapping>
+
+
+ <!-- ==================== Default Welcome File List ===================== -->
+ <!-- When a request URI refers to a directory, the default servlet looks -->
+ <!-- for a "welcome file" within that directory and, if present, -->
+ <!-- to the corresponding resource URI for display. If no welcome file -->
+ <!-- is present, the default servlet either serves a directory listing, -->
+ <!-- or returns a 404 status, depending on how it is configured. -->
+ <!-- -->
+ <!-- If you define welcome files in your own application's web.xml -->
+ <!-- deployment descriptor, that list *replaces* the list configured -->
+ <!-- here, so be sure that you include any of the default values that -->
+ <!-- you wish to include. -->
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ <welcome-file>index.htm</welcome-file>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <error-page>
+ <error-code>404</error-code>
+ <location>/404.html</location>
+ </error-page>
+
+ <error-page>
+ <error-code>500</error-code>
+ <location>/500.html</location>
+ </error-page>
+
+</web-app>
diff --git a/base/tps/shared/conf/workers.properties b/base/tps/shared/conf/workers.properties
new file mode 100644
index 000000000..ae26a983c
--- /dev/null
+++ b/base/tps/shared/conf/workers.properties
@@ -0,0 +1,209 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+# workers.properties -
+#
+# This file provides jk derived plugins with the needed information to
+# connect to the different tomcat workers. Note that the distributed
+# version of this file requires modification before it is usable by a
+# plugin.
+#
+# As a general note, the characters $( and ) are used internally to define
+# macros. Do not use them in your own configuration!!!
+#
+# Whenever you see a set of lines such as:
+# x=value
+# y=$(x)\something
+#
+# the final value for y will be value\something
+#
+# Normaly all you will need to do is un-comment and modify the first three
+# properties, i.e. workers.tomcat_home, workers.java_home and ps.
+# Most of the configuration is derived from these.
+#
+# When you are done updating workers.tomcat_home, workers.java_home and ps
+# you should have 3 workers configured:
+#
+# - An ajp12 worker that connects to localhost:8007
+# - An ajp13 worker that connects to localhost:8009
+# - A jni inprocess worker.
+# - A load balancer worker
+#
+# However by default the plugins will only use the ajp12 worker. To have
+# the plugins use other workers you should modify the worker.list property.
+#
+#
+
+# OPTIONS ( very important for jni mode )
+
+#
+# workers.tomcat_home should point to the location where you
+# installed tomcat. This is where you have your conf, webapps and lib
+# directories.
+#
+workers.tomcat_home=/var/tomcat3
+
+#
+# workers.java_home should point to your Java installation. Normally
+# you should have a bin and lib directories beneath it.
+#
+workers.java_home=/opt/IBMJava2-13
+
+#
+# You should configure your environment slash... ps=\ on NT and / on UNIX
+# and maybe something different elsewhere.
+#
+ps=/
+
+#
+#------ ADVANCED MODE ------------------------------------------------
+#---------------------------------------------------------------------
+#
+
+#
+#------ DEFAULT worket list ------------------------------------------
+#---------------------------------------------------------------------
+#
+#
+# The workers that your plugins should create and work with
+#
+# Add 'inprocess' if you want JNI connector
+worker.list=ajp12, ajp13
+# , inprocess
+
+
+#
+#------ DEFAULT ajp12 WORKER DEFINITION ------------------------------
+#---------------------------------------------------------------------
+#
+
+#
+# Defining a worker named ajp12 and of type ajp12
+# Note that the name and the type do not have to match.
+#
+worker.ajp12.port=8007
+worker.ajp12.host=localhost
+worker.ajp12.type=ajp12
+#
+# Specifies the load balance factor when used with
+# a load balancing worker.
+# Note:
+# ----> lbfactor must be > 0
+# ----> Low lbfactor means less work done by the worker.
+worker.ajp12.lbfactor=1
+
+#
+#------ DEFAULT ajp13 WORKER DEFINITION ------------------------------
+#---------------------------------------------------------------------
+#
+
+#
+# Defining a worker named ajp13 and of type ajp13
+# Note that the name and the type do not have to match.
+#
+worker.ajp13.port=8009
+worker.ajp13.host=localhost
+worker.ajp13.type=ajp13
+#
+# Specifies the load balance factor when used with
+# a load balancing worker.
+# Note:
+# ----> lbfactor must be > 0
+# ----> Low lbfactor means less work done by the worker.
+worker.ajp13.lbfactor=1
+
+#
+# Specify the size of the open connection cache.
+#worker.ajp13.cachesize
+
+#
+#------ DEFAULT LOAD BALANCER WORKER DEFINITION ----------------------
+#---------------------------------------------------------------------
+#
+
+#
+# The loadbalancer (type lb) workers perform wighted round-robin
+# load balancing with sticky sessions.
+# Note:
+# ----> If a worker dies, the load balancer will check its state
+# once in a while. Until then all work is redirected to peer
+# workers.
+worker.loadbalancer.type=lb
+worker.loadbalancer.balanced_workers=ajp12, ajp13
+
+
+#
+#------ DEFAULT JNI WORKER DEFINITION---------------------------------
+#---------------------------------------------------------------------
+#
+
+#
+# Defining a worker named inprocess and of type jni
+# Note that the name and the type do not have to match.
+#
+worker.inprocess.type=jni
+
+#
+#------ CLASSPATH DEFINITION -----------------------------------------
+#---------------------------------------------------------------------
+#
+
+#
+# Additional class path components.
+#
+worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)tomcat.jar
+
+#
+# Setting the command line for tomcat.
+# Note: The cmd_line string may not contain spaces.
+#
+worker.inprocess.cmd_line=start
+
+# Not needed, but can be customized.
+#worker.inprocess.cmd_line=-config
+#worker.inprocess.cmd_line=$(workers.tomcat_home)$(ps)conf$(ps)server.xml
+#worker.inprocess.cmd_line=-home
+#worker.inprocess.cmd_line=$(workers.tomcat_home)
+
+#
+# The JVM that we are about to use
+#
+# This is for Java2
+#
+# Windows
+worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)jvm.dll
+# IBM JDK1.3
+#worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)libjvm.so
+# Unix - Sun VM or blackdown
+#worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)lib$(ps)i386$(ps)classic$(ps)libjvm.so
+
+#
+# And this is for jdk1.1.X
+#
+#worker.inprocess.jvm_lib=$(workers.java_home)$(ps)bin$(ps)javai.dll
+
+
+#
+# Setting the place for the stdout and stderr of tomcat
+#
+worker.inprocess.stdout=$(workers.tomcat_home)$(ps)logs$(ps)inprocess.stdout
+worker.inprocess.stderr=$(workers.tomcat_home)$(ps)logs$(ps)inprocess.stderr
+
+#
+# Setting the tomcat.home Java property
+#
+#worker.inprocess.sysprops=tomcat.home=$(workers.tomcat_home)
+
+#
+# Java system properties
+#
+# worker.inprocess.sysprops=java.compiler=NONE
+# worker.inprocess.sysprops=myprop=mypropvalue
+
+#
+# Additional path components.
+#
+# worker.inprocess.ld_path=d:$(ps)SQLLIB$(ps)bin
+#
diff --git a/base/tps/shared/conf/workers.properties.minimal b/base/tps/shared/conf/workers.properties.minimal
new file mode 100644
index 000000000..51980ac49
--- /dev/null
+++ b/base/tps/shared/conf/workers.properties.minimal
@@ -0,0 +1,22 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+# workers.properties.minimal -
+#
+# This file provides minimal jk configuration properties needed to
+# connect to Tomcat.
+#
+# The workers that jk should create and work with
+#
+worker.list=ajp13w
+
+
+#
+# Defining a worker named ajp13w and of type ajp13
+# Note that the name and the type do not have to match.
+#
+worker.ajp13w.type=ajp13
+worker.ajp13w.host=localhost
+worker.ajp13w.port=8009
diff --git a/base/tps/shared/conf/workers2.properties b/base/tps/shared/conf/workers2.properties
new file mode 100644
index 000000000..3c8e0f4a5
--- /dev/null
+++ b/base/tps/shared/conf/workers2.properties
@@ -0,0 +1,136 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+[logger]
+level=DEBUG
+
+[config:]
+file=${serverRoot}/conf/workers2.properties
+debug=0
+debugEnv=0
+
+[uriMap:]
+info=Maps the requests. Options: debug
+debug=0
+
+# Alternate file logger
+#[logger.file:0]
+#level=DEBUG
+#file=${serverRoot}/logs/jk2.log
+
+[shm:]
+info=Scoreboard. Required for reconfiguration and status with multiprocess servers
+file=${serverRoot}/logs/jk2.shm
+size=1000000
+debug=0
+disabled=0
+
+[workerEnv:]
+info=Global server options
+timing=1
+debug=0
+# Default Native Logger (apache2 or win32 )
+# can be overriden to a file logger, useful
+# when tracing win32 related issues
+#logger=logger.file:0
+
+[lb:lb]
+info=Default load balancer.
+debug=0
+
+[lb:lb_1]
+info=A second load balancer.
+debug=0
+
+[channel.socket:localhost:8009]
+info=Ajp13 forwarding over socket
+debug=0
+tomcatId=localhost:8009
+
+[channel.socket:localhost:8019]
+info=A second tomcat instance.
+debug=0
+tomcatId=localhost:8019
+lb_factor=1
+#group=lb
+group:lb:lb
+#group=lb_1
+group:lb:lb_1
+disabled=0
+
+[channel.un:/opt/33/work/jk2.socket]
+info=A second channel connecting to localhost:8019 via unix socket
+tomcatId=localhost:8019
+lb_factor=1
+debug=0
+
+[channel.jni:jni]
+info=The jni channel, used if tomcat is started inprocess
+
+[status:]
+info=Status worker, displays runtime informations
+
+[vm:]
+info=Parameters used to load a JVM in the server process
+#JVM=C:\jdk\jre\bin\hotspot\jvm.dll
+classpath=${TOMCAT_HOME}/bin/tomcat-jni.jar
+classpath=${TOMCAT_HOME}/server/lib/commons-logging.jar
+OPT=-Dtomcat.home=${TOMCAT_HOME}
+OPT=-Dcatalina.home=${TOMCAT_HOME}
+OPT=-Xmx128M
+#OPT=-Djava.compiler=NONE
+disabled=1
+
+[worker.jni:onStartup]
+info=Command to be executed by the VM on startup. This one will start tomcat.
+class=org/apache/jk/apr/TomcatStarter
+ARG=start
+# For Tomcat 5 use the 'stard' for startup argument
+# ARG=stard
+disabled=1
+stdout=${serverRoot}/logs/stdout.log
+stderr=${serverRoot}/logs/stderr.log
+
+[worker.jni:onShutdown]
+info=Command to be executed by the VM on shutdown. This one will stop tomcat.
+class=org/apache/jk/apr/TomcatStarter
+ARG=stop
+disabled=1
+
+[uri:/jkstatus/*]
+info=Display status information and checks the config file for changes.
+group=status:
+
+[uri:127.0.0.1:8003]
+info=Example virtual host. Make sure myVirtualHost is in /etc/hosts to test it
+alias=myVirtualHost:8003
+
+[uri:127.0.0.1:8003/ex]
+info=Example webapp in the virtual host. It'll go to lb_1 ( i.e. localhost:8019 )
+context=/ex
+group=lb_1
+
+[uri:/examples]
+info=Example webapp in the default context.
+context=/examples
+debug=0
+
+[uri:/examples1/*]
+info=A second webapp, this time going to the second tomcat only.
+group=lb_1
+debug=0
+
+[uri:/examples/servlet/*]
+info=Prefix mapping
+
+[uri:/examples/*.jsp]
+info=Extension mapping
+
+[uri:/examples/*]
+info=Map the whole webapp
+
+[uri:/examples/servlet/HelloW]
+info=Example with debug enabled.
+debug=10
diff --git a/base/tps/shared/conf/workers2.properties.minimal b/base/tps/shared/conf/workers2.properties.minimal
new file mode 100644
index 000000000..0e88d14c7
--- /dev/null
+++ b/base/tps/shared/conf/workers2.properties.minimal
@@ -0,0 +1,60 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+#
+# This is the minimal JK2 connector configuration file.
+#
+
+[logger]
+info=Native logger
+level=ERROR
+
+[config:]
+file=${serverRoot}/conf/workers2.properties
+debug=0
+debugEnv=0
+
+[uriMap:]
+info=Maps the requests.
+debug=0
+
+[shm:]
+info=Scoreboard. Required for reconfiguration and status with multiprocess servers
+file=anonymous
+debug=0
+
+[workerEnv:]
+info=Global server options
+timing=0
+debug=0
+
+[lb:lb]
+info=Default load balancer.
+debug=0
+
+[channel.socket:localhost:8009]
+info=Ajp13 forwarding over socket
+debug=0
+tomcatId=localhost:8009
+
+[uri:/admin]
+info=Tomcat HTML based administration web application.
+debug=0
+
+[uri:/manager]
+info=A scriptable management web application for the Tomcat Web Server.
+debug=0
+
+[uri:/jsp-examples]
+info=JSP 2.0 Examples.
+debug=0
+
+[uri:/servlets-examples]
+info=Servlet 2.4 Examples.
+debug=0
+
+[uri:/*.jsp]
+info=JSP Extension mapping.
+debug=0
diff --git a/base/tps/shared/webapps/tps/404.html b/base/tps/shared/webapps/tps/404.html
new file mode 100755
index 000000000..0bf93578c
--- /dev/null
+++ b/base/tps/shared/webapps/tps/404.html
@@ -0,0 +1,145 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2009 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<script language=javascript>
+var url = document.URL;
+var protocol = location.protocol;
+var hostname = location.hostname;
+var port = location.port;
+</script>
+
+<head>
+<title>TPS 404 Error!</title>
+<!-- always expand ALL relative paths -->
+<script language=javascript>
+document.write('<link rel="shortcut icon" href="');
+document.write(protocol);
+document.write('//');
+document.write(hostname);
+document.write(':');
+document.write(port);
+document.write('/pki/images/favicon.ico');
+document.write('" />');
+document.write('<link rel="stylesheet" href="');
+document.write(protocol);
+document.write('//');
+document.write(hostname);
+document.write(':');
+document.write(port);
+document.write('/pki/css/pki-base.css');
+document.write('" type="text/css" />');
+document.write('<META http-equiv=Content-Type content="text/html; charset=UTF-8">');
+</script>
+</head>
+<body bgcolor="#FFFFFF" link="#666699" vlink="#666699" alink="#333366">
+<div id="header">
+<!-- always expand ALL relative paths -->
+<script language=javascript>
+document.write('<a href="http://pki.fedoraproject.org/" title="Visit pki.fedoraproject.org for more information about Dogtag products and services"><img src="');
+document.write(protocol);
+document.write('//');
+document.write(hostname);
+document.write(':');
+document.write(port);
+document.write('/pki/images/logo_header.gif');
+document.write('" alt="Dogtag" id="myLogo" /></a>');
+</script>
+ <div id="headertitle">
+ <a href="/" title="Dogtag Network homepage">Dogtag<sup><font size="-2">&reg;</font></sup> Certificate System</a>
+ </div>
+ <div id="account">
+ <dl><dt><span></span></dt><dd></dd></dl>
+ </div>
+</div>
+
+<div id="mainNavOuter">
+<div id="mainNav">
+<div id="mainNavInner">
+
+</div><!-- end mainNavInner -->
+</div><!-- end mainNav -->
+</div><!-- end mainNavOuter -->
+
+
+<div id="bar">
+
+<div id="systembar">
+<div id="systembarinner">
+
+<div>
+ -
+</div>
+
+
+</div>
+</div>
+
+</div>
+<font size="+1" face="PrimaSans BT, Verdana, Arial, Helvetica, sans-serif">
+Certificate System TPS Error Page
+</font><br>
+<p>
+</font>
+<p>
+<script language=javascript>
+document.write('<center>');
+document.write('<table border="1" cellspacing="0" cellpadding="0">');
+document.write('<tr valign="TOP">');
+document.write('<td bgcolor="grey" align="center"><b><font color="BLACK">HTTP STATUS</font></b></td>');
+document.write('<td bgcolor="grey" align="center"><b><font color="BLACK">DESCRIPTION</font></b></td>');
+document.write('</tr>');
+document.write('<tr valign="TOP">');
+document.write('<td align="center"><b><font size="+3" color="red">');
+document.write('404');
+document.write('</font></b></td>');
+document.write('<td><b><font size="+1" color="RED">');
+document.write('The requested resource could not be found but may be available again in the future.');
+document.write('</font></b><br><b><font size="+1" color="RED">');
+document.write('Please check the validity of the URL listed below:');
+document.write('</font></b><br><br>');
+document.write('<center><b><font size="+1"><a href="');
+document.write(url);
+document.write('">');
+document.write(url);
+document.write('</a>');
+document.write('</font></b></center><br></td>');
+document.write('</tr>');
+document.write('</table>');
+document.write('</center>');
+</script>
+<div id="footer">
+</div>
+<!--
+To prevent Internet Explorer from overriding the display of this custom error
+page by displaying it's own "Friendly HTTP Error Message", always include the
+following 'padding' to ensure that the text size exceeds 512 bytes:
+
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+-->
+</body>
+</html>
diff --git a/base/tps/shared/webapps/tps/500.html b/base/tps/shared/webapps/tps/500.html
new file mode 100755
index 000000000..3e1e8bb66
--- /dev/null
+++ b/base/tps/shared/webapps/tps/500.html
@@ -0,0 +1,138 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2009 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<script language=javascript>
+var url = document.URL;
+var protocol = location.protocol;
+var hostname = location.hostname;
+var port = location.port;
+</script>
+
+<head>
+<title>TPS 500 Error!</title>
+<!-- always expand ALL relative paths -->
+<script language=javascript>
+document.write('<link rel="shortcut icon" href="');
+document.write(protocol);
+document.write('//');
+document.write(hostname);
+document.write(':');
+document.write(port);
+document.write('/pki/images/favicon.ico');
+document.write('" />');
+document.write('<link rel="stylesheet" href="');
+document.write(protocol);
+document.write('//');
+document.write(hostname);
+document.write(':');
+document.write(port);
+document.write('/pki/css/pki-base.css');
+document.write('" type="text/css" />');
+document.write('<META http-equiv=Content-Type content="text/html; charset=UTF-8">');
+</script>
+</head>
+<body bgcolor="#FFFFFF" link="#666699" vlink="#666699" alink="#333366">
+<div id="header">
+<!-- always expand ALL relative paths -->
+<script language=javascript>
+document.write('<a href="http://pki.fedoraproject.org/" title="Visit pki.fedoraproject.org for more information about Dogtag products and services"><img src="');
+document.write(protocol);
+document.write('//');
+document.write(hostname);
+document.write(':');
+document.write(port);
+document.write('/pki/images/logo_header.gif');
+document.write('" alt="Dogtag" id="myLogo" /></a>');
+</script>
+ <div id="headertitle">
+ <a href="/" title="Dogtag Network homepage">Dogtag<sup><font size="-2">&reg;</font></sup> Certificate System</a>
+ </div>
+ <div id="account">
+ <dl><dt><span></span></dt><dd></dd></dl>
+ </div>
+</div>
+
+<div id="mainNavOuter">
+<div id="mainNav">
+<div id="mainNavInner">
+
+</div><!-- end mainNavInner -->
+</div><!-- end mainNav -->
+</div><!-- end mainNavOuter -->
+
+
+<div id="bar">
+
+<div id="systembar">
+<div id="systembarinner">
+
+<div>
+ -
+</div>
+
+
+</div>
+</div>
+
+</div>
+<font size="+1" face="PrimaSans BT, Verdana, Arial, Helvetica, sans-serif">
+Certificate System TPS Error Page
+</font><br>
+<p>
+</font>
+<p>
+<script language=javascript>
+document.write('<center>');
+document.write('<table border="1" cellspacing="0" cellpadding="0">');
+document.write('<tr valign="TOP">');
+document.write('<td bgcolor="grey" align="center"><b><font color="BLACK">HTTP STATUS</font></b></td>');
+document.write('<td bgcolor="grey" align="center"><b><font color="BLACK">DESCRIPTION</font></b></td>');
+document.write('</tr>');
+document.write('<tr valign="TOP">');
+document.write('<td align="center"><b><font size="+3" color="red">');
+document.write('500');
+document.write('</font></b></td>');
+document.write('<td><b><font size="+1" color="RED">');
+document.write('The server encountered an unexpected condition which prevented it from fulfilling the request.<br>');
+document.write('Please consult your local administrator for further assistance. The Certificate System logs may provide further information.');
+document.write('</font></b><br></td>');
+document.write('</tr>');
+document.write('</table>');
+document.write('</center>');
+</script>
+<div id="footer">
+</div>
+<!--
+To prevent Internet Explorer from overriding the display of this custom error
+page by displaying it's own "Friendly HTTP Error Message", always include the
+following 'padding' to ensure that the text size exceeds 512 bytes:
+
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+[IE padding][IE padding][IE padding][IE padding][IE padding][IE padding]
+-->
+</body>
+</html>
diff --git a/base/tps/shared/webapps/tps/GenUnexpectedError.template b/base/tps/shared/webapps/tps/GenUnexpectedError.template
new file mode 100644
index 000000000..ea545c145
--- /dev/null
+++ b/base/tps/shared/webapps/tps/GenUnexpectedError.template
@@ -0,0 +1,67 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2007 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<CMS_TEMPLATE>
+
+<TITLE>TPS Processing Error!</TITLE>
+
+<BODY BGCOLOR="white">
+
+<font size="+1" face="PrimaSans BT, Verdana, Arial, Helvetica, sans-serif">
+Problem Processing Your Request
+</font>
+
+<table BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%" BACKGROUND="/pki/images/hr.gif" >
+ <tr>
+ <td>&nbsp;</td>
+ </tr>
+</table>
+
+<font size="-1" face="PrimaSans BT, Verdana, Arial, Helvetica, sans-serif">
+
+<SCRIPT LANGUAGE="JavaScript">
+var authority = 'Certificate System';
+if (result.fixed.authorityName != null) {
+ authority = result.fixed.authorityName;
+}
+
+document.writeln('<P>');
+document.write('The '+authority+' encountered an unexpected error ');
+document.writeln(' while processing your request.');
+document.writeln(
+ 'The following is a detailed message of the error that occurred.');
+
+document.writeln('<P>');
+document.writeln('<BLOCKQUOTE><B><PRE>');
+if (result.fixed.unexpectedError != null) {
+ document.write(result.fixed.unexpectedError);
+} else {
+ document.write('No further details provided.');
+}
+document.writeln('</PRE></B></BLOCKQUOTE>');
+
+document.writeln('<P>');
+document.writeln(
+ 'Please consult your local administrator for further assistance.');
+document.writeln('The Certificate System logs may provide further information.');
+</SCRIPT>
+
+</font>
+</BODY>
+</HTML>
diff --git a/base/tps/shared/webapps/tps/WEB-INF/velocity.properties b/base/tps/shared/webapps/tps/WEB-INF/velocity.properties
new file mode 100644
index 000000000..c1c6e4ea9
--- /dev/null
+++ b/base/tps/shared/webapps/tps/WEB-INF/velocity.properties
@@ -0,0 +1,13 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2006 Red Hat, Inc.
+# All rights reserved.
+# --- END COPYRIGHT BLOCK ---
+#
+resource.loader = file
+file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
+file.resource.loader.path = /usr/share/pki/server/webapps/pki
+file.resource.loader.cache = true
+file.resource.loader.modificationCheckInterval = 2
+input.encoding=UTF-8
+output.encoding=UTF-8
+runtime.log.logsystem.class=org.apache.velocity.runtime.log.NullLogSystem
diff --git a/base/tps/shared/webapps/tps/WEB-INF/web.xml b/base/tps/shared/webapps/tps/WEB-INF/web.xml
new file mode 100644
index 000000000..8506b2725
--- /dev/null
+++ b/base/tps/shared/webapps/tps/WEB-INF/web.xml
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- BEGIN COPYRIGHT BLOCK
+ Copyright (C) 2006 Red Hat, Inc.
+ All rights reserved.
+ END COPYRIGHT BLOCK -->
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "file:///usr/share/pki/setup/web-app_2_3.dtd">
+<web-app>
+
+ <display-name>Token Processing Service</display-name>
+
+ <servlet>
+ <servlet-name>tpsstart</servlet-name>
+ <servlet-class>com.netscape.cms.servlet.base.CMSStartServlet</servlet-class>
+ <init-param>
+ <param-name>AuthzMgr</param-name>
+ <param-value>BasicAclAuthz</param-value>
+ </init-param>
+ <init-param>
+ <param-name>ID</param-name>
+ <param-value>tpsstart</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet>
+ <servlet-name>tpsug</servlet-name>
+ <servlet-class>com.netscape.cms.servlet.admin.UsrGrpAdminServlet</servlet-class>
+ <init-param>
+ <param-name>ID</param-name>
+ <param-value>tpsug</param-value>
+ </init-param>
+ <init-param>
+ <param-name>AuthzMgr</param-name>
+ <param-value>BasicAclAuthz</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <servlet-name>tpslog</servlet-name>
+ <servlet-class>com.netscape.cms.servlet.admin.LogAdminServlet</servlet-class>
+ <init-param>
+ <param-name>ID</param-name>
+ <param-value>tpslog</param-value> </init-param>
+ <init-param>
+ <param-name>AuthzMgr</param-name>
+ <param-value>BasicAclAuthz</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <servlet-name>tpsGetStatus </servlet-name>
+ <servlet-class> com.netscape.cms.servlet.csadmin.GetStatus</servlet-class>
+ <init-param>
+ <param-name>GetClientCert</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>authority</param-name>
+ <param-value>tps</param-value>
+ </init-param>
+ <init-param>
+ <param-name>ID</param-name>
+ <param-value>tpsGetStatus</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet>
+ <servlet-name>phoneHome</servlet-name>
+ <servlet-class>org.dogtagpki.server.tps.TPSPhoneHome</servlet-class>
+ </servlet>
+
+ <servlet>
+ <servlet-name>tps</servlet-name>
+ <servlet-class>org.dogtagpki.server.tps.TPSServlet</servlet-class>
+ </servlet>
+
+ <listener>
+ <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
+ </listener>
+
+ <context-param>
+ <param-name>resteasy.servlet.mapping.prefix</param-name>
+ <param-value>/rest</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>resteasy.resource.method-interceptors</param-name>
+ <param-value>org.jboss.resteasy.core.ResourceMethodSecurityInterceptor</param-value>
+ </context-param>
+
+ <servlet>
+ <servlet-name>Resteasy</servlet-name>
+ <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.dogtagpki.server.tps.rest.TPSApplication</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Resteasy</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>tpsstart</servlet-name>
+ <url-pattern>/start</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>tpsug</servlet-name>
+ <url-pattern>/ug</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>tpslog</servlet-name>
+ <url-pattern>/log</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>tpsGetStatus</servlet-name>
+ <url-pattern>/admin/tps/getStatus</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>phoneHome</servlet-name>
+ <url-pattern>/phoneHome</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>tps</servlet-name>
+ <url-pattern>/tps</url-pattern>
+ </servlet-mapping>
+
+ <!-- ==================== Default Session Configuration =============== -->
+ <!-- You can set the default session timeout (in minutes) for all newly -->
+ <!-- created sessions by modifying the value below. -->
+ <!-- -->
+ <!-- To disable session timeouts for this instance, set a value of -1. -->
+
+ <session-config>
+ <session-timeout>30</session-timeout>
+ </session-config>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Account Services</web-resource-name>
+ <url-pattern>/rest/account/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Admin Services</web-resource-name>
+ <url-pattern>/rest/admin/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Audit</web-resource-name>
+ <url-pattern>/rest/audit/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Authenticators</web-resource-name>
+ <url-pattern>/rest/authenticators/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Configuration</web-resource-name>
+ <url-pattern>/rest/config/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Connectors</web-resource-name>
+ <url-pattern>/rest/connectors/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Profiles</web-resource-name>
+ <url-pattern>/rest/profiles/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Profile Mappings</web-resource-name>
+ <url-pattern>/rest/profile-mappings/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Self Tests</web-resource-name>
+ <url-pattern>/rest/selftests/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Token Services</web-resource-name>
+ <url-pattern>/rest/tokens/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>UI</web-resource-name>
+ <url-pattern>/ui/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+
+ <login-config>
+ <realm-name>Token Processing Service</realm-name>
+ </login-config>
+
+ <security-role>
+ <role-name>*</role-name>
+ </security-role>
+
+</web-app>
diff --git a/base/tps/shared/webapps/tps/index.html b/base/tps/shared/webapps/tps/index.html
new file mode 100644
index 000000000..c48da3307
--- /dev/null
+++ b/base/tps/shared/webapps/tps/index.html
@@ -0,0 +1,73 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<html>
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link href="/pki/css/patternfly.css" rel="stylesheet" media="screen, print">
+ <script src="/pki/js/jquery.js"></script>
+ <script src="/pki/js/bootstrap.js"></script>
+ <script src="/tps/js/account.js"></script>
+ <script>
+$(function() {
+ var account = new Account();
+ $("form").submit(function(e) {
+ account.login({
+ success: function() {
+ window.location.href = "/tps/ui";
+ },
+ error: function() {
+ PKI.logout();
+ }
+ });
+ e.preventDefault();
+ });
+});
+ </script>
+</head>
+<body>
+
+<nav id="navigation" class="navbar navbar-default navbar-pf" role="navigation">
+<div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="navbar-brand" href="/tps">
+ <b>Token Processing Service</b>
+ </a>
+</div>
+</nav>
+
+<div id="content">
+
+<form action="/tps/ui">
+<div class="col-sm-5 col-md-6 col-lg-7 details">
+<p><strong>Welcome to the Dogtag Token Processing System 10.2</strong>
+<p>The Token Processing System (TPS) is the conduit between the user-centered Enterprise Security Client,
+which interacts with the tokens, and the Certificate System backend subsystems, such as the Certificate Manager.
+</p>
+<button type="submit" class="btn btn-primary btn-lg" tabindex="4">Log In</button>
+</div>
+</form>
+
+</div>
+
+</body>
+</html>
diff --git a/base/tps/shared/webapps/tps/js/account.js b/base/tps/shared/webapps/tps/js/account.js
new file mode 100644
index 000000000..97b222aaa
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/account.js
@@ -0,0 +1,37 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+function Account() {
+
+ this.url = "/tps/rest/account";
+
+ this.login = function(options) {
+ var jqxhr = $.get(this.url + "/login", null, null, "json");
+ jqxhr.done(options.success);
+ jqxhr.fail(options.error);
+ };
+
+ this.logout = function(options) {
+ var jqxhr = $.get(this.url + "/logout");
+ jqxhr.done(options.success);
+ jqxhr.fail(options.error);
+ };
+}; \ No newline at end of file
diff --git a/base/tps/shared/webapps/tps/js/activity.js b/base/tps/shared/webapps/tps/js/activity.js
new file mode 100644
index 000000000..cbc724e23
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/activity.js
@@ -0,0 +1,97 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var ActivityModel = Model.extend({
+ urlRoot: "/tps/rest/activities",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ tokenID: response.TokenID,
+ userID: response.UserID,
+ ip: response.IP,
+ operation: response.Operation,
+ result: response.Result,
+ message: response.Message,
+ date: new Date(response.Date)
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: attributes.id,
+ TokenID: attributes.tokenID,
+ UserID: attributes.userID,
+ IP: attributes.ip,
+ Operation: attributes.operation,
+ Result: attributes.result,
+ Message: attributes.message,
+ Date: attributes.date.getTime()/1000 + 'Z'
+ };
+ }
+});
+
+var ActivityCollection = Collection.extend({
+ urlRoot: "/tps/rest/activities",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new ActivityModel({
+ id: entry.id,
+ tokenID: entry.TokenID,
+ userID: entry.UserID,
+ ip: entry.IP,
+ operation: entry.Operation,
+ result: entry.Result,
+ message: entry.Message,
+ date: new Date(entry.Date)
+ });
+ }
+});
+
+var ActivityPage = EntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ ActivityPage.__super__.initialize.call(self, options);
+ }
+});
+
+var ActivitiesTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ ActivitiesTable.__super__.initialize.call(self, options);
+ }
+});
+
+var ActivitiesPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new ActivitiesTable({
+ el: $("table[name='activities']"),
+ collection: new ActivityCollection()
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/audit.js b/base/tps/shared/webapps/tps/js/audit.js
new file mode 100644
index 000000000..986596e1d
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/audit.js
@@ -0,0 +1,232 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var AuditModel = Model.extend({
+ url: function() {
+ return "/tps/rest/audit";
+ },
+ parseResponse: function(response) {
+ return {
+ id: "audit",
+ status: response.Status,
+ signed: response.Signed,
+ interval: response.Interval,
+ bufferSize: response.BufferSize,
+ events: response.Events.Event
+ };
+ },
+ createRequest: function(entry) {
+ return {
+ Status: entry.status,
+ Signed: entry.signed,
+ Interval: entry.interval,
+ BufferSize: entry.bufferSize,
+ Events: {
+ Event: entry.events
+ }
+ };
+ },
+ enable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=enable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ },
+ disable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=disable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ }
+});
+
+var AuditTableItem = TableItem.extend({
+ initialize: function(options) {
+ var self = this;
+ AuditTableItem.__super__.initialize.call(self, options);
+ },
+ renderColumn: function(td, templateTD) {
+ var self = this;
+
+ AuditTableItem.__super__.renderColumn.call(self, td, templateTD);
+
+ $("a", td).click(function(e) {
+ e.preventDefault();
+ self.open();
+ });
+ },
+ open: function() {
+ var self = this;
+
+ var value = self.get("value");
+ var dialog;
+
+ if (self.table.mode == "view" || value == "mandatory") {
+ // In view mode all events are read-only.
+ // Mandatory events are always read-only.
+ dialog = new Dialog({
+ el: self.table.parent.$("#event-dialog"),
+ title: "Event",
+ readonly: ["name", "value"],
+ actions: ["close"]
+ });
+
+ } else if (self.table.mode == "edit" && value != "mandatory") {
+ // Optional events are editable in edit mode.
+ dialog = new Dialog({
+ el: self.table.parent.$("#event-dialog"),
+ title: "Edit Event",
+ readonly: ["name"],
+ actions: ["cancel", "save"]
+ });
+
+ dialog.handler("save", function() {
+
+ // save changes
+ dialog.save();
+ _.extend(self.entry, dialog.entry);
+
+ // redraw table
+ self.table.render();
+ dialog.close();
+ });
+ }
+
+ dialog.entry = _.clone(self.entry);
+
+ dialog.open();
+ }
+});
+
+var AuditPage = EntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ options.model = new AuditModel();
+ options.editable = ["signed", "interval", "bufferSize"];
+ AuditPage.__super__.initialize.call(self, options);
+ },
+ setup: function() {
+ var self = this;
+
+ AuditPage.__super__.setup.call(self);
+
+ self.enableLink = $("a[name='enable']", self.menu);
+ self.disableLink = $("a[name='disable']", self.menu);
+
+ self.enableLink.click(function(e) {
+
+ e.preventDefault();
+
+ var message = "Are you sure you want to enable this entry?";
+ if (!confirm(message)) return;
+ self.model.enable({
+ success: function(data, textStatus, jqXHR) {
+ self.entry = _.clone(self.model.attributes);
+ self.render();
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ new ErrorDialog({
+ el: $("#error-dialog"),
+ title: "HTTP Error " + jqXHR.responseJSON.Code,
+ content: jqXHR.responseJSON.Message
+ }).open();
+ }
+ });
+ });
+
+ self.disableLink.click(function(e) {
+
+ e.preventDefault();
+
+ var message = "Are you sure you want to disable this entry?";
+ if (!confirm(message)) return;
+ self.model.disable({
+ success: function(data, textStatus, jqXHR) {
+ self.entry = _.clone(self.model.attributes);
+ self.render();
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ new ErrorDialog({
+ el: $("#error-dialog"),
+ title: "HTTP Error " + jqXHR.responseJSON.Code,
+ content: jqXHR.responseJSON.Message
+ }).open();
+ }
+ });
+ });
+
+ self.eventsTable = new Table({
+ el: self.$("table[name='events']"),
+ columnMappings: {
+ id: "name"
+ },
+ pageSize: 10,
+ tableItem: AuditTableItem,
+ parent: self
+ });
+ },
+ renderContent: function() {
+ var self = this;
+
+ AuditPage.__super__.renderContent.call(self);
+
+ var status = self.entry.status;
+ if (status == "Disabled") {
+ self.enableLink.show();
+ self.disableLink.hide();
+
+ } else if (status == "Enabled") {
+ self.enableLink.hide();
+ self.disableLink.show();
+ }
+
+ if (self.mode == "edit") {
+ self.eventsTable.mode = "edit";
+
+ } else { // self.mode == "view"
+ self.eventsTable.mode = "view";
+ }
+
+ self.eventsTable.entries = self.entry.events;
+ self.eventsTable.render();
+ },
+ saveFields: function() {
+ var self = this;
+
+ AuditPage.__super__.saveFields.call(self);
+
+ self.entry.events = self.eventsTable.entries;
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/authenticator.js b/base/tps/shared/webapps/tps/js/authenticator.js
new file mode 100644
index 000000000..f91cf6bfe
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/authenticator.js
@@ -0,0 +1,109 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var AuthenticatorModel = Model.extend({
+ urlRoot: "/tps/rest/authenticators",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ authenticatorID: response.id,
+ status: response.Status,
+ properties: response.Properties.Property
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: attributes.authenticatorID,
+ Status: attributes.status,
+ Properties: {
+ Property: attributes.properties
+ }
+ };
+ },
+ enable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=enable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ },
+ disable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=disable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ }
+});
+
+var AuthenticatorCollection = Collection.extend({
+ urlRoot: "/tps/rest/authenticators",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new AuthenticatorModel({
+ id: entry.id,
+ status: entry.Status
+ });
+ }
+});
+
+var AuthenticatorsTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ AuthenticatorsTable.__super__.initialize.call(self, options);
+ },
+ add: function() {
+ var self = this;
+
+ window.location.hash = "#new-authenticator";
+ }
+});
+
+var AuthenticatorsPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new AuthenticatorsTable({
+ el: $("table[name='authenticators']"),
+ collection: new AuthenticatorCollection(),
+ parent: self
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/cert.js b/base/tps/shared/webapps/tps/js/cert.js
new file mode 100644
index 000000000..016b56ee0
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/cert.js
@@ -0,0 +1,100 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var CertificateModel = Model.extend({
+ urlRoot: "/tps/rest/certs",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ serialNumber: response.SerialNumber,
+ subject: response.Subject,
+ tokenID: response.TokenID,
+ userID: response.UserID,
+ keyType: response.KeyType,
+ status: response.Status,
+ createTime: response.CreateTime,
+ modifyTime: response.ModifyTime
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: attributes.id,
+ SerialNumber: attributes.serialNumber,
+ Subject: attributes.subject,
+ TokenID: attributes.tokenID,
+ UserID: attributes.userID,
+ KeyType: attributes.keyType,
+ Status: attributes.status,
+ CreateTime: attributes.createTime,
+ ModifyTime: attributes.modifyTime
+ };
+ }
+});
+
+var CertificateCollection = Collection.extend({
+ urlRoot: "/tps/rest/certs",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new CertificateModel({
+ id: entry.id,
+ serialNumber: entry.SerialNumber,
+ subject: entry.Subject,
+ tokenID: entry.TokenID,
+ userID: entry.UserID,
+ keyType: entry.KeyType,
+ status: entry.Status,
+ createTime: entry.CreateTime,
+ modifyTime: entry.ModifyTime
+ });
+ }
+});
+
+var CertificatePage = EntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ CertificatePage.__super__.initialize.call(self, options);
+ }
+});
+
+var CertificatesTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ CertificatesTable.__super__.initialize.call(self, options);
+ }
+});
+
+var CertificatesPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new CertificatesTable({
+ el: $("table[name='certificates']"),
+ collection: new CertificateCollection()
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/config.js b/base/tps/shared/webapps/tps/js/config.js
new file mode 100644
index 000000000..5b651a09d
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/config.js
@@ -0,0 +1,51 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var ConfigModel = Model.extend({
+ url: function() {
+ return "/tps/rest/config";
+ },
+ parseResponse: function(response) {
+ return {
+ id: "config",
+ status: response.Status,
+ properties: response.Properties.Property
+ };
+ },
+ createRequest: function(entry) {
+ return {
+ Status: entry.status,
+ Properties: {
+ Property: entry.properties
+ }
+ };
+ }
+});
+
+var ConfigPage = ConfigEntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ options.model = new ConfigModel();
+ options.tableItem = PropertiesTableItem;
+ options.tableSize = 15;
+ ConfigPage.__super__.initialize.call(self, options);
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/connector.js b/base/tps/shared/webapps/tps/js/connector.js
new file mode 100644
index 000000000..bc7e4c2bd
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/connector.js
@@ -0,0 +1,109 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var ConnectorModel = Model.extend({
+ urlRoot: "/tps/rest/connectors",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ connectorID: response.id,
+ status: response.Status,
+ properties: response.Properties.Property
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: attributes.connectorID,
+ Status: attributes.status,
+ Properties: {
+ Property: attributes.properties
+ }
+ };
+ },
+ enable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=enable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ },
+ disable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=disable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ }
+});
+
+var ConnectorCollection = Collection.extend({
+ urlRoot: "/tps/rest/connectors",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new ConnectorModel({
+ id: entry.id,
+ status: entry.Status
+ });
+ }
+});
+
+var ConnectorsTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ ConnectorsTable.__super__.initialize.call(self, options);
+ },
+ add: function() {
+ var self = this;
+
+ window.location.hash = "#new-connector";
+ }
+});
+
+var ConnectorsPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new ConnectorsTable({
+ el: $("table[name='connectors']"),
+ collection: new ConnectorCollection(),
+ parent: self
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/group.js b/base/tps/shared/webapps/tps/js/group.js
new file mode 100644
index 000000000..50d7d6c67
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/group.js
@@ -0,0 +1,232 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var GroupModel = Model.extend({
+ urlRoot: "/tps/rest/admin/groups",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ groupID: response.GroupID,
+ description: response.Description
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: this.id,
+ GroupID: attributes.groupID,
+ Description: attributes.description
+ };
+ }
+});
+
+var GroupCollection = Collection.extend({
+ model: GroupModel,
+ urlRoot: "/tps/rest/admin/groups",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new GroupModel({
+ id: entry.id,
+ groupID: entry.GroupID,
+ description: entry.Description
+ });
+ }
+});
+
+var GroupMemberModel = Model.extend({
+ url: function() {
+ var self = this;
+
+ // There's an attribute name mismatch for group ID: the
+ // server uses GroupID and the client uses groupID. In other
+ // models the mismatch can be translated just fine, but in
+ // this model it becomes a problem because the model needs
+ // to construct the URL using the attribute.
+ //
+ // During read operation it needs to use the attribute that's
+ // already translated for client (i.e. groupID), but during
+ // add it needs to use the attribute meant for server (i.e.
+ // GroupID). So the workaround is to read whichever available.
+ var groupID = self.get("groupID"); // for read
+ groupID = groupID || self.get("GroupID"); // for add
+
+ var url = "/tps/rest/admin/groups/" + groupID + "/members";
+
+ // append member ID for read
+ if (self.id) url = url + "/" + self.id;
+
+ return url;
+ },
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ memberID: response.id,
+ groupID: response.GroupID
+ };
+ },
+ createRequest: function(entry) {
+ return {
+ id: entry.memberID,
+ GroupID: entry.groupID
+ };
+ }
+});
+
+var GroupMemberCollection = Collection.extend({
+ initialize: function(models, options) {
+ var self = this;
+ GroupMemberCollection.__super__.initialize.call(self, models, options);
+ options = options || {};
+ self.groupID = options.groupID;
+ self.urlRoot = "/tps/rest/admin/groups/" + self.groupID + "/members";
+ },
+ getEntries: function(response) {
+ return response.Member;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ model: function(attrs, options) {
+ return new GroupMemberModel({
+ groupID: this.groupID
+ });
+ },
+ parseEntry: function(entry) {
+ return new GroupMemberModel({
+ id: entry.id,
+ memberID: entry.id,
+ groupID: entry.GroupID
+ });
+ }
+});
+
+var GroupMembersTableItem = TableItem.extend({
+ initialize: function(options) {
+ var self = this;
+ GroupMembersTableItem.__super__.initialize.call(self, options);
+ },
+ renderColumn: function(td, templateTD) {
+ var self = this;
+
+ GroupMembersTableItem.__super__.renderColumn.call(self, td, templateTD);
+
+ $("a", td).click(function(e) {
+ e.preventDefault();
+ self.table.open(self);
+ });
+ }
+});
+
+var GroupPage = EntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ GroupPage.__super__.initialize.call(self, options);
+ },
+ setup: function() {
+ var self = this;
+
+ GroupPage.__super__.setup.call(self);
+
+ var dialog = self.$("#member-dialog");
+
+ var addDialog = new Dialog({
+ el: dialog,
+ title: "Add Member",
+ readonly: ["groupID"],
+ actions: ["cancel", "add"]
+ });
+
+ var editDialog = new Dialog({
+ el: dialog,
+ title: "Member",
+ readonly: ["groupID", "memberID"],
+ actions: ["close"]
+ });
+
+ self.membersTable = new ModelTable({
+ el: self.$("table[name='members']"),
+ pageSize: 10,
+ addDialog: addDialog,
+ editDialog: editDialog,
+ tableItem: GroupMembersTableItem,
+ parent: self
+ });
+ },
+ renderContent: function() {
+ var self = this;
+
+ GroupPage.__super__.renderContent.call(self);
+
+ // Since the members table is backed by a REST resource any
+ // changes will be executed immediately even if the page is
+ // in view mode. To avoid confusion, the members table will
+ // be disabled in page edit mode.
+ if (self.mode == "edit") {
+ // In page edit mode, the members tables is read-only.
+ self.membersTable.mode = "view";
+
+ self.membersTable.collection = new GroupMemberCollection(null, { groupID: self.entry.id });
+
+ } else if (self.mode == "add") {
+ // In page add mode, the members table is read-only.
+ self.membersTable.mode = "view";
+
+ // self.membersTable.collection is undefined for new group
+
+ } else { // self.mode == "view"
+ // In page view mode, the members table is editable.
+ self.membersTable.mode = "edit";
+
+ self.membersTable.collection = new GroupMemberCollection(null, { groupID: self.entry.id });
+ }
+
+ self.membersTable.render();
+ }
+});
+
+var GroupsTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ GroupsTable.__super__.initialize.call(self, options);
+ },
+ add: function() {
+ var self = this;
+
+ window.location.hash = "#new-group";
+ }
+});
+
+var GroupsPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new GroupsTable({
+ el: $("table[name='groups']"),
+ collection: new GroupCollection()
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/profile-mapping.js b/base/tps/shared/webapps/tps/js/profile-mapping.js
new file mode 100644
index 000000000..54c042562
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/profile-mapping.js
@@ -0,0 +1,109 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var ProfileMappingModel = Model.extend({
+ urlRoot: "/tps/rest/profile-mappings",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ profileMappingID: response.id,
+ status: response.Status,
+ properties: response.Properties.Property
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: attributes.profileMappingID,
+ Status: attributes.status,
+ Properties: {
+ Property: attributes.properties
+ }
+ };
+ },
+ enable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=enable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ },
+ disable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=disable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ }
+});
+
+var ProfileMappingCollection = Collection.extend({
+ urlRoot: "/tps/rest/profile-mappings",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new ProfileMappingModel({
+ id: entry.id,
+ status: entry.Status
+ });
+ }
+});
+
+var ProfileMappingsTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ ProfileMappingsTable.__super__.initialize.call(self, options);
+ },
+ add: function() {
+ var self = this;
+
+ window.location.hash = "#new-profile-mapping";
+ }
+});
+
+var ProfileMappingsPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new ProfileMappingsTable({
+ el: $("table[name='profile-mappings']"),
+ collection: new ProfileMappingCollection(),
+ parent: self
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/profile.js b/base/tps/shared/webapps/tps/js/profile.js
new file mode 100644
index 000000000..0454686a9
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/profile.js
@@ -0,0 +1,109 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var ProfileModel = Model.extend({
+ urlRoot: "/tps/rest/profiles",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ profileID: response.id,
+ status: response.Status,
+ properties: response.Properties.Property
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: attributes.profileID,
+ Status: attributes.status,
+ Properties: {
+ Property: attributes.properties
+ }
+ };
+ },
+ enable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=enable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ },
+ disable: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?action=disable",
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ }
+});
+
+var ProfileCollection = Collection.extend({
+ urlRoot: "/tps/rest/profiles",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new ProfileModel({
+ id: entry.id,
+ status: entry.Status
+ });
+ }
+});
+
+var ProfilesTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ ProfilesTable.__super__.initialize.call(self, options);
+ },
+ add: function() {
+ var self = this;
+
+ window.location.hash = "#new-profile";
+ }
+});
+
+var ProfilesPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new ProfilesTable({
+ el: $("table[name='profiles']"),
+ collection: new ProfileCollection(),
+ parent: self
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/selftest.js b/base/tps/shared/webapps/tps/js/selftest.js
new file mode 100644
index 000000000..d28907817
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/selftest.js
@@ -0,0 +1,88 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var SelfTestModel = Model.extend({
+ urlRoot: "/tps/rest/selftests",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ enabledAtStartup: response.EnabledAtStartup,
+ criticalAtStartup: response.CriticalAtStartup,
+ enabledOnDemand: response.EnabledOnDemand,
+ criticalOnDemand: response.CriticalOnDemand,
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: attributes.id,
+ EnabledAtStartup: attributes.enabledAtStartup,
+ CriticalAtStartup: attributes.criticalAtStartup,
+ EnabledOnDemand: attributes.enabledOnDemand,
+ CriticalOnDemand: attributes.criticalOnDemand
+ };
+ }
+});
+
+var SelfTestCollection = Collection.extend({
+ urlRoot: "/tps/rest/selftests",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new SelfTestModel({
+ id: entry.id,
+ enabledAtStartup: entry.EnabledAtStartup,
+ criticalAtStartup: entry.CriticalAtStartup,
+ enabledOnDemand: entry.EnabledOnDemand,
+ criticalOnDemand: entry.CriticalOnDemand,
+ });
+ }
+});
+
+var SelfTestPage = EntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ SelfTestPage.__super__.initialize.call(self, options);
+ }
+});
+
+var SelfTestsTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ SelfTestsTable.__super__.initialize.call(self, options);
+ }
+});
+
+var SelfTestsPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new SelfTestsTable({
+ el: $("table[name='selftests']"),
+ collection: new SelfTestCollection()
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/token.js b/base/tps/shared/webapps/tps/js/token.js
new file mode 100644
index 000000000..2ea17714e
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/token.js
@@ -0,0 +1,258 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var TokenStatus = {
+ UNINITIALIZED: "Uninitialized",
+ ACTIVE: "Active",
+ TEMP_LOST: "Temporarily lost",
+ PERM_LOST: "Permanently lost",
+ DAMAGED: "Physically damaged",
+ TERMINATED: "Terminated"
+};
+
+var TokenModel = Model.extend({
+ urlRoot: "/tps/rest/tokens",
+ parseResponse: function(response) {
+ return {
+ id: response.id,
+ tokenID: response.TokenID,
+ userID: response.UserID,
+ type: response.Type,
+ status: response.Status,
+ statusLabel: TokenStatus[response.Status],
+ appletID: response.AppletID,
+ keyInfo: response.KeyInfo,
+ policy: response.Policy,
+ createTimestamp: response.CreateTimestamp,
+ modifyTimestamp: response.ModifyTimestamp
+ };
+ },
+ createRequest: function(attributes) {
+ return {
+ id: this.id,
+ TokenID: attributes.tokenID,
+ UserID: attributes.userID,
+ Type: attributes.type,
+ Status: attributes.status,
+ AppletID: attributes.appletID,
+ KeyInfo: attributes.keyInfo,
+ Policy: attributes.policy,
+ CreateTimestamp: attributes.createTimestamp,
+ ModifyTimestamp: attributes.modifyTimestamp
+ };
+ },
+ changeStatus: function(options) {
+ var self = this;
+ $.ajax({
+ type: "POST",
+ url: self.url() + "?status=" + options.status,
+ dataType: "json"
+ }).done(function(data, textStatus, jqXHR) {
+ self.set(self.parseResponse(data));
+ if (options.success) options.success.call(self, data, textStatus, jqXHR);
+ }).fail(function(jqXHR, textStatus, errorThrown) {
+ if (options.error) options.error.call(self, jqXHR, textStatus, errorThrown);
+ });
+ }
+});
+
+var TokenCollection = Collection.extend({
+ model: TokenModel,
+ urlRoot: "/tps/rest/tokens",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new TokenModel({
+ id: entry.id,
+ tokenID: entry.TokenID,
+ userID: entry.UserID,
+ type: entry.Type,
+ status: entry.Status,
+ statusLabel: TokenStatus[entry.Status],
+ appletID: entry.AppletID,
+ keyInfo: entry.KeyInfo,
+ policy: entry.Policy,
+ createTimestamp: entry.CreateTimestamp,
+ modifyTimestamp: entry.ModifyTimestamp
+ });
+ }
+});
+
+var TokenPage = EntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ TokenPage.__super__.initialize.call(self, options);
+ },
+ setup: function() {
+ var self = this;
+
+ TokenPage.__super__.setup.call(self);
+
+ self.changeStatusLink = $("a[name='changeStatus']", self.menu);
+
+ self.changeStatusLink.click(function(e) {
+
+ e.preventDefault();
+
+ var dialog = new Dialog({
+ el: $("#token-status-dialog"),
+ title: "Change Token Status",
+ readonly: ["tokenID"],
+ actions: ["cancel", "save"]
+ });
+
+ dialog.entry = _.clone(self.model.attributes);
+
+ dialog.handler("save", function() {
+
+ // save changes
+ dialog.save();
+
+ // check if the status was changed
+ if (dialog.entry.status != self.model.attributes.status) {
+
+ self.model.changeStatus({
+ status: dialog.entry.status,
+ success: function(data, textStatus, jqXHR) {
+ self.render();
+ },
+ error: function(jqXHR, textStatus, errorThrow) {
+ new ErrorDialog({
+ el: $("#error-dialog"),
+ title: "HTTP Error " + jqXHR.responseJSON.Code,
+ content: jqXHR.responseJSON.Message
+ }).open();
+ }
+ });
+ }
+
+ dialog.close();
+ });
+
+ dialog.open();
+ });
+ },
+ renderContent: function() {
+ var self = this;
+
+ TokenPage.__super__.renderContent.call(self);
+
+ if (self.mode == "add") {
+ self.changeStatusLink.hide();
+ } else {
+ self.changeStatusLink.show();
+ }
+ }
+});
+
+var TokenTableItem = TableItem.extend({
+ initialize: function(options) {
+ var self = this;
+ TokenTableItem.__super__.initialize.call(self, options);
+ },
+ renderColumn: function(td, templateTD) {
+ var self = this;
+
+ TokenTableItem.__super__.renderColumn.call(self, td, templateTD);
+
+ var name = td.attr("name");
+ if (name == "status") {
+ $("a", td).click(function(e) {
+ e.preventDefault();
+ self.editStatus();
+ });
+ }
+ },
+ editStatus: function() {
+ var self = this;
+
+ var model = self.table.collection.get(self.entry.id);
+
+ var dialog = new Dialog({
+ el: $("#token-status-dialog"),
+ title: "Change Token Status",
+ readonly: ["tokenID", "userID", "type",
+ "appletID", "keyInfo", "policy",
+ "createTimestamp", "modifyTimestamp"],
+ actions: ["cancel", "save"]
+ });
+
+ dialog.entry = _.clone(model.attributes);
+
+ dialog.handler("save", function() {
+
+ // save changes
+ dialog.save();
+
+ // check if the status was changed
+ if (dialog.entry.status != model.attributes.status) {
+
+ model.changeStatus({
+ status: dialog.entry.status,
+ success: function(data, textStatus, jqXHR) {
+ self.table.render();
+ },
+ error: function(jqXHR, textStatus, errorThrow) {
+ new ErrorDialog({
+ el: $("#error-dialog"),
+ title: "HTTP Error " + jqXHR.responseJSON.Code,
+ content: jqXHR.responseJSON.Message
+ }).open();
+ }
+ });
+ }
+
+ dialog.close();
+ });
+
+ dialog.open();
+ }
+});
+
+var TokensTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ options.tableItem = TokenTableItem;
+ TokensTable.__super__.initialize.call(self, options);
+ },
+ add: function() {
+ var self = this;
+
+ window.location.hash = "#new-token";
+ }
+});
+
+var TokensPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new TokensTable({
+ el: $("table[name='tokens']"),
+ collection: new TokenCollection()
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/tps.js b/base/tps/shared/webapps/tps/js/tps.js
new file mode 100644
index 000000000..476533759
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/tps.js
@@ -0,0 +1,231 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var PropertiesTableItem = TableItem.extend({
+ initialize: function(options) {
+ var self = this;
+ PropertiesTableItem.__super__.initialize.call(self, options);
+ },
+ get: function(name) {
+ var self = this;
+
+ if (name.substring(0, 7) == "parent.") {
+ name = name.substring(7);
+ return self.table.parent.entry[name];
+ }
+
+ return PropertiesTableItem.__super__.get.call(self, name);
+ },
+ renderColumn: function(td, templateTD) {
+ var self = this;
+
+ PropertiesTableItem.__super__.renderColumn.call(self, td, templateTD);
+
+ $("a", td).click(function(e) {
+ e.preventDefault();
+ self.open();
+ });
+ },
+ open: function() {
+ var self = this;
+
+ var dialog;
+
+ if (self.table.mode == "view") {
+ // In view mode all properties are read-only.
+ dialog = new Dialog({
+ el: self.table.parent.$("#property-dialog"),
+ title: "Property",
+ readonly: ["name", "value"],
+ actions: ["close"]
+ });
+
+ } else {
+ // In edit mode all properties are editable.
+ dialog = new Dialog({
+ el: self.table.parent.$("#property-dialog"),
+ title: "Edit Property",
+ readonly: ["name"],
+ actions: ["cancel", "save"]
+ });
+
+ dialog.handler("save", function() {
+
+ // save changes
+ dialog.save();
+ _.extend(self.entry, dialog.entry);
+
+ // redraw table
+ self.table.render();
+ dialog.close();
+ });
+ }
+
+ dialog.entry = _.clone(self.entry);
+
+ dialog.open();
+ }
+});
+
+var PropertiesTable = Table.extend({
+ initialize: function(options) {
+ var self = this;
+ options.columnMappings = {
+ id: "name"
+ };
+ PropertiesTable.__super__.initialize.call(self, options);
+ },
+ sort: function() {
+ var self = this;
+
+ // sort properties by name
+ self.filteredEntries = _.sortBy(self.filteredEntries, function(entry) {
+ return entry.name;
+ });
+ },
+ remove: function(items) {
+ var self = this;
+
+ // remove selected entries
+ self.entries = _.reject(self.entries, function(entry) {
+ return _.contains(items, entry.name);
+ });
+
+ // redraw table
+ self.render();
+ }
+});
+
+var ConfigEntryPage = EntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ ConfigEntryPage.__super__.initialize.call(self, options);
+ self.tableItem = options.tableItem || PropertiesTableItem;
+ self.tableSize = options.tableSize || 10;
+ },
+ setup: function() {
+ var self = this;
+
+ ConfigEntryPage.__super__.setup.call(self);
+
+ self.enableLink = $("a[name='enable']", self.menu);
+ self.disableLink = $("a[name='disable']", self.menu);
+
+ self.enableLink.click(function(e) {
+
+ e.preventDefault();
+
+ var message = "Are you sure you want to enable this entry?";
+ if (!confirm(message)) return;
+ self.model.enable({
+ success: function(data, textStatus, jqXHR) {
+ self.entry = _.clone(self.model.attributes);
+ self.render();
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ new ErrorDialog({
+ el: $("#error-dialog"),
+ title: "HTTP Error " + jqXHR.responseJSON.Code,
+ content: jqXHR.responseJSON.Message
+ }).open();
+ }
+ });
+ });
+
+ self.disableLink.click(function(e) {
+
+ e.preventDefault();
+
+ var message = "Are you sure you want to disable this entry?";
+ if (!confirm(message)) return;
+ self.model.disable({
+ success: function(data, textStatus, jqXHR) {
+ self.entry = _.clone(self.model.attributes);
+ self.render();
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ new ErrorDialog({
+ el: $("#error-dialog"),
+ title: "HTTP Error " + jqXHR.responseJSON.Code,
+ content: jqXHR.responseJSON.Message
+ }).open();
+ }
+ });
+ });
+
+ var dialog = self.$("#property-dialog");
+
+ var addDialog = new Dialog({
+ el: dialog,
+ title: "Add Property",
+ actions: ["cancel", "add"]
+ });
+
+ var table = self.$("table[name='properties']");
+ self.addButton = $("button[name='add']", table);
+ self.removeButton = $("button[name='remove']", table);
+
+ self.propertiesTable = new PropertiesTable({
+ el: table,
+ addDialog: addDialog,
+ tableItem: self.tableItem,
+ pageSize: self.tableSize,
+ parent: self
+ });
+ },
+ renderContent: function() {
+ var self = this;
+
+ ConfigEntryPage.__super__.renderContent.call(self);
+
+ var status = self.entry.status;
+ if (status == "Disabled") {
+ self.enableLink.show();
+ self.disableLink.hide();
+
+ } else if (status == "Enabled") {
+ self.enableLink.hide();
+ self.disableLink.show();
+ }
+
+ if (self.mode == "add") {
+ self.propertiesTable.mode = "edit";
+ self.propertiesTable.entries = [];
+
+ } else if (self.mode == "edit") {
+ self.propertiesTable.mode = "edit";
+ self.propertiesTable.entries = self.entry.properties;
+
+ } else { // self.mode == "view"
+ self.propertiesTable.mode = "view";
+ self.propertiesTable.entries = self.entry.properties;
+ }
+
+ self.propertiesTable.render();
+ },
+ saveFields: function() {
+ var self = this;
+
+ ConfigEntryPage.__super__.saveFields.call(self);
+
+ self.entry.properties = self.propertiesTable.entries;
+ }
+});
diff --git a/base/tps/shared/webapps/tps/js/user.js b/base/tps/shared/webapps/tps/js/user.js
new file mode 100644
index 000000000..3a29f1dd1
--- /dev/null
+++ b/base/tps/shared/webapps/tps/js/user.js
@@ -0,0 +1,150 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ *
+ * @author Endi S. Dewata
+ */
+
+var UserModel = Model.extend({
+ urlRoot: "/tps/rest/admin/users",
+ parseResponse: function(response) {
+
+ var attrs = {};
+ if (response.Attributes) {
+ var attributes = response.Attributes.Attribute;
+ attributes = attributes == undefined ? [] : [].concat(attributes);
+
+ _(attributes).each(function(attribute) {
+ var name = attribute.name;
+ var value = attribute.value;
+ attrs[name] = value;
+ });
+ }
+
+ return {
+ id: response.id,
+ userID: response.UserID,
+ fullName: response.FullName,
+ email: response.Email,
+ state: response.State,
+ type: response.Type,
+ attributes: attrs
+ };
+ },
+ createRequest: function(attributes) {
+ var attrs = [];
+ _(attributes.attributes).each(function(value, name) {
+ attrs.push({
+ name: name,
+ value: value
+ });
+ });
+
+ return {
+ id: this.id,
+ UserID: attributes.userID,
+ FullName: attributes.fullName,
+ Email: attributes.email,
+ State: attributes.state,
+ Type: attributes.type,
+ Attributes: {
+ Attribute: attrs
+ }
+ };
+ }
+});
+
+var UserCollection = Collection.extend({
+ model: UserModel,
+ urlRoot: "/tps/rest/admin/users",
+ getEntries: function(response) {
+ return response.entries;
+ },
+ getLinks: function(response) {
+ return response.Link;
+ },
+ parseEntry: function(entry) {
+ return new UserModel({
+ id: entry.id,
+ userID: entry.UserID,
+ fullName: entry.FullName
+ });
+ }
+});
+
+var UserPage = EntryPage.extend({
+ initialize: function(options) {
+ var self = this;
+ UserPage.__super__.initialize.call(self, options);
+ },
+ loadField: function(input) {
+ var self = this;
+
+ var name = input.attr("name");
+ if (name != "tpsProfiles") {
+ UserPage.__super__.loadField.call(self, input);
+ return;
+ }
+
+ var attributes = self.entry.attributes;
+ if (attributes) {
+ var value = attributes.tpsProfiles;
+ input.val(value);
+ }
+ },
+ saveField: function(input) {
+ var self = this;
+
+ var name = input.attr("name");
+ if (name != "tpsProfiles") {
+ UserPage.__super__.saveField.call(self, input);
+ return;
+ }
+
+ var attributes = self.entry.attributes;
+ if (attributes == undefined) {
+ attributes = {};
+ self.entry.attributes = attributes;
+ }
+ attributes.tpsProfiles = input.val();
+ }
+});
+
+var UsersTable = ModelTable.extend({
+ initialize: function(options) {
+ var self = this;
+ UsersTable.__super__.initialize.call(self, options);
+ },
+ add: function() {
+ var self = this;
+
+ window.location.hash = "#new-user";
+ }
+});
+
+var UsersPage = Page.extend({
+ load: function() {
+ var self = this;
+
+ var table = new UsersTable({
+ el: $("table[name='users']"),
+ collection: new UserCollection()
+ });
+
+ table.render();
+ }
+});
diff --git a/base/tps/shared/webapps/tps/services.template b/base/tps/shared/webapps/tps/services.template
new file mode 100644
index 000000000..c6792fea1
--- /dev/null
+++ b/base/tps/shared/webapps/tps/services.template
@@ -0,0 +1,106 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2007 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<CMS_TEMPLATE>
+<title>TKS Services</title>
+ <link rel="shortcut icon" href="/pki/images/favicon.ico" />
+ <link rel="stylesheet" href="/pki/css/pki-base.css" type="text/css" />
+ <META http-equiv=Content-Type content="text/html; charset=UTF-8">
+
+</head>
+<body bgcolor="#FFFFFF" link="#666699" vlink="#666699" alink="#333366">
+
+<div id="header">
+ <a href="http://pki.fedoraproject.org/" title="Visit pki.fedoraproject.org for more information about Dogtag products and services"><img src="/pki/images/logo_header.gif" alt="Dogtag" id="myLogo" /></a>
+ <div id="headertitle">
+ <a href="/" title="Dogtag Network homepage">Dogtag<sup><font size="-2">&reg;</font></sup> Certificate System</a>
+ </div>
+ <div id="account">
+ <dl><dt><span></span></dt><dd></dd></dl>
+ </div>
+</div>
+
+<div id="mainNavOuter">
+<div id="mainNav">
+<div id="mainNavInner">
+
+</div><!-- end mainNavInner -->
+</div><!-- end mainNav -->
+</div><!-- end mainNavOuter -->
+
+
+<div id="bar">
+
+<div id="systembar">
+<div id="systembarinner">
+
+<div>
+ -
+</div>
+
+
+</div>
+</div>
+
+</div>
+
+
+<font size="+1" face="PrimaSans BT, Verdana, Arial, Helvetica, sans-serif">
+Certificate System TKS Services Page
+</font><br>
+<p>
+</font>
+<p>
+<center>
+<table border="0" cellspacing="0" cellpadding="0">
+<tr valign="TOP">
+<td>&nbsp;</td>
+<td>&nbsp;</td>
+</tr>
+<script language=javascript>
+for (var i=0; i<result.recordSet.length; ++i) {
+ document.write('<tr valign="TOP">');
+ document.write('<td>');
+ document.write('<td>');
+ document.write('<font size=4 face="PrimaSans BT, Verdana, sans-serif">');
+ document.write('<li><a href="');
+ document.write(result.recordSet[i].prefix + "://" +
+ result.recordSet[i].host + ":" + result.recordSet[i].port + "/"+
+ result.recordSet[i].uri);
+ if (result.recordSet[i].type == "admin") {
+ document.write('">Admin Services</a></font>');
+ } else if (result.recordSet[i].type == "agent") {
+ document.write('">Agent Services</a></font>');
+ } else if (result.recordSet[i].type == "ee") {
+ document.write('">SSL End Users Services</a></font>');
+ }
+
+ document.write('</font></td></tr>');
+}
+</script>
+<tr valign="TOP">
+<td>&nbsp;</td>
+<td>&nbsp;</td>
+</tr>
+</table>
+</center>
+<div id="footer">
+</div>
+</body>
+</html>
diff --git a/base/tps/shared/webapps/tps/ui/activities.html b/base/tps/shared/webapps/tps/ui/activities.html
new file mode 100644
index 000000000..0762401fd
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/activities.html
@@ -0,0 +1,83 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Activities</strong></li>
+</ol>
+
+<span class="pki-title">Activities</span>
+</div>
+
+<table name="activities">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="8">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="activity_selectall" type="checkbox"><label for="activity_selectall">&nbsp;</label></th>
+ <th>Activity ID</th>
+ <th>Token ID</th>
+ <th>User ID</th>
+ <th>IP</th>
+ <th>Operation</th>
+ <th>Result</th>
+ <th>Date</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="activity_select" type="checkbox"><label for="activity_select">&nbsp;</label></td>
+ <td name="id"><a href="#activities/${id}">${id}</a></td>
+ <td name="tokenID">${tokenID}</td>
+ <td name="userID">${userID}</td>
+ <td name="ip">${ip}</td>
+ <td name="operation">${operation}</td>
+ <td name="result">${result}</td>
+ <td name="date">${date}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="8">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/shared/webapps/tps/ui/activity.html b/base/tps/shared/webapps/tps/ui/activity.html
new file mode 100644
index 000000000..5ba96a4e1
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/activity.html
@@ -0,0 +1,47 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#activities">Activities</a></li>
+ <li class="active"><strong><span name="title">Activity ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Activity ${id}</span>
+</div>
+
+<div name="activity" class="pki-fields">
+<fieldset>
+ <label>Activity ID</label>
+ <input name="id" readonly="readonly"><br>
+ <label>Token ID</label>
+ <input name="tokenID" readonly="readonly"><br>
+ <label>User ID</label>
+ <input name="userID" readonly="readonly"><br>
+ <label>IP</label>
+ <input name="ip" readonly="readonly"><br>
+ <label>operation</label>
+ <input name="operation" readonly="readonly"><br>
+ <label>Result</label>
+ <input name="result" readonly="readonly"><br>
+ <label>Date</label>
+ <input name="date" readonly="readonly"><br>
+ <label>Message</label>
+ <input name="message" readonly="readonly"><br>
+</fieldset>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/audit.html b/base/tps/shared/webapps/tps/ui/audit.html
new file mode 100644
index 000000000..3e6cc6cbb
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/audit.html
@@ -0,0 +1,134 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Audit Logging</strong></li>
+</ol>
+
+<span class="pki-title">Audit Logging</span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+<a name="enable" href="#">Enable</a><a name="disable" href="#" style="display: none;">Disable</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<div name="audit" class="pki-fields">
+<fieldset>
+ <label>Status</label>
+ <input name="status" readonly="readonly">
+ <br>
+ <label>Signed</label>
+ <input name="signed" readonly="readonly">
+ <br>
+ <label>Interval</label>
+ <input name="interval" readonly="readonly">
+ <br>
+ <label>Buffer Size</label>
+ <input name="bufferSize" readonly="readonly">
+ <br>
+</fieldset>
+</div>
+
+<h2>Events</h2>
+
+<table name="events">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons" style="display: none;">
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="events_selectall" type="checkbox"><label for="events_selectall">&nbsp;</label></th>
+ <th class="pki-property-name-column">Name</th>
+ <th>Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="events_select" type="checkbox"><label for="events_select">&nbsp;</label></td>
+ <td name="id" class="pki-property-name-column"><a href="/tps/ui/audit/events/${id}">${id}</a></td>
+ <td name="value">${value}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
+
+<div id="event-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Edit Event</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Name</label>
+ <input name="name" readonly="readonly"><br>
+ <label>Value</label>
+ <input name="value" readonly="readonly"><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="add" class="btn btn-primary">Add</button>
+ <button name="save" class="btn btn-primary">Save</button>
+ <button name="close" class="btn btn-primary">Close</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/authenticator.html b/base/tps/shared/webapps/tps/ui/authenticator.html
new file mode 100644
index 000000000..6da1fbf12
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/authenticator.html
@@ -0,0 +1,131 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#authenticators">Authentication Sources</a></li>
+ <li class="active"><strong><span name="title">Authentication Source ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Authentication Source ${id}</span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+<a name="enable" href="#">Enable</a><a name="disable" href="#" style="display: none;">Disable</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<div name="authenticator" class="pki-fields">
+<fieldset>
+ <label>Source ID</label>
+ <input name="authenticatorID" readonly="readonly">
+ <br>
+ <label>Status</label>
+ <input name="status" readonly="readonly">
+ <br>
+</fieldset>
+</div>
+
+<h2>Properties</h2>
+
+<table name="properties">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons" style="display: none;">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="authenticator_selectall" type="checkbox"><label for="authenticator_selectall">&nbsp;</label></th>
+ <th class="pki-property-name-column">Name</th>
+ <th>Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="authenticator_select" type="checkbox"><label for="authenticator_select">&nbsp;</label></td>
+ <td name="id" class="pki-property-name-column"><a href="/tps/ui/authenticators/${parent.id}/properties/${id}">${id}</a></td>
+ <td name="value">${value}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
+
+<div id="property-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Edit Property</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Name</label>
+ <input name="name" readonly="readonly"><br>
+ <label>Value</label>
+ <input name="value" readonly="readonly"><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="add" class="btn btn-primary">Add</button>
+ <button name="save" class="btn btn-primary">Save</button>
+ <button name="close" class="btn btn-primary">Close</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/authenticators.html b/base/tps/shared/webapps/tps/ui/authenticators.html
new file mode 100644
index 000000000..f9b0b0a28
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/authenticators.html
@@ -0,0 +1,74 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Authentication Sources</strong></li>
+</ol>
+<span class="pki-title">Authentication Sources</span>
+</div>
+
+<table name="authenticators">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="authenticator_selectall" type="checkbox"><label for="authenticator_selectall">&nbsp;</label></th>
+ <th>Source ID</th>
+ <th>Status</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="authenticator_select" type="checkbox"><label for="authenticator_select">&nbsp;</label></td>
+ <td name="id"><a href="#authenticators/${id}">${id}</a></td>
+ <td name="status">${status}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/shared/webapps/tps/ui/cert.html b/base/tps/shared/webapps/tps/ui/cert.html
new file mode 100644
index 000000000..456f23355
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/cert.html
@@ -0,0 +1,49 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#certs">Certificates</a></li>
+ <li class="active"><strong><span name="title">Certificate ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Certificate ${id}</span>
+</div>
+
+<div name="certificate" class="pki-fields">
+<fieldset>
+ <label>Certificate ID</label>
+ <input name="id" readonly="readonly"><br>
+ <label>Serial Number</label>
+ <input name="serialNumber" readonly="readonly"><br>
+ <label>Subject</label>
+ <input name="subject" readonly="readonly"><br>
+ <label>Token ID</label>
+ <input name="tokenID" readonly="readonly"><br>
+ <label>User ID</label>
+ <input name="userID" readonly="readonly"><br>
+ <label>Key Type</label>
+ <input name="keyType" readonly="readonly"><br>
+ <label>Status</label>
+ <input name="status" readonly="readonly"><br>
+ <label>Created</label>
+ <input name="createTime" readonly="readonly"><br>
+ <label>Modified</label>
+ <input name="modifyTime" readonly="readonly"><br>
+</fieldset>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/certs.html b/base/tps/shared/webapps/tps/ui/certs.html
new file mode 100644
index 000000000..a87c2dd32
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/certs.html
@@ -0,0 +1,87 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Certificates</strong></li>
+</ol>
+
+<span class="pki-title">Certificates</span>
+</div>
+
+<table name="certificates">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="10">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="cert_selectall" type="checkbox"><label for="cert_selectall">&nbsp;</label></tdh>
+ <th>Certificate ID</th>
+ <th>Serial Number</th>
+ <th>Subject</th>
+ <th>Token ID</th>
+ <th>User ID</th>
+ <th>Key Type</th>
+ <th>Status</th>
+ <th>Create Time</th>
+ <th>Modify Time</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="cert_select" type="checkbox"><label for="cert_select">&nbsp;</label></td>
+ <td name="id"><a href="#certs/${id}">${id}</a></td>
+ <td name="serialNumber">${serialNumber}</td>
+ <td name="subject">${subject}</td>
+ <td name="tokenID">${tokenID}</td>
+ <td name="userID">${userID}</td>
+ <td name="keyType">${keyType}</td>
+ <td name="status">${status}</td>
+ <td name="createTime">${createTime}</td>
+ <td name="modifyTime">${modifyTime}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="10">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/shared/webapps/tps/ui/config.html b/base/tps/shared/webapps/tps/ui/config.html
new file mode 100644
index 000000000..d94a0fa28
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/config.html
@@ -0,0 +1,116 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>General Configuration</strong></li>
+</ol>
+
+<span class="pki-title">General Configuration</span></span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<table name="properties">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons" style="display: none;">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="properties_selectall" type="checkbox"><label for="properties_selectall">&nbsp;</label></th>
+ <th class="pki-property-name-column">Name</th>
+ <th>Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="properties_select" type="checkbox"><label for="properties_select">&nbsp;</label></td>
+ <td name="id" class="pki-property-name-column"><a href="/tps/ui/config/properties/${id}">${id}</a></td>
+ <td name="value">${value}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
+
+<div id="property-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Edit Property</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Name</label>
+ <input name="name" readonly="readonly"><br>
+ <label>Value</label>
+ <input name="value" readonly="readonly"><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="add" class="btn btn-primary">Add</button>
+ <button name="save" class="btn btn-primary">Save</button>
+ <button name="close" class="btn btn-primary">Close</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/connector.html b/base/tps/shared/webapps/tps/ui/connector.html
new file mode 100644
index 000000000..015a7ac6d
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/connector.html
@@ -0,0 +1,131 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#connectors">Subsystem Connections</a></li>
+ <li class="active"><strong><span name="title">Subsystem Connection ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Subsystem Connection ${id}</span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+<a name="enable" href="#">Enable</a><a name="disable" href="#" style="display: none;">Disable</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<div name="connector" class="pki-fields">
+<fieldset>
+ <label>Connector ID</label>
+ <input name="connectorID" readonly="readonly">
+ <br>
+ <label>Status</label>
+ <input name="status" readonly="readonly">
+ <br>
+</fieldset>
+</div>
+
+<h2>Properties</h2>
+
+<table name="properties">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons" style="display: none;">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="connector_selectall" type="checkbox"><label for="connector_selectall">&nbsp;</label></th>
+ <th class="pki-property-name-column">Name</th>
+ <th>Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="connector_select" type="checkbox"><label for="connector_select">&nbsp;</label></td>
+ <td name="id" class="pki-property-name-column"><a href="/tps/ui/connectors/${parent.id}/properties/${id}">${id}</a></td>
+ <td name="value">${value}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
+
+<div id="property-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Edit Property</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Name</label>
+ <input name="name" readonly="readonly"><br>
+ <label>Value</label>
+ <input name="value" readonly="readonly"><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="add" class="btn btn-primary">Add</button>
+ <button name="save" class="btn btn-primary">Save</button>
+ <button name="close" class="btn btn-primary">Close</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/connectors.html b/base/tps/shared/webapps/tps/ui/connectors.html
new file mode 100644
index 000000000..4d4d59772
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/connectors.html
@@ -0,0 +1,75 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Subsystem Connections</strong></li>
+</ol>
+
+<span class="pki-title">Subsystem Connections</span>
+</div>
+
+<table name="connectors">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="connector_selectall" type="checkbox"><label for="connector_selectall">&nbsp;</label></th>
+ <th>Connector ID</th>
+ <th>Status</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="connector_select" type="checkbox"><label for="connector_select">&nbsp;</label></td>
+ <td name="id"><a href="#connectors/${id}">${id}</a></td>
+ <td name="status">${status}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/shared/webapps/tps/ui/group.html b/base/tps/shared/webapps/tps/ui/group.html
new file mode 100644
index 000000000..493b79488
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/group.html
@@ -0,0 +1,125 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#groups">Groups</a></li>
+ <li class="active"><strong><span name="title">Group ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Group ${id}</span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<div name="group" class="pki-fields">
+<fieldset>
+ <label>Group ID</label>
+ <input name="groupID" readonly="readonly"><br>
+ <label>Description</label>
+ <input name="description" readonly="readonly"><br>
+</fieldset>
+</div>
+
+<h2>Members</h2>
+
+<table name="members">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="2">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="members_selectall" type="checkbox"><label for="members_selectall">&nbsp;</label></th>
+ <th>User ID</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="members_select" type="checkbox"><label for="members_select">&nbsp;</label></td>
+ <td name="id">${id}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="2">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
+
+<div id="member-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Group Member</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Group ID</label>
+ <input name="groupID" readonly="readonly"><br>
+ <label>User ID</label>
+ <input name="memberID" readonly="readonly"><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="add" class="btn btn-primary">Add</button>
+ <button name="close" class="btn btn-primary">Close</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/groups.html b/base/tps/shared/webapps/tps/ui/groups.html
new file mode 100644
index 000000000..9f4239db8
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/groups.html
@@ -0,0 +1,75 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Groups</strong></li>
+</ol>
+
+<span class="pki-title">Groups</span>
+</div>
+
+<table name="groups">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="group_selectall" type="checkbox"><label for="group_selectall">&nbsp;</label></th>
+ <th>Group ID</th>
+ <th>Description</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="group_select" type="checkbox"><label for="group_select">&nbsp;</label></td>
+ <td name="id"><a href="#groups/${id}">${id}</a></td>
+ <td name="description">${description}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/shared/webapps/tps/ui/home.html b/base/tps/shared/webapps/tps/ui/home.html
new file mode 100644
index 000000000..8502ca448
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/home.html
@@ -0,0 +1,60 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+</ol>
+
+<span name="title" class="pki-title">Token Processing Service</span>
+</div>
+
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title">Token Management</h3>
+ </div>
+ <div class="panel-body">
+ <a href="#tokens">Tokens</a><br>
+ <a href="#certs">Certificates</a><br>
+ <a href="#activities">Activities</a><br>
+ </div>
+</div>
+
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title">Account Management</h3>
+ </div>
+ <div class="panel-body">
+ <a href="#users">Users</a><br>
+ <a href="#groups">Groups</a><br>
+ </div>
+</div>
+
+<div class="panel panel-default">
+ <div class="panel-heading">
+ <h3 class="panel-title">System Management</h3>
+ </div>
+ <div class="panel-body">
+ <a href="#config">General Configuration</a><br>
+ <a href="#authenticators">Authentication Sources</a><br>
+ <a href="#connections">Subsystem Connections</a><br>
+ <a href="#profiles">Profiles</a><br>
+ <a href="#profile-mappings">Profile Mappings</a><br>
+ <a href="#audit">Audit Logging</a><br>
+ <a href="#selftests">Self Tests</a><br>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/index.html b/base/tps/shared/webapps/tps/ui/index.html
new file mode 100644
index 000000000..eddceefd7
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/index.html
@@ -0,0 +1,429 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<html>
+<head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link href="/pki/css/patternfly.css" rel="stylesheet" media="screen, print">
+ <link href="/pki/css/pki-ui.css" rel="stylesheet" type="text/css">
+ <script src="/pki/js/jquery.js"></script>
+ <script src="/pki/js/underscore.js"></script>
+ <script src="/pki/js/backbone.js"></script>
+ <script src="/pki/js/bootstrap.js"></script>
+ <script src="/pki/js/patternfly.js"></script>
+ <script src="/pki/js/pki-ui.js"></script>
+ <script src="/tps/js/tps.js"></script>
+ <script src="/tps/js/account.js"></script>
+ <script src="/tps/js/activity.js"></script>
+ <script src="/tps/js/audit.js"></script>
+ <script src="/tps/js/authenticator.js"></script>
+ <script src="/tps/js/cert.js"></script>
+ <script src="/tps/js/config.js"></script>
+ <script src="/tps/js/connector.js"></script>
+ <script src="/tps/js/group.js"></script>
+ <script src="/tps/js/profile.js"></script>
+ <script src="/tps/js/profile-mapping.js"></script>
+ <script src="/tps/js/selftest.js"></script>
+ <script src="/tps/js/token.js"></script>
+ <script src="/tps/js/user.js"></script>
+ <script>
+$(function() {
+
+ var account = new Account();
+ account.login({
+ success: function(data, textStatus, jqXHR) {
+ var user = $("#user");
+ user.text(data.FullName);
+ },
+ error: function() {
+ window.location.href = "/tps";
+ }
+ });
+
+ var content = $("#content");
+
+ var router = new Backbone.Router();
+
+ router.route("", "home", function() {
+ new Page({
+ el: content,
+ url: "home.html"
+ }).open();
+ });
+
+ router.route("activities", "activities", function() {
+ new ActivitiesPage({
+ el: content,
+ url: "activities.html"
+ }).open();
+ });
+
+ router.route("activities/:id", "activity", function(id) {
+ new ActivityPage({
+ el: content,
+ url: "activity.html",
+ model: new ActivityModel({ id: id })
+ }).open();
+ });
+
+ router.route("audit", "audit", function() {
+ new AuditPage({
+ el: content,
+ url: "audit.html"
+ }).open();
+ });
+
+ router.route("authenticators", "authenticators", function() {
+ new AuthenticatorsPage({
+ el: content,
+ url: "authenticators.html"
+ }).open();
+ });
+
+ router.route("authenticators/:id", "authenticator", function(id) {
+ new ConfigEntryPage({
+ el: content,
+ url: "authenticator.html",
+ model: new AuthenticatorModel({ id: id })
+ }).open();
+ });
+
+ router.route("new-authenticator", "new-authenticator", function() {
+ new ConfigEntryPage({
+ el: content,
+ url: "authenticator.html",
+ model: new AuthenticatorModel(),
+ mode: "add",
+ title: "New Authenticator",
+ editable: ["authenticatorID"],
+ parentHash: "#authenticators"
+ }).open();
+ });
+
+ router.route("certs", "certs", function() {
+ new CertificatesPage({
+ el: content,
+ url: "certs.html"
+ }).open();
+ });
+
+ router.route("certs/:id", "cert", function(id) {
+ new CertificatePage({
+ el: content,
+ url: "cert.html",
+ model: new CertificateModel({ id: id })
+ }).open();
+ });
+
+ router.route("config", "config", function() {
+ new ConfigPage({
+ el: content,
+ url: "config.html"
+ }).open();
+ });
+
+ router.route("connectors", "connectors", function() {
+ new ConnectorsPage({
+ el: content,
+ url: "connectors.html"
+ }).open();
+ });
+
+ router.route("connectors/:id", "connector", function(id) {
+ new ConfigEntryPage({
+ el: content,
+ url: "connector.html",
+ model: new ConnectorModel({ id: id })
+ }).open();
+ });
+
+ router.route("new-connector", "new-connector", function() {
+ new ConfigEntryPage({
+ el: content,
+ url: "connector.html",
+ model: new ConnectorModel(),
+ mode: "add",
+ title: "New Connector",
+ editable: ["connectorID"],
+ parentHash: "#connectors"
+ }).open();
+ });
+
+ router.route("groups", "groups", function() {
+ new GroupsPage({
+ el: content,
+ url: "groups.html"
+ }).open();
+ });
+
+ router.route("groups/:id", "group", function(id) {
+ new GroupPage({
+ el: content,
+ url: "group.html",
+ model: new GroupModel({ id: id }),
+ editable: ["description"]
+ }).open();
+ });
+
+ router.route("new-group", "new-group", function() {
+ new GroupPage({
+ el: content,
+ url: "group.html",
+ model: new GroupModel(),
+ mode: "add",
+ title: "New Group",
+ editable: ["groupID", "description"],
+ parentHash: "#groups"
+ }).open();
+ });
+
+ router.route("profiles", "profiles", function() {
+ new ProfilesPage({
+ el: content,
+ url: "profiles.html"
+ }).open();
+ });
+
+ router.route("profiles/:id", "profile", function(id) {
+ new ConfigEntryPage({
+ el: content,
+ url: "profile.html",
+ model: new ProfileModel({ id: id })
+ }).open();
+ });
+
+ router.route("new-profile", "new-profile", function() {
+ new ConfigEntryPage({
+ el: content,
+ url: "profile.html",
+ model: new ProfileModel(),
+ mode: "add",
+ title: "New Profile",
+ editable: ["profileID"],
+ parentHash: "#profiles"
+ }).open();
+ });
+
+ router.route("profile-mappings", "profile-mappings", function() {
+ new ProfileMappingsPage({
+ el: content,
+ url: "profile-mappings.html"
+ }).open();
+ });
+
+ router.route("profile-mappings/:id", "profile-mapping", function(id) {
+ new ConfigEntryPage({
+ el: content,
+ url: "profile-mapping.html",
+ model: new ProfileMappingModel({ id: id }),
+ }).open();
+ });
+
+ router.route("new-profile-mapping", "new-profile-mapping", function() {
+ new ConfigEntryPage({
+ el: content,
+ url: "profile-mapping.html",
+ model: new ProfileMappingModel(),
+ mode: "add",
+ title: "New Profile Mapping",
+ editable: ["profileMappingID"],
+ parentHash: "#profile-mappings"
+ }).open();
+ });
+
+ router.route("selftests", "selftests", function() {
+ new SelfTestsPage({
+ el: content,
+ url: "selftests.html"
+ }).open();
+ });
+
+ router.route("selftests/:id", "selftest", function(id) {
+ new SelfTestPage({
+ el: content,
+ url: "selftest.html",
+ model: new SelfTestModel({ id: id })
+ }).open();
+ });
+
+ router.route("tokens", "tokens", function() {
+ new TokensPage({
+ el: content,
+ url: "tokens.html"
+ }).open();
+ });
+
+ router.route("tokens/:id", "token", function(id) {
+ new TokenPage({
+ el: content,
+ url: "token.html",
+ model: new TokenModel({ id: id }),
+ editable: ["userID", "type", "appletID", "keyInfo", "policy"]
+ }).open();
+ });
+
+ router.route("new-token", "new-token", function() {
+ new TokenPage({
+ el: content,
+ url: "token.html",
+ model: new TokenModel(),
+ mode: "add",
+ title: "New Token",
+ editable: ["tokenID", "userID", "type", "appletID", "keyInfo", "policy"],
+ parentHash: "#tokens"
+ }).open();
+ });
+
+ router.route("users", "users", function() {
+ new UsersPage({
+ el: content,
+ url: "users.html"
+ }).open();
+ });
+
+ router.route("users/:id", "user", function(id) {
+ new UserPage({
+ el: content,
+ url: "user.html",
+ model: new UserModel({ id: id }),
+ editable: ["fullName", "email", "tpsProfiles"]
+ }).open();
+ });
+
+ router.route("new-user", "new-user", function() {
+ new UserPage({
+ el: content,
+ url: "user.html",
+ model: new UserModel(),
+ mode: "add",
+ title: "New User",
+ editable: ["userID", "fullName", "email", "tpsProfiles"],
+ parentHash: "#users"
+ }).open();
+ });
+
+ router.route("logout", "logout", function() {
+ // destroy server session
+ account.logout({
+ success: function() {
+ // clear browser cache
+ PKI.logout({
+ success: function() {
+ window.location.href = "/tps";
+ },
+ error: function() {
+ alert("Logout failed. Please close the browser.");
+ }
+ });
+ },
+ error: function() {
+ alert("Logout failed. Please close the browser.");
+ }
+ });
+ });
+
+ Backbone.history.start();
+});
+ </script>
+</head>
+<body>
+
+<nav id="navigation" class="navbar navbar-default navbar-pf" role="navigation">
+<div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="navbar-brand" href="/tps">
+ <b>Token Processing Service</b>
+ </a>
+</div>
+<div class="collapse navbar-collapse navbar-collapse-1">
+ <ul class="nav navbar-nav navbar-utility">
+ <li><a href="#">Status</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+ <span class="pficon pficon-user"></span>
+ <span id="user"></span><b class="caret"></b>
+ </a>
+ <ul class="dropdown-menu">
+ <li><a href="#logout">Logout</a></li>
+ </ul>
+ </li>
+ </ul>
+ <ul class="nav navbar-nav navbar-primary">
+ <li><a href="#"><span class="glyphicon glyphicon-home"></span> Home</a></li>
+ <li><a href="#tokens">Tokens</a></li>
+ <li><a href="#certs">Certificates</a></li>
+ <li><a href="#activities">Activities</a></li>
+ <li class="dropdown context">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+ Accounts
+ <b class="caret"></b>
+ </a>
+ <ul class="dropdown-menu">
+ <li><a href="#users">Users</a></li>
+ <li><a href="#groups">Groups</a></li>
+ </ul>
+ </li>
+ <li class="dropdown context">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+ System
+ <b class="caret"></b>
+ </a>
+ <ul class="dropdown-menu">
+ <li><a href="#config">General Configuration</a></li>
+ <li><a href="#authenticators">Authentication Sources</a></li>
+ <li><a href="#connectors">Subsystem Connections</a></li>
+ <li><a href="#profiles">Profiles</a></li>
+ <li><a href="#profile-mappings">Profile Mappings</a></li>
+ <li><a href="#audit">Audit Logging</a></li>
+ <li><a href="#selftests">Self Tests</a></li>
+ </ul>
+ </li>
+ </ul>
+</div>
+</nav>
+
+<div id="content">
+</div>
+
+<div id="error-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Error</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <span name="content"></span>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="close" class="btn btn-primary">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/base/tps/shared/webapps/tps/ui/profile-mapping.html b/base/tps/shared/webapps/tps/ui/profile-mapping.html
new file mode 100644
index 000000000..139d21262
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/profile-mapping.html
@@ -0,0 +1,131 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#profile-mappings">Profile Mappings</a></li>
+ <li class="active"><strong><span name="title">Profile Mapping ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Profile Mapping ${id}</span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+<a name="enable" href="#">Enable</a><a name="disable" href="#" style="display: none;">Disable</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<div name="profile-mapping" class="pki-fields">
+<fieldset>
+ <label>Profile Mapping ID</label>
+ <input name="profileMappingID" readonly="readonly">
+ <br>
+ <label>Status</label>
+ <input name="status" readonly="readonly">
+ <br>
+</fieldset>
+</div>
+
+<h2>Properties</h2>
+
+<table name="properties">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons" style="display: none;">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="profile_selectall" type="checkbox"><label for="profile_selectall">&nbsp;</label></th>
+ <th class="pki-property-name-column">Name</th>
+ <th>Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="profile_select" type="checkbox"><label for="profile_select">&nbsp;</label></td>
+ <td name="id" class="pki-property-name-column"><a href="/tps/ui/profile-mappings/${parent.id}/properties/${id}">${id}</a></td>
+ <td name="value">${value}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
+
+<div id="property-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Edit Property</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Name</label>
+ <input name="name" readonly="readonly"><br>
+ <label>Value</label>
+ <input name="value" readonly="readonly"><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="add" class="btn btn-primary">Add</button>
+ <button name="save" class="btn btn-primary">Save</button>
+ <button name="close" class="btn btn-primary">Close</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/profile-mappings.html b/base/tps/shared/webapps/tps/ui/profile-mappings.html
new file mode 100644
index 000000000..dc797bc18
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/profile-mappings.html
@@ -0,0 +1,75 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Profile Mappings</strong></li>
+</ol>
+
+<span class="pki-title">Profile Mappings</span>
+</div>
+
+<table name="profile-mappings">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="profile_mapping_selectall" type="checkbox"><label for="profile_mapping_selectall">&nbsp;</label></th>
+ <th>Profile Mapping ID</th>
+ <th>Status</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="profile_mapping_select" type="checkbox"><label for="profile_mapping_select">&nbsp;</label></td>
+ <td name="id"><a href="#profile-mappings/${id}">${id}</a></td>
+ <td name="status">${status}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/shared/webapps/tps/ui/profile.html b/base/tps/shared/webapps/tps/ui/profile.html
new file mode 100644
index 000000000..61811bcc3
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/profile.html
@@ -0,0 +1,131 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#profiles">Profiles</a></li>
+ <li class="active"><strong><span name="title">Profile ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Profile ${id}</span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+<a name="enable" href="#">Enable</a><a name="disable" href="#" style="display: none;">Disable</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<div name="profile" class="pki-fields">
+<fieldset>
+ <label>Profile ID</label>
+ <input name="profileID" readonly="readonly">
+ <br>
+ <label>Status</label>
+ <input name="status" readonly="readonly">
+ <br>
+</fieldset>
+</div>
+
+<h2>Properties</h2>
+
+<table name="properties">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons" style="display: none;">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="profile_selectall" type="checkbox"><label for="profile_selectall">&nbsp;</label></th>
+ <th class="pki-property-name-column">Name</th>
+ <th>Value</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="profile_select" type="checkbox"><label for="profile_select">&nbsp;</label></td>
+ <td name="id" class="pki-property-name-column"><a href="/tps/ui/profiles/${parent.id}/properties/${id}">${id}</a></td>
+ <td name="value">${value}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
+
+<div id="property-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Edit Property</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Name</label>
+ <input name="name" readonly="readonly"><br>
+ <label>Value</label>
+ <input name="value" readonly="readonly"><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="add" class="btn btn-primary">Add</button>
+ <button name="save" class="btn btn-primary">Save</button>
+ <button name="close" class="btn btn-primary">Close</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/profiles.html b/base/tps/shared/webapps/tps/ui/profiles.html
new file mode 100644
index 000000000..00218e5f7
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/profiles.html
@@ -0,0 +1,75 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Profiles</strong></li>
+</ol>
+
+<span class="pki-title">Profiles</span>
+</div>
+
+<table name="profiles">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="profile_selectall" type="checkbox"><label for="profile_selectall">&nbsp;</label></th>
+ <th>Profile ID</th>
+ <th>Status</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="profile_select" type="checkbox"><label for="profile_select">&nbsp;</label></td>
+ <td name="id"><a href="#profiles/${id}">${id}</a></td>
+ <td name="status">${status}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/shared/webapps/tps/ui/selftest.html b/base/tps/shared/webapps/tps/ui/selftest.html
new file mode 100644
index 000000000..8a680355a
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/selftest.html
@@ -0,0 +1,42 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#selftests">Self Tests</a></li>
+ <li class="active"><strong><span name="title">Self Test ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Self Test ${id}</span>
+
+</div>
+
+<div name="user" class="pki-fields">
+<fieldset>
+ <label>Self Test ID</label>
+ <input name="id" readonly="readonly"><br>
+ <label>Enabled at Startup</label>
+ <input name="enabledAtStartup" readonly="readonly"><br>
+ <label>Critical at Startup</label>
+ <input name="criticalAtStartup" readonly="readonly"><br>
+ <label>Enabled on Demand</label>
+ <input name="enabledOnDemand" readonly="readonly"><br>
+ <label>Critical on Demand</label>
+ <input name="criticalOnDemand" readonly="readonly"><br>
+</fieldset>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/selftests.html b/base/tps/shared/webapps/tps/ui/selftests.html
new file mode 100644
index 000000000..2b428e2d2
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/selftests.html
@@ -0,0 +1,79 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Self Tests</strong></li>
+</ol>
+
+<span class="pki-title">Self Tests</span>
+</div>
+
+<table name="selftests">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="6">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="selftest_selectall" type="checkbox"><label for="selftest_selectall">&nbsp;</label></th>
+ <th>Self Test ID</th>
+ <th>Enabled at Statup</th>
+ <th>Critical at Startup</th>
+ <th>Enabled on Demand</th>
+ <th>Critical on Demand</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="selftest_select" type="checkbox"><label for="selftest_select">&nbsp;</label></td>
+ <td name="id"><a href="#selftests/${id}">${id}</a></td>
+ <td name="enabledAtStartup">${enabledAtStartup}</td>
+ <td name="criticalAtStartup">${criticalAtStartup}</td>
+ <td name="enabledOnDemand">${enabledOnDemand}</td>
+ <td name="criticalOnDemand">${criticalOnDemand}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="6">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/shared/webapps/tps/ui/token.html b/base/tps/shared/webapps/tps/ui/token.html
new file mode 100644
index 000000000..78384acfe
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/token.html
@@ -0,0 +1,96 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#tokens">Tokens</a></li>
+ <li class="active"><strong><span name="title">Token ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">Token ${id}</span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+<a name="changeStatus" href="#">Change Status</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<div name="token" class="pki-fields">
+<fieldset>
+ <label>Token ID</label>
+ <input name="tokenID" readonly="readonly"><br>
+ <label>User ID</label>
+ <input name="userID" readonly="readonly"><br>
+ <label>Type</label>
+ <input name="type" readonly="readonly"><br>
+ <label>Status</label>
+ <input name="statusLabel" readonly="readonly"><br>
+ <label>Applet ID</label>
+ <input name="appletID" readonly="readonly"><br>
+ <label>Key Info</label>
+ <input name="keyInfo" readonly="readonly"><br>
+ <label>Policy</label>
+ <input name="policy" readonly="readonly"><br>
+ <label>Created</label>
+ <input name="createTimestamp" readonly="readonly"><br>
+ <label>Modified</label>
+ <input name="modifyTimestamp" readonly="readonly"><br>
+</fieldset>
+</div>
+
+<div id="token-status-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Change Token Status</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Token ID</label>
+ <input name="tokenID" readonly="readonly"><br>
+ <label>Status</label>
+ <select name="status">
+ <option value="UNINITIALIZED">Uninitialized</option>
+ <option value="ACTIVE">Active</option>
+ <option value="TEMP_LOST">Temporarily lost</option>
+ <option value="PERM_LOST">Permanently lost</option>
+ <option value="DAMAGED">Physically damaged</option>
+ <option value="TERMINATED">Terminated</option>
+ </select><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="save" class="btn btn-primary">Save</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/tokens.html b/base/tps/shared/webapps/tps/ui/tokens.html
new file mode 100644
index 000000000..aca579a68
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/tokens.html
@@ -0,0 +1,135 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Tokens</strong></li>
+</ol>
+
+<span class="pki-title">Tokens</span>
+</div>
+
+<table name="tokens">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="10">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="token_selectall" type="checkbox"><label for="token_selectall">&nbsp;</label></th>
+ <th>Token ID</th>
+ <th>User ID</th>
+ <th>Type</th>
+ <th>Status</th>
+ <th>Applet ID</th>
+ <th>Key Info</th>
+ <th>Policy</th>
+ <th>Created</th>
+ <th>Modified</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="token_select" type="checkbox"><label for="token_select">&nbsp;</label></td>
+ <td name="id"><a href="#tokens/${id}">${id}</a></td>
+ <td name="userID">${userID}</td>
+ <td name="type">${type}</td>
+ <td name="status"><a href="#tokens/${id}/status">${statusLabel}</a></td>
+ <td name="appletID">${appletID}</td>
+ <td name="keyInfo">${keyInfo}</td>
+ <td name="policy">${policy}</td>
+ <td name="created">${createTimestamp}</td>
+ <td name="modified">${modifyTimestamp}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="10">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
+
+<div id="token-status-dialog" class="modal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ <span class="pficon pficon-close"></span>
+ </button>
+ <h4 class="modal-title">Change Token Status</h4>
+ </div>
+ <div class="modal-body">
+ <fieldset>
+ <label>Token ID</label>
+ <input name="tokenID" readonly="readonly"><br>
+ <label>User ID</label>
+ <input name="userID" readonly="readonly"><br>
+ <label>Type</label>
+ <input name="type" readonly="readonly"><br>
+ <label>Status</label>
+ <select name="status">
+ <option value="UNINITIALIZED">Uninitialized</option>
+ <option value="ACTIVE">Active</option>
+ <option value="TEMP_LOST">Temporarily lost</option>
+ <option value="PERM_LOST">Permanently lost</option>
+ <option value="DAMAGED">Physically damaged</option>
+ <option value="TERMINATED">Terminated</option>
+ </select><br>
+ <label>Applet ID</label>
+ <input name="appletID" readonly="readonly"><br>
+ <label>Key Info</label>
+ <input name="keyInfo" readonly="readonly"><br>
+ <label>Policy</label>
+ <input name="policy" readonly="readonly"><br>
+ <label>Created</label>
+ <input name="createTimestamp" readonly="readonly"><br>
+ <label>Modified</label>
+ <input name="modifyTimestamp" readonly="readonly"><br>
+ </fieldset>
+ </div>
+ <div class="modal-footer">
+ <button name="save" class="btn btn-primary">Save</button>
+ <button name="cancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/user.html b/base/tps/shared/webapps/tps/ui/user.html
new file mode 100644
index 000000000..8463d0bef
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/user.html
@@ -0,0 +1,57 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2014 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li><a href="#users">Users</a></li>
+ <li class="active"><strong><span name="title">User ${id}</span></strong></li>
+</ol>
+
+<span name="title" class="pki-title">User ${id}</span>
+
+<span class="pki-actions">
+
+<span class="pki-menu" style="display: none;">
+<a name="edit" href="#">Edit</a><br>
+</span>
+
+<span class="pki-buttons" style="display: none;">
+<button name="cancel">Cancel</button>
+<button name="save" class="primary">Save</button>
+</span>
+
+</span>
+
+</div>
+
+<div name="user" class="pki-fields">
+<fieldset>
+ <label>User ID</label>
+ <input name="userID" readonly="readonly"><br>
+ <label>Full Name</label>
+ <input name="fullName" readonly="readonly"><br>
+ <label>Email</label>
+ <input name="email" readonly="readonly"><br>
+ <label>Type</label>
+ <input name="type" readonly="readonly"><br>
+ <label>State</label>
+ <input name="state" readonly="readonly"><br>
+ <label>TPS Profiles</label>
+ <input name="tpsProfiles" readonly="readonly"><br>
+</fieldset>
+</div>
diff --git a/base/tps/shared/webapps/tps/ui/users.html b/base/tps/shared/webapps/tps/ui/users.html
new file mode 100644
index 000000000..18d59c9de
--- /dev/null
+++ b/base/tps/shared/webapps/tps/ui/users.html
@@ -0,0 +1,75 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Copyright (C) 2013 Red Hat, Inc.
+ All rights reserved.
+ --- END COPYRIGHT BLOCK --- -->
+<div class="pki-header">
+<ol class="breadcrumb">
+ <li><a href="#">Home</a></li>
+ <li class="active"><strong>Users</strong></li>
+</ol>
+
+<span class="pki-title">Users</span>
+</div>
+
+<table name="users">
+<thead>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <span name="search">
+ <input name="search" type="text" placeholder="Search...">
+ </span>
+ <span class="pki-table-buttons">
+ <button name="add">Add</button>
+ <button name="remove">Remove</button>
+ </span>
+ </th>
+ </tr>
+ <tr>
+ <th class="pki-select-column"><input id="user_selectall" type="checkbox"><label for="user_selectall">&nbsp;</label></th>
+ <th>User ID</th>
+ <th>Full Name</th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td class="pki-select-column"><input id="user_select" type="checkbox"><label for="user_select">&nbsp;</label></td>
+ <td name="id"><a href="#users/${id}">${id}</a></td>
+ <td name="fullName">${fullName}</td>
+ </tr>
+</tbody>
+<tfoot>
+ <tr>
+ <th class="pki-table-actions" colspan="3">
+ <div class="pki-table-info">
+ Total: <span name="totalEntries">0</span> entries
+ </div>
+ <div class="pki-page-controls">
+ <ul class="pagination">
+ <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+ <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+ </ul>
+ <span class="pki-page-jump">
+ <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+ </span>
+ <ul class="pagination">
+ <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+ <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+ </ul>
+ </div>
+ </th>
+ </tr>
+</tfoot>
+</table>
diff --git a/base/tps/src/CMakeLists.txt b/base/tps/src/CMakeLists.txt
new file mode 100644
index 000000000..b36a01526
--- /dev/null
+++ b/base/tps/src/CMakeLists.txt
@@ -0,0 +1,170 @@
+project(pki-tps_java NONE)
+
+find_file(LDAPJDK_JAR
+ NAMES
+ ldapjdk.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(JSS_JAR
+ NAMES
+ jss4.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+)
+
+find_file(COMMONS_CODEC_JAR
+ NAMES
+ commons-codec.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(COMMONS_LANG_JAR
+ NAMES
+ commons-lang.jar
+ PATHS
+ /usr/share/java
+)
+
+find_file(JAXRS_API_JAR
+ NAMES
+ jaxrs-api.jar
+ PATHS
+ ${RESTEASY_LIB}
+)
+
+find_file(TOMCAT_CATALINA_JAR
+ NAMES
+ catalina.jar
+ PATHS
+ /usr/share/java/tomcat
+)
+
+find_file(PKI_CERTSRV_JAR
+ NAMES
+ pki-certsrv.jar
+ PATHS
+ /usr/share/java/pki
+)
+
+find_file(PKI_CMS_JAR
+ NAMES
+ pki-cms.jar
+ PATHS
+ /usr/share/java/pki
+)
+
+find_file(PKI_CMSCORE_JAR
+ NAMES
+ pki-cmscore.jar
+ PATHS
+ /usr/share/java/pki
+)
+
+find_file(PKI_CMSUTIL_JAR
+ NAMES
+ pki-cmsutil.jar
+ PATHS
+ /usr/share/java/pki
+)
+
+find_file(PKI_NSUTIL_JAR
+ NAMES
+ pki-nsutil.jar
+ PATHS
+ /usr/share/java/pki
+)
+
+find_file(JAXRS_API_JAR
+ NAMES
+ jaxrs-api.jar
+ PATHS
+ ${RESTEASY_LIB}
+)
+
+find_file(RESTEASY_JAXRS_JAR
+ NAMES
+ resteasy-jaxrs.jar
+ PATHS
+ ${RESTEASY_LIB}
+)
+
+find_file(RESTEASY_ATOM_PROVIDER_JAR
+ NAMES
+ resteasy-atom-provider.jar
+ PATHS
+ ${RESTEASY_LIB}
+)
+
+find_file(SERVLET_JAR
+ NAMES
+ servlet.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(SYMKEY_JAR
+ NAMES
+ symkey.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+find_file(VELOCITY_JAR
+ NAMES
+ velocity.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
+# build pki-tps
+javac(pki-tps-classes
+ SOURCES
+ org/dogtagpki/server/tps/*.java
+ CLASSPATH
+ ${COMMONS_CODEC_JAR} ${COMMONS_LANG_JAR}
+ ${LDAPJDK_JAR}
+ ${JSS_JAR} ${SYMKEY_JAR}
+ ${JAXRS_API_JAR} ${RESTEASY_JAXRS_JAR} ${RESTEASY_ATOM_PROVIDER_JAR}
+ ${SERVLET_JAR} ${TOMCAT_CATALINA_JAR} ${VELOCITY_JAR}
+ ${PKI_CMSUTIL_JAR} ${PKI_NSUTIL_JAR}
+ ${PKI_CERTSRV_JAR} ${PKI_CMS_JAR} ${PKI_CMSCORE_JAR}
+ OUTPUT_DIR
+ ${CMAKE_BINARY_DIR}/classes
+ DEPENDS
+ pki-nsutil-jar pki-cmsutil-jar pki-certsrv-jar pki-cms-jar pki-cmscore-jar
+)
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/pki-tps.mf
+ ${CMAKE_CURRENT_BINARY_DIR}/pki-tps.mf
+)
+
+jar(pki-tps-jar
+ CREATE
+ ${CMAKE_BINARY_DIR}/dist/pki-tps.jar
+ OPTIONS
+ m
+ PARAMS
+ ${CMAKE_CURRENT_BINARY_DIR}/pki-tps.mf
+ INPUT_DIR
+ ${CMAKE_BINARY_DIR}/classes
+ FILES
+ org/dogtagpki/server/tps/*.class
+ DEPENDS
+ pki-tps-classes
+)
+
+install(
+ FILES
+ ${CMAKE_BINARY_DIR}/dist/pki-tps.jar
+ DESTINATION
+ ${JAVA_JAR_INSTALL_DIR}/pki
+)
+
+set(PKI_TPS_JAR ${CMAKE_BINARY_DIR}/dist/pki-tps.jar CACHE INTERNAL "pki-tps jar file")
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSPhoneHome.java b/base/tps/src/org/dogtagpki/server/tps/TPSPhoneHome.java
new file mode 100644
index 000000000..e0b3b6b87
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSPhoneHome.java
@@ -0,0 +1,95 @@
+package org.dogtagpki.server.tps;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class TPSPhoneHome extends HttpServlet {
+
+ private static final long serialVersionUID = 1864386666927370987L;
+ private static String phoneHomeName = "phoneHome.xml";
+
+ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
+ //Simply return xml file to the client
+ //In the future we could get this info from elsewhere such as LDAP
+
+ CMS.debug("TPSPhoneHome entering.");
+
+ renderPhoneHome(request, response);
+ }
+
+ private void renderPhoneHome(HttpServletRequest request, HttpServletResponse response) throws ServletException,
+ IOException {
+ ServletOutputStream stream = null;
+ BufferedInputStream buf = null;
+ FileInputStream input = null;
+
+ try {
+
+ stream = response.getOutputStream();
+ response.setContentType("application/xml");
+
+ String confPath = getConfigPath();
+
+ confPath += File.separator + phoneHomeName;
+
+ input = new FileInputStream(confPath);
+ // InputStream input = ctx.getResourceAsStream(phoneHomeName);
+ buf = new BufferedInputStream(input);
+
+ int readBytes = 0;
+ TPSBuffer readData = new TPSBuffer();
+ while ((readBytes = buf.read()) != -1) {
+ stream.write(readBytes);
+ readData.add((byte) readBytes);
+ }
+
+ CMS.debug("TPSPhoneHome.renderPhoneHome: data: " + readData.toHexString());
+
+ } catch (IOException e) {
+ CMS.debug("TPSPhoneHome.renderPhoneHome: Error encountered: " + e);
+ throw new ServletException("TPSPhoneHome.renderPhoneHome: Error encountered: " + e);
+ } finally {
+ if (stream != null)
+ stream.close();
+ if (buf != null)
+ buf.close();
+ if (input != null)
+ input.close();
+ }
+
+ }
+
+ private String getConfigPath() {
+
+ String path = null;
+ String context = getServletContext().getContextPath();
+
+ // get subsystem name by removing the / prefix from the context
+ String subsystem = context.startsWith("/") ? context.substring(1) : context;
+
+ // catalina.base points to instance dir
+ String instanceDir = System.getProperty("catalina.base");
+
+ //Finish off path of conf directory
+ path = instanceDir + File.separator + "conf" + File.separator +
+ subsystem + File.separator;
+
+ CMS.debug("TPSPhoneHome.getConfigPath: returning: " + path);
+
+ return path;
+
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSServlet.java b/base/tps/src/org/dogtagpki/server/tps/TPSServlet.java
new file mode 100644
index 000000000..87c416b3e
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSServlet.java
@@ -0,0 +1,65 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.dogtagpki.tps.TPSConnection;
+
+import com.netscape.certsrv.apps.CMS;
+
+/**
+ * @author Endi S. Dewata <edewata@redhat.com>
+ */
+public class TPSServlet extends HttpServlet {
+
+ private static final long serialVersionUID = -1092227495262381074L;
+
+ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
+
+ String encoding = request.getHeader("Transfer-Encoding");
+
+ CMS.debug("Encoding: " + encoding);
+
+ if (encoding.equals("chunked") == false) {
+ throw new IOException("TPSServlet.service: incorrect encoding! ");
+ }
+
+ response.setHeader("Transfer-Encoding", "chunked");
+
+ TPSConnection con = new TPSConnection(
+ request.getInputStream(), response.getOutputStream(), true);
+
+ CMS.debug("TPSConnection created: " + con);
+
+ String ipAddress = request.getRemoteAddr();
+
+ TPSSession session = new TPSSession(con, ipAddress);
+
+ CMS.debug("TPSSession created: " + session);
+
+ session.process();
+
+ CMS.debug("After session.process() exiting ...");
+
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSSession.java b/base/tps/src/org/dogtagpki/server/tps/TPSSession.java
new file mode 100644
index 000000000..4a175e698
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSSession.java
@@ -0,0 +1,174 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps;
+
+import java.io.IOException;
+
+import org.dogtagpki.server.tps.dbs.TokenRecord;
+import org.dogtagpki.server.tps.processor.TPSEnrollProcessor;
+import org.dogtagpki.server.tps.processor.TPSPinResetProcessor;
+import org.dogtagpki.server.tps.processor.TPSProcessor;
+import org.dogtagpki.tps.TPSConnection;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.BeginOpMsg;
+import org.dogtagpki.tps.msg.EndOpMsg;
+import org.dogtagpki.tps.msg.TPSMessage;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class TPSSession {
+
+ private TPSConnection connection;
+ private String ipAddress; /* remote IP */
+ private TokenRecord tokenRecord;
+
+ public TPSSession(TPSConnection conn, String ip) {
+
+ if (conn == null) {
+ throw new NullPointerException("TPSSession incoming connection is null!");
+ }
+
+ CMS.debug("TPSSession constructor conn: " + conn);
+ connection = conn;
+
+ if (ip == null) {
+ // probably unlikely to happen; log it and continue anyway
+ CMS.debug("TPSSession constructor remote ipAddress null");
+ } else {
+ CMS.debug("TPSSession constructor remote ipAddress: " + getIpAddress());
+ }
+ setIpAddress(ip);
+
+ }
+
+ public TPSConnection getConnection() {
+ return connection;
+ }
+
+ public TPSMessage read() throws IOException {
+ TPSMessage message = null;
+
+ CMS.debug("TPSSession.process() about to call read on connection : " + connection);
+
+ try {
+ message = connection.read();
+ CMS.debug("TPSSession.process() created message " + message);
+
+ } catch (IOException e) {
+ //Catch here so we can log
+ CMS.debug("TPSSession.process: Exception reading from the client: " + e.toString());
+ throw e;
+ }
+
+ return message;
+ }
+
+ public void write(TPSMessage msg) throws IOException {
+
+ try {
+ connection.write(msg);
+ } catch (Exception e) {
+ //Catch here so we can log
+ CMS.debug("Exception writing to client: " + e.toString());
+ throw e;
+ }
+
+ }
+
+ public void process() throws IOException {
+ EndOpMsg.TPSStatus status = EndOpMsg.TPSStatus.STATUS_NO_ERROR;
+ CMS.debug("In TPSSession.process()");
+
+ TPSMessage firstMsg = read();
+
+ TPSMessage.MsgType msg_type = firstMsg.getType();
+ TPSMessage.OpType op_type = firstMsg.getOpType();
+
+ if (msg_type != TPSMessage.MsgType.MSG_BEGIN_OP) {
+ throw new IOException("Wrong first message type read in TPSSession.process!");
+ }
+
+ int result = EndOpMsg.RESULT_ERROR;
+ BeginOpMsg beginOp = (BeginOpMsg) firstMsg;
+ try {
+ switch (op_type) {
+ case OP_FORMAT:
+
+ //Assume success, processor will indicate otherwise
+ result = EndOpMsg.RESULT_GOOD;
+ TPSProcessor processor = new TPSProcessor(this);
+ processor.process(beginOp);
+ break;
+
+ case OP_ENROLL:
+ //Assume success, processor will indicate otherwise
+ result = EndOpMsg.RESULT_GOOD;
+ TPSEnrollProcessor enrollProcessor = new TPSEnrollProcessor(this);
+ enrollProcessor.process(beginOp);
+ break;
+ case OP_RENEW:
+ break;
+ case OP_RESET_PIN:
+ result = EndOpMsg.RESULT_GOOD;
+ TPSPinResetProcessor pinResetProcessor = new TPSPinResetProcessor(this);
+ pinResetProcessor.process(beginOp);
+ break;
+ case OP_UNBLOCK:
+ break;
+ case OP_UNDEFINED:
+ break;
+ default:
+ break;
+
+ }
+ } catch (TPSException e) {
+ //Get the status from the exception and return it to the client.
+ CMS.debug("TPSSession.process: Message processing failed: " + e);
+ status = e.getStatus();
+ result = EndOpMsg.RESULT_ERROR;
+ } catch (IOException e) {
+ CMS.debug("TPSSession.process: IO error happened during processing: " + e);
+ // We get here we are done.
+ throw e;
+
+ }
+
+ EndOpMsg endOp = new EndOpMsg(firstMsg.getOpType(), result, status);
+ write(endOp);
+
+ CMS.debug("TPSSession.process: leaving: result: " + result + " status: " + status);
+
+ }
+
+ public TokenRecord getTokenRecord() {
+ return tokenRecord;
+ }
+
+ public void setTokenRecord(TokenRecord tokenRecord) {
+ this.tokenRecord = tokenRecord;
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ private void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java b/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java
new file mode 100644
index 000000000..75cdddadb
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSSubsystem.java
@@ -0,0 +1,231 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps;
+
+import org.dogtagpki.server.tps.authentication.AuthenticationManager;
+import org.dogtagpki.server.tps.cms.ConnectionManager;
+import org.dogtagpki.server.tps.config.AuthenticatorDatabase;
+import org.dogtagpki.server.tps.config.ConfigDatabase;
+import org.dogtagpki.server.tps.config.ConnectorDatabase;
+import org.dogtagpki.server.tps.config.ProfileDatabase;
+import org.dogtagpki.server.tps.config.ProfileMappingDatabase;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
+import org.dogtagpki.server.tps.dbs.TPSCertDatabase;
+import org.dogtagpki.server.tps.dbs.TokenDatabase;
+import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.server.tps.profile.TokenProfileResolverManager;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.crypto.ObjectNotFoundException;
+import org.mozilla.jss.crypto.TokenException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authority.IAuthority;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ISubsystem;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.request.IRequestListener;
+import com.netscape.certsrv.request.IRequestQueue;
+import com.netscape.cmscore.dbs.DBSubsystem;
+
+/**
+ * @author Endi S. Dewata <edewata@redhat.com>
+ */
+public class TPSSubsystem implements IAuthority, ISubsystem {
+
+ public final static String ID = "tps";
+
+ public ILogger logger = CMS.getLogger();
+
+ public String id;
+ public String nickname;
+ public ISubsystem owner;
+ public IConfigStore config;
+
+ public ActivityDatabase activityDatabase;
+ public AuthenticatorDatabase authenticatorDatabase;
+ public TPSCertDatabase certDatabase;
+ public ConfigDatabase configDatabase;
+ public ConnectorDatabase connectorDatabase;
+ public ProfileDatabase profileDatabase;
+ public ProfileMappingDatabase profileMappingDatabase;
+ public TokenDatabase tokenDatabase;
+ public ConnectionManager connManager;
+ public AuthenticationManager authManager;
+ public TokenProfileResolverManager profileResolverManager;
+ public TPSEngine engine;
+ public TPSTokendb tdb;
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(String id) throws EBaseException {
+ this.id = id;
+ }
+
+ @Override
+ public void init(ISubsystem owner, IConfigStore config) throws EBaseException {
+ this.owner = owner;
+ this.config = config;
+
+ IDBSubsystem dbSubsystem = DBSubsystem.getInstance();
+ IConfigStore cs = CMS.getConfigStore();
+
+ String activityDatabaseDN = cs.getString("tokendb.activityBaseDN");
+ activityDatabase = new ActivityDatabase(dbSubsystem, activityDatabaseDN);
+
+ String certDatabaseDN = cs.getString("tokendb.certBaseDN");
+ certDatabase = new TPSCertDatabase(dbSubsystem, certDatabaseDN);
+
+ String tokenDatabaseDN = cs.getString("tokendb.baseDN");
+ tokenDatabase = new TokenDatabase(dbSubsystem, tokenDatabaseDN);
+
+ configDatabase = new ConfigDatabase();
+ authenticatorDatabase = new AuthenticatorDatabase();
+ connectorDatabase = new ConnectorDatabase();
+ profileDatabase = new ProfileDatabase();
+ profileMappingDatabase = new ProfileMappingDatabase();
+ tdb = new TPSTokendb(this);
+
+ engine = new TPSEngine();
+ engine.init();
+
+ }
+
+ @Override
+ public void startup() throws EBaseException {
+ CMS.debug("TPSSubsystem: startup() begins");
+ connManager = new ConnectionManager();
+ connManager.initConnectors();
+ authManager = new AuthenticationManager();
+ authManager.initAuthInstances();
+ profileResolverManager = new TokenProfileResolverManager();
+ profileResolverManager.initProfileResolverInstances();
+ CMS.debug("TPSSubsystem: startup() ends.");
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public IConfigStore getConfigStore() {
+ return config;
+ }
+
+ @Override
+ public IRequestQueue getRequestQueue() {
+ return null;
+ }
+
+ @Override
+ public void registerRequestListener(IRequestListener listener) {
+ }
+
+ @Override
+ public void registerPendingListener(IRequestListener listener) {
+ }
+
+ @Override
+ public void log(int level, String msg) {
+ logger.log(ILogger.EV_SYSTEM, ILogger.S_TPS, level, msg);
+ }
+
+ @Override
+ public String getNickname() {
+ return nickname;
+ }
+
+ public void setNickname(String nickname) {
+ this.nickname = nickname;
+ }
+
+ @Override
+ public String getOfficialName() {
+ return "tps";
+ }
+
+ public ActivityDatabase getActivityDatabase() {
+ return activityDatabase;
+ }
+
+ public AuthenticatorDatabase getAuthenticatorDatabase() {
+ return authenticatorDatabase;
+ }
+
+ public TPSCertDatabase getCertDatabase() {
+ return certDatabase;
+ }
+
+ public ConfigDatabase getConfigDatabase() {
+ return configDatabase;
+ }
+
+ public ConnectorDatabase getConnectorDatabase() {
+ return connectorDatabase;
+ }
+
+ public ProfileDatabase getProfileDatabase() {
+ return profileDatabase;
+ }
+
+ public ProfileMappingDatabase getProfileMappingDatabase() {
+ return profileMappingDatabase;
+ }
+
+ public TokenDatabase getTokenDatabase() {
+ return tokenDatabase;
+ }
+
+ public ConnectionManager getConnectionManager() {
+ return connManager;
+ }
+
+ public AuthenticationManager getAuthenticationManager() {
+ return authManager;
+ }
+
+ public TokenProfileResolverManager getProfileResolverManager() {
+ return profileResolverManager;
+ }
+
+ public TPSTokendb getTokendb() {
+ return tdb;
+ }
+
+ public org.mozilla.jss.crypto.X509Certificate getSubsystemCert() throws EBaseException, NotInitializedException,
+ ObjectNotFoundException, TokenException {
+ IConfigStore cs = CMS.getConfigStore();
+ String nickname = cs.getString("tps.subsystem.nickname", "");
+ String tokenname = cs.getString("tps.subsystem.tokenname", "");
+ if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token"))
+ nickname = tokenname + ":" + nickname;
+
+ CryptoManager cm = CryptoManager.getInstance();
+ return cm.findCertByNickname(nickname);
+ }
+
+ public TPSEngine getEngine() {
+ return engine;
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokenPolicy.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokenPolicy.java
new file mode 100644
index 000000000..1a866f737
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokenPolicy.java
@@ -0,0 +1,158 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps;
+
+import org.dogtagpki.server.tps.dbs.TokenRecord;
+import org.dogtagpki.tps.main.TPSException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+
+/*
+ * TPSTokenPolicy - handles token enrollment related policies
+ *
+ * @author cfu
+ */
+public class TPSTokenPolicy {
+ private TPSSubsystem tps;
+ private static final String DEFAULT_POLICY_SET_STRING =
+ "RE_ENROLL=YES;RENEW=NO;FORCE_FORMAT=NO;PIN_RESET=NO;RESET_PIN_RESET_TO_NO=NO";
+ private boolean re_enroll = true;
+ private boolean renew = false;
+ private boolean force_format = false;
+ private boolean pin_reset = true;
+ private boolean reset_pin_reset_to_no = false;
+
+ public TPSTokenPolicy (TPSSubsystem tps) throws TPSException {
+ if (tps == null) {
+ String msg = "TPSTokenPolicy.TPSTokenPolicy: tps cannnot be null";
+ CMS.debug(msg);
+ throw new TPSException(msg);
+ }
+ this.tps = tps;
+ // init from config first
+ String policySetString = getDefaultPolicySetString();
+ parsePolicySetString(policySetString);
+
+ }
+
+ public String getDefaultPolicySetString() {
+ IConfigStore configStore = CMS.getConfigStore();
+ String configName = "tokendb.defaultPolicy";
+ String policySetString;
+ try {
+ policySetString = configStore.getString(configName);
+ } catch (EPropertyNotFound e) {
+ policySetString = DEFAULT_POLICY_SET_STRING;
+ } catch (EBaseException e) {
+ policySetString = DEFAULT_POLICY_SET_STRING;
+ }
+
+ return policySetString;
+ }
+
+ public void parsePolicySetString (String policySetString) {
+ if (policySetString == null)
+ return; // take the default
+
+ String[] policySet = policySetString.split(";");
+ for (String policyString : policySet) {
+ String[] policy = policyString.split("=");
+ if (policy[0].equalsIgnoreCase("RE_ENROLL"))
+ re_enroll = getBool(policy[1], true);
+ else if (policy[0].equalsIgnoreCase("RENEW"))
+ renew = getBool(policy[1], false);
+ else if (policy[0].equalsIgnoreCase("FORCE_FORMAT"))
+ force_format = getBool(policy[1], false);
+ else if (policy[0].equalsIgnoreCase("PIN_RESET"))
+ pin_reset = getBool(policy[1], false);
+ else if (policy[0].equalsIgnoreCase("RESET_PIN_RESET_TO_NO"))
+ reset_pin_reset_to_no = getBool(policy[1], false);
+ //else no change, just take the default;
+ }
+ }
+
+/*
+ * getBool translates string to boolean:
+ * true: "YES", "yes", "TRUE", "true"
+ * false: "NO", "no", "FALSE", "false"
+ *
+ * if tring is null or Anything othrer than the above, defaultbool is returned
+ */
+ private boolean getBool(String string, boolean defaultBool) {
+ if (string == null)
+ return defaultBool;
+
+ if (string.equalsIgnoreCase("YES") ||
+ string.equalsIgnoreCase("true")) {
+ return true;
+ } else if (string.equalsIgnoreCase("NO") ||
+ string.equalsIgnoreCase("false")) {
+ return false;
+ }
+
+ return defaultBool;
+ }
+
+ private void getUpdatedPolicy(String cuid) {
+ // note: default policy already initialized in the constructor
+ TokenRecord tokenRecord = null;
+ String policySetString = null;
+ try {
+ tokenRecord = tps.tdb.tdbGetTokenEntry(cuid);
+ } catch (Exception e) {
+ // just take the default;
+ return;
+ }
+
+ policySetString = tokenRecord.getPolicy();
+ parsePolicySetString(policySetString);
+ }
+
+ public boolean isAllowedTokenPinReset(String cuid) {
+ getUpdatedPolicy(cuid);
+
+ return reset_pin_reset_to_no;
+ }
+
+ public boolean isAllowedPinReset(String cuid) {
+ getUpdatedPolicy(cuid);
+
+ return pin_reset;
+ }
+
+ public boolean isForceTokenFormat(String cuid) {
+ getUpdatedPolicy(cuid);
+
+ return force_format;
+ }
+
+ public boolean isAllowdTokenReenroll(String cuid) {
+ getUpdatedPolicy(cuid);
+
+ return re_enroll;
+ }
+
+ public boolean isAllowdTokenRenew(String cuid) {
+ getUpdatedPolicy(cuid);
+
+ return renew;
+ }
+} \ No newline at end of file
diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
new file mode 100644
index 000000000..914706dd9
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/TPSTokendb.java
@@ -0,0 +1,425 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+
+import netscape.security.x509.RevocationReason;
+
+import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
+import org.dogtagpki.server.tps.cms.CARevokeCertResponse;
+import org.dogtagpki.server.tps.dbs.TPSCertRecord;
+import org.dogtagpki.server.tps.dbs.TokenRecord;
+import org.dogtagpki.tps.main.TPSException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.tps.token.TokenStatus;
+
+/*
+ * TPSTokendb class offers a collection of tokendb management convenience routines
+ */
+public class TPSTokendb {
+ private TPSSubsystem tps;
+ private Map<TokenStatus, Collection<TokenStatus>> allowedTransitions = new HashMap<TokenStatus, Collection<TokenStatus>>();
+
+ public TPSTokendb(TPSSubsystem tps) throws EBaseException {
+ if (tps == null) {
+ String msg = "TPStokendb.TPSTokendb: tps cannot be null";
+ CMS.debug(msg);
+ throw new EBaseException(msg);
+ }
+ this.tps = tps;
+ try {
+ initAllowedTransitions();
+ } catch (Exception e) {
+ CMS.debug("TPSTokendb: initAllowedTransitions() failed:" + e);
+ throw new EBaseException(e.toString());
+ }
+ }
+
+ void initAllowedTransitions()
+ throws Exception {
+ CMS.debug("TPSTokendb.initAllowedTransitions()");
+ IConfigStore configStore = CMS.getConfigStore();
+
+ // load allowed token state transitions
+ CMS.debug("TPSTokendbs: allowed transitions:");
+
+ for (String transition : configStore.getString("tokendb.allowedTransitions").split(",")) {
+ String states[] = transition.split(":");
+ TokenStatus fromState = TokenStatus.fromInt(Integer.valueOf(states[0]));
+ TokenStatus toState = TokenStatus.fromInt(Integer.valueOf(states[1]));
+ CMS.debug("TPSTokendb: - " + fromState + " to " + toState);
+
+ Collection<TokenStatus> nextStates = allowedTransitions.get(fromState);
+ if (nextStates == null) {
+ nextStates = new HashSet<TokenStatus>();
+ allowedTransitions.put(fromState, nextStates);
+ }
+ nextStates.add(toState);
+ }
+ }
+
+ public boolean isTransitionAllowed(TokenRecord tokenRecord, TokenStatus newState) {
+ boolean result = false;
+ TokenStatus currentTokenStatus = tokenRecord.getTokenStatus();
+ CMS.debug("TokenRecord.isTransitionAllowed(): current status: " + currentTokenStatus);
+ Collection<TokenStatus> nextStatuses = allowedTransitions.get(currentTokenStatus);
+ CMS.debug("TokenRecord.isTransitionAllowed(): allowed next statuses: " + nextStatuses);
+ if (nextStatuses == null || !nextStatuses.contains(newState)) {
+ CMS.debug("TokenRecord.isTransitionAllowed(): next status not allowed: " + newState);
+
+ result = false;
+ } else {
+ //status change allowed
+ result = true;
+ }
+ return result;
+ }
+
+ /*
+ * tdbActivity logs token activities; This version is called by non-administrative functions
+ */
+ public void tdbActivity(
+ String op, TokenRecord tokenRecord, String ip, String msg, String result) {
+ try {
+ tps.activityDatabase.log(
+ ip,
+ (tokenRecord != null)? tokenRecord.getId():null,
+ op,
+ result,
+ msg,
+ (tokenRecord != null)? tokenRecord.getUserID():null,
+ (tokenRecord != null)? tokenRecord.getType():null);
+ } catch (Exception e) {
+ msg = msg + ";" + " tokendb activity logging failure: " + e;
+ }
+ }
+
+ /*
+ * tdbActivity logs token activities; This version is called by administrative functions
+ */
+ public void tdbActivity(
+ String op, TokenRecord tokenRecord, String ip, String msg, String result, String uid) {
+ try {
+ tps.activityDatabase.log(
+ ip,
+ (tokenRecord != null)? tokenRecord.getId():null,
+ op,
+ result,
+ msg,
+ uid,
+ (tokenRecord != null)? tokenRecord.getType():null);
+ } catch (Exception e) {
+ msg = msg + ";" + " tokendb activity logging failure: " + e;
+ }
+ }
+
+ public boolean isTokenPresent(String cuid) {
+ boolean present = false;
+ try {
+ tps.tokenDatabase.getRecord(cuid);
+ present = true;
+ } catch (Exception e) {
+ CMS.debug("TPSTokendb.isTokenPresent: token entry not found");
+ present = false;
+ }
+ return present;
+ }
+
+ public TokenRecord tdbGetTokenEntry(String cuid)
+ throws Exception {
+ return tps.tokenDatabase.getRecord(cuid);
+ }
+
+ /*
+ * tdbFindTokenRecordsByUID finds and returns token records belong to one user
+ * @param uid the uid of the owner to the token
+ * @return ArrayList of the token records
+ */
+ public ArrayList<TokenRecord> tdbFindTokenRecordsByUID(String uid)
+ throws Exception {
+ ArrayList<TokenRecord> tokenRecords = new ArrayList<TokenRecord>();
+ String filter = uid;
+ Iterator<TokenRecord> records = null;
+ records = tps.tokenDatabase.findRecords(filter).iterator();
+
+ while (records.hasNext()) {
+ TokenRecord tokenRecord = records.next();
+ tokenRecords.add(tokenRecord);
+ }
+
+ return tokenRecords;
+ }
+
+ public void tdbHasActiveToken(String userid)
+ throws Exception {
+ if (userid == null)
+ throw new Exception("TPSTokendb.tdbhasActiveToken: uerid null");
+
+ ArrayList<TokenRecord> tokens =
+ tdbFindTokenRecordsByUID(userid);
+ boolean foundActive = false;
+ for (TokenRecord tokenRecord:tokens) {
+ if (tokenRecord.getStatus().equals("active")) {
+ foundActive = true;
+ }
+ }
+ if (!foundActive) {
+ throw new Exception("TPSTokendb.tdbhasActiveToken: active token not found");
+ }
+ }
+
+ public void tdbAddTokenEntry(TokenRecord tokenRecord, String status)
+ throws Exception {
+ tokenRecord.setStatus(status);
+
+ tps.tokenDatabase.addRecord(tokenRecord.getId(), tokenRecord);
+ }
+
+ public void tdbUpdateTokenEntry(TokenRecord tokenRecord)
+ throws Exception {
+ String id = tokenRecord.getId();
+ TokenRecord existingTokenRecord;
+ try {
+ existingTokenRecord = tps.tokenDatabase.getRecord(id);
+ } catch (Exception e) {
+ CMS.debug("TPSTokendb.tdbUpdateTokenEntry: token entry not found; Adding");
+ // add and exit
+ tdbAddTokenEntry(tokenRecord, "uninitialized");
+ return;
+ }
+ // token found; modify
+ CMS.debug("TPSTokendb.tdbUpdateTokenEntry: token entry found; Modifying with status: "+ tokenRecord.getStatus());
+ // don't change the create time of an existing token record; put it back
+ tokenRecord.setCreateTimestamp(existingTokenRecord.getCreateTimestamp());
+ tps.tokenDatabase.updateRecord(id, tokenRecord);
+ }
+
+ /*
+ * tdbAddCertificatesForCUID adds certificates issued for the token CUID
+ * @param cuid the cuid of the token
+ * @param certs an ArrayList of TPSCertRecord
+ */
+ public void tdbAddCertificatesForCUID(String cuid, ArrayList<TPSCertRecord> certs)
+ throws TPSException {
+ boolean tokenExist = isTokenPresent(cuid);
+ if (!tokenExist){
+ CMS.debug("TPSTokendb.tdbAddCertificatesForCUID: token not found: "+ cuid);
+ throw new TPSException("TPSTokendb:tdbUpdateCertificates: token "+ cuid + " does not exist");
+ }
+
+ CMS.debug("TPSTokendb.tdbAddCertificatesForCUID: found token "+ cuid);
+ CMS.debug("TPSTokendb.tdbAddCertificatesForCUID: number of certs to update:"+ certs.size());
+ try {
+ for (TPSCertRecord cert: certs) {
+ // cert.setOrigin(cuid);
+
+ try {
+ tps.certDatabase.addRecord(cert.getId(), cert);
+ } catch (Exception e) {
+
+ //If this is due to a dup, try to update the record.
+ tps.certDatabase.updateRecord(cert.getId(), cert);
+ }
+ }
+ } catch (Exception e) {
+ CMS.debug("TPSTokendb.tdbAddCertificatesForCUID: "+ e);
+ // TODO: what if it throws in the middle of the cert list -- some cert records already updated?
+ throw new TPSException(e.getMessage());
+ }
+ }
+
+ /*
+ * tdbGetCertificatesByCUID finds and returns certificate records belong to a token cuid
+ * @param cuid the cuid of the token
+ * @return ArrayList of the cert records
+ */
+ public ArrayList<TPSCertRecord> tdbGetCertificatesByCUID(String cuid)
+ throws TPSException {
+ if (cuid == null)
+ throw new TPSException("TPSTokendb.tdbGetCertificatesByCUID: cuid null");
+
+ ArrayList<TPSCertRecord> certRecords = new ArrayList<TPSCertRecord>();
+ String filter = cuid;
+ Iterator<TPSCertRecord> records;
+ try {
+ records = tps.certDatabase.findRecords(filter).iterator();
+ } catch (Exception e) {
+ CMS.debug("TPSTokendb.tdbGetCertificatesByCUID:" + e);
+ throw new TPSException(e.getMessage());
+ }
+
+ while (records.hasNext()) {
+ TPSCertRecord certRecord = records.next();
+ certRecords.add(certRecord);
+ }
+
+ return certRecords;
+ }
+
+ public void revokeCertsByCUID(String cuid, String tokenReason) throws Exception {
+ String method = "TPStokendb.revokeCertsByCUID";
+ CMS.debug(method + ": called");
+ if (cuid == null)
+ throw new TPSException(method + ": cuid null");
+ revokeCertsByCUID(true, cuid, tokenReason);
+ }
+
+ public void unRevokeCertsByCUID(String cuid) throws Exception {
+ String method = "TPStokendb.unRevokeCertsByCUID";
+ CMS.debug(method + ": called");
+ if (cuid == null)
+ throw new TPSException(method + ": cuid null");
+ revokeCertsByCUID(false, cuid, null /* null for unrevoke*/);
+ }
+
+ /*
+ * revokeCertsByCUID
+ * @param isRevoke true if to revoke; false to unrevoke
+ * @param cuid cuid of token to revoke/unrevoke
+ * @param onHold true if revocation is to put onHold; false if to really revoke
+ */
+ private void revokeCertsByCUID(boolean isRevoke, String cuid, String tokenReason) throws Exception {
+ String method = "TPSTokendb.revokeCertsByCUID";
+ if (cuid == null)
+ throw new TPSException(method + ": cuid null");
+ String auditMsg;
+ IConfigStore configStore = CMS.getConfigStore();
+ ArrayList<TPSCertRecord> certRecords = tps.getTokendb().tdbGetCertificatesByCUID(cuid);
+ if (tokenReason != null) {
+ if (!tokenReason.equalsIgnoreCase("onHold") &&
+ !tokenReason.equalsIgnoreCase("destroyed") &&
+ !tokenReason.equalsIgnoreCase("keyCompromise")) {
+ auditMsg = "unknown tokenRecord lost reason:" + tokenReason;
+ CMS.debug(method + ":" + auditMsg);
+ throw new Exception(method + ":" + auditMsg);
+ }
+
+ }
+ for (TPSCertRecord cert : certRecords) {
+ // get conn id
+ String config = "op.enroll." + cert.getType() + ".keyGen." + cert.getKeyType() + ".ca.conn";
+ String connID = configStore.getString(config);
+
+ RevocationReason revokeReason = RevocationReason.UNSPECIFIED;
+
+ if (isRevoke) {
+ auditMsg = "called to revoke";
+ CMS.debug(method + ":" + auditMsg);
+ boolean revokeCert = false;
+
+ // get revoke or not
+ config = "op.enroll." + cert.getType() + ".keyGen." + cert.getKeyType() +
+ ".recovery." + tokenReason + ".revokeCert";
+ //TODO: temporaryToken doesn't have all params; default to false if not found for now
+ revokeCert = configStore.getBoolean(config, false); // default to false
+ if (!revokeCert) {
+ auditMsg = "cert not to be revoked:" + cert.getSerialNumber();
+ CMS.debug(method + ":" + auditMsg);
+ continue;
+ }
+ auditMsg = "cert to be revoked:" + cert.getSerialNumber();
+ CMS.debug(method + ":" + auditMsg);
+
+ // get revoke reason
+ config = "op.enroll." + cert.getType() + ".keyGen." + cert.getKeyType() +
+ ".recovery." + tokenReason + ".revokeCert.reason";
+ int reasonInt = configStore.getInteger(config, 0);
+ revokeReason = RevocationReason.fromInt(reasonInt);
+ } else { // is unrevoke
+ auditMsg = "called to unrevoke";
+ CMS.debug(method + ":" + auditMsg);
+ if (!cert.getStatus().equalsIgnoreCase("revoked_on_hold")) {
+ auditMsg = "cert record current status is not revoked_on_hold; cannot unrevoke";
+ CMS.debug(method + ":" + auditMsg);
+ continue;// TODO: continue or bail?
+ }
+ }
+
+ CARemoteRequestHandler caRH = null;
+ caRH = new CARemoteRequestHandler(connID);
+ String hexSerial = cert.getSerialNumber();
+ if (hexSerial.length() >= 3 && hexSerial.startsWith("0x")) {
+ String serial = hexSerial.substring(2); // skip over the '0x'
+ BigInteger bInt = new BigInteger(serial, 16);
+ String serialStr = bInt.toString();
+ CMS.debug(method + ": found cert hex serial: " + serial +
+ " dec serial:" + serialStr);
+ CARevokeCertResponse response =
+ caRH.revokeCertificate(isRevoke, serialStr, cert.getCertificate(),
+ revokeReason);
+ CMS.debug(method + ": response status =" + response.getStatus());
+ } else {
+ auditMsg = "mulformed hex serial number :" + hexSerial;
+ CMS.debug(method + ": " + auditMsg);
+ throw new Exception(auditMsg);
+ }
+
+ // update certificate status
+ if (isRevoke) {
+ if (revokeReason == RevocationReason.CERTIFICATE_HOLD) {
+ cert.setStatus("revoked_on_hold");
+ } else {
+ cert.setStatus("revoked");
+ }
+ } else {
+ cert.setStatus("active");
+ }
+ tps.certDatabase.updateRecord(cert.getId(), cert);
+ auditMsg = "cert (un)revoked:" + cert.getSerialNumber();
+ CMS.debug(method + ":" + auditMsg);
+ //TODO: tdbActivity
+ }
+ }
+
+ public void tdbAddCertEntry(TPSCertRecord certRecord, String status)
+ throws Exception {
+ certRecord.setStatus(status);
+
+ tps.certDatabase.addRecord(certRecord.getId(), certRecord);
+ }
+
+ public void tdbUpdateCertEntry(TPSCertRecord certRecord)
+ throws Exception {
+ String method = "TPSTokendb.tdbUpdateCertEntry";
+ String id = certRecord.getId();
+ TPSCertRecord existingCertRecord;
+ try {
+ existingCertRecord = tps.certDatabase.getRecord(id);
+ } catch (Exception e) {
+ CMS.debug(method + ": token entry not found; Adding");
+ // add and exit
+ tdbAddCertEntry(certRecord, certRecord.getStatus());
+ return;
+ }
+ // cert found; modify
+ CMS.debug(method + ": cert entry found; Modifying with status: "+ certRecord.getStatus());
+ // don't change the create time of an existing token record; put it back
+ certRecord.setCreateTime(existingCertRecord.getCreateTime());
+ tps.certDatabase.updateRecord(id, certRecord);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java b/base/tps/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java
new file mode 100644
index 000000000..16d57f948
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java
@@ -0,0 +1,92 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.authentication;
+
+import java.util.HashMap;
+
+import com.netscape.certsrv.base.EBaseException;
+
+/*
+ * AuthUIParameters is a class for per locale parameter sets
+ *
+ * @author cfu
+ */
+public class AuthUIParameter {
+
+ private String paramId;
+ /*
+ * auths.instance.<authInst>.ui.id.<param>.name.<locale>=<name>
+ * auths.instance.<authInst>.ui.id.<param>.description.<locale>=<description>
+ * e.g.
+ * auths.instance.ldap1.ui.id.PASSWORD.description.en=LDAP Password
+ * auths.instance.ldap1.ui.id.PASSWORD.name.en=LDAP Password
+ * auths.instance.ldap1.ui.id.UID.description.en=LDAP User ID
+ * auths.instance.ldap1.ui.id.UID.name.en=LDAP User ID
+ *
+ * for each id param <locale, name>
+ */
+ private HashMap<String, String> uiParamIdName;
+ private HashMap<String, String> uiParamIdDescription;
+
+ public AuthUIParameter(String id)
+ throws EBaseException {
+ paramId = id;
+ uiParamIdName = new HashMap<String, String>();
+ uiParamIdDescription = new HashMap<String, String>();
+ }
+
+ public void setParamName(String locale, String name) {
+ uiParamIdName.put(locale, name);
+ }
+
+ public String getParamName(String locale) {
+ return uiParamIdName.get(locale);
+ }
+
+ public void setParamDescription(String locale, String desc) {
+ uiParamIdDescription.put(locale, desc);
+ }
+
+ public String getParamDescription(String locale) {
+ return uiParamIdDescription.get(locale);
+ }
+
+ public String toString(String locale) {
+ String name = getParamName(locale);
+ if (name == null)
+ name = getParamName("en");
+
+ String desc = getParamDescription(locale);
+ if (desc == null)
+ desc = getParamDescription("en");
+
+ String typeValue = "string";
+
+ if(paramId.equals("PASSWORD")){
+ typeValue = "password";
+ }
+
+ String string =
+ "id=" + paramId +
+ "&name=" + name +
+ "&desc=" + desc +
+ "&type=" + typeValue +
+ "&option=";
+ return string;
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/authentication/AuthenticationManager.java b/base/tps/src/org/dogtagpki/server/tps/authentication/AuthenticationManager.java
new file mode 100644
index 000000000..e163bf6b1
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/authentication/AuthenticationManager.java
@@ -0,0 +1,287 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.authentication;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+
+/**
+ * AuthenticationManager is a class for management of authentication
+ * instances
+ *
+ * @author cfu
+ */
+public class AuthenticationManager
+{
+ private Hashtable<String, TPSAuthenticator> authInstances;
+
+ public AuthenticationManager() {
+ }
+
+ /*
+ * initAuthInstances initializes authentication manager instances
+ *
+ * configuration e.g.
+ *
+ * auths.instance.ldap1.ui.description.en=This authenticates user against the LDAP directory.
+ * auths.instance.ldap1.ui.title.en=LDAP Authentication
+ * auths.instance.ldap1.ui.id.PASSWORD.description.en=LDAP Password
+ * auths.instance.ldap1.ui.id.PASSWORD.name.en=LDAP Password
+ * auths.instance.ldap1.ui.id.PASSWORD.credMap.authCred=pwd
+ * auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred.extlogin=PASSWORD
+ * auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred.login=password
+ * auths.instance.ldap1.ui.id.UID.description.en=LDAP User ID
+ * auths.instance.ldap1.ui.id.UID.name.en=LDAP User ID
+ * auths.instance.ldap1.ui.id.UID.credMap.authCred=uid
+ * auths.instance.ldap1.ui.id.UID.credMap.msgCred.extlogin=UID
+ * auths.instance.ldap1.ui.id.UID.credMap.msgCred.login=screen_name
+ * auths.instance.ldap1.ui.retries=1
+ *
+ * # the following are handled by the IAuthManager itself
+ * auths.instance.ldap1.dnpattern=
+ * auths.instance.ldap1.ldap.basedn=dc=idm,dc=lab,dc=bos,dc=redhat,dc=com
+ * auths.instance.ldap1.ldap.ldapauth.authtype=BasicAuth
+ * auths.instance.ldap1.ldap.ldapauth.bindDN=
+ * auths.instance.ldap1.ldap.ldapauth.bindPWPrompt=ldap1
+ * auths.instance.ldap1.ldap.ldapauth.clientCertNickname=
+ * auths.instance.ldap1.ldap.ldapconn.host=vm-060.idm.lab.bos.redhat.com
+ * auths.instance.ldap1.ldap.ldapconn.port=389
+ * auths.instance.ldap1.ldap.ldapconn.secureConn=False
+ * auths.instance.ldap1.ldap.ldapconn.version=3
+ * auths.instance.ldap1.ldap.maxConns=15
+ * auths.instance.ldap1.ldap.minConns=3
+ * auths.instance.ldap1.ldapByteAttributes=
+ * auths.instance.ldap1.ldapStringAttributes=mail,cn,uid
+ * auths.instance.ldap1.pluginName=UidPwdDirAuth
+ */
+ public void initAuthInstances() throws EBaseException {
+ CMS.debug("AuthenticationManager: initAuthInstances(): begins.");
+ IConfigStore conf = CMS.getConfigStore();
+ IConfigStore authInstSubstore = conf.getSubStore("auths.instance");
+ Enumeration<String> auth_enu = authInstSubstore.getSubStoreNames();
+ authInstances = new Hashtable<String, TPSAuthenticator>();
+ while (auth_enu.hasMoreElements()) {
+ String authInstID = auth_enu.nextElement();
+ CMS.debug("AuthenticationManager: initAuthInstances(): initializing authentication instance " + authInstID);
+ IConfigStore authInstSub =
+ authInstSubstore.getSubStore(authInstID);
+ TPSAuthenticator authInst =
+ createAuthentication(authInstSub, authInstID);
+ authInstances.put(authInstID, authInst);
+ CMS.debug("AuthenticationManager: initAuthInstances(): authentication instance "
+ + authInstID +
+ " initialized.");
+ }
+ CMS.debug("AuthenticationManager: initAuthInstances(): ends.");
+ }
+
+ /*
+ * createAuthentication creates and returns an Authenticaiton
+ *
+ * @param conf config store of the authentication instance
+ * @return Authentication the authentication instance
+ */
+ private TPSAuthenticator createAuthentication(IConfigStore conf, String authInstID)
+ throws EBaseException {
+
+ CMS.debug("AuthenticationManager: createAuthentication(): begins for " +
+ authInstID);
+
+ if (conf == null || conf.size() <= 0) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf null or empty.");
+ throw new EBaseException("called with null config store");
+ }
+
+ TPSAuthenticator auth = new TPSAuthenticator(authInstID);
+
+ IConfigStore uiSub = conf.getSubStore("ui");
+ if (uiSub == null) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + conf.getName() + ".ui" + " null or empty.");
+ throw new EBaseException("config " + conf.getName() + ".ui" + " not found");
+ }
+
+ // init ui title
+ IConfigStore uiTitleSub = uiSub.getSubStore("title");
+ if (uiTitleSub == null) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + uiSub.getName() + ".title" + " null or empty.");
+ throw new EBaseException("config " + uiSub.getName() + ".title" + " not found");
+ }
+
+ Enumeration<String> uiTitle_enu = uiTitleSub.getPropertyNames();
+
+ while (uiTitle_enu.hasMoreElements()) {
+ String locale = uiTitle_enu.nextElement();
+ String title = uiTitleSub.getString(locale);
+ if (title.isEmpty()) {
+ CMS.debug("AuthenticationManager: createAuthentication(): title for locale "
+ + locale + " not found");
+ continue;
+ }
+ auth.setUiTitle(locale, title);
+ CMS.debug("AuthenticationManager: createAuthentication(): added title="
+ + title + ", locale= " + locale);
+ }
+
+ // init ui description
+ IConfigStore uiDescSub = uiSub.getSubStore("description");
+ if (uiDescSub == null) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + uiSub.getName() + ".description" + " null or empty.");
+ throw new EBaseException("config " + uiSub.getName() + ".description" + " not found");
+ }
+ Enumeration<String> uiDesc_enu = uiDescSub.getPropertyNames();
+
+ while (uiDesc_enu.hasMoreElements()) {
+ String locale = uiDesc_enu.nextElement();
+ String description = uiDescSub.getString(locale);
+ if (description.isEmpty()) {
+ CMS.debug("AuthenticationManager: createAuthentication(): description for locale "
+ + locale + " not found");
+ continue;
+ }
+ auth.setUiDescription(locale, description);
+ CMS.debug("AuthenticationManager: createAuthentication(): added description="
+ + description + ", locale= " + locale);
+ }
+
+ // init ui parameters
+ IConfigStore uiParamSub = uiSub.getSubStore("id");
+ if (uiParamSub == null) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + uiSub.getName() + ".id" + " null or empty.");
+ throw new EBaseException("config " + uiSub.getName() + ".id" + " not found");
+ }
+ Enumeration<String> uiParam_enu = uiParamSub.getSubStoreNames();
+ while (uiParam_enu.hasMoreElements()) {
+ String id = uiParam_enu.nextElement();
+ CMS.debug("AuthenticationManager: createAuthentication(): id param=" +
+ id);
+ IConfigStore idNameSub = uiParamSub.getSubStore(id + ".name");
+ if (idNameSub == null) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + uiParamSub.getName() + ".name" + " null or empty.");
+ continue;
+ }
+
+ AuthUIParameter up = new AuthUIParameter(id);
+ Enumeration<String> idName_enu = idNameSub.getPropertyNames();
+ while (idName_enu.hasMoreElements()) {
+ String locale = idName_enu.nextElement();
+ String name = idNameSub.getString(locale);
+ if (name.isEmpty()) {
+ CMS.debug("AuthenticationManager: createAuthentication(): name for locale "
+ + locale + " not found");
+ continue;
+ }
+ CMS.debug("AuthenticationManager: createAuthentication(): name =" +
+ name + " for locale " + locale);
+ up.setParamName(locale, name);
+ }
+
+ IConfigStore idDescSub = uiParamSub.getSubStore(id + ".description");
+ if (idDescSub == null) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + uiParamSub.getName() + ".description" + " null or empty.");
+ continue;
+ }
+ Enumeration<String> idDesc_enu = idDescSub.getPropertyNames();
+ while (idDesc_enu.hasMoreElements()) {
+ String locale = idDesc_enu.nextElement();
+ String desc = idDescSub.getString(locale);
+ if (desc.isEmpty()) {
+ CMS.debug("AuthenticationManager: createAuthentication(): description for locale "
+ + locale + " not found");
+ continue;
+ }
+ CMS.debug("AuthenticationManager: createAuthentication(): desc =" +
+ desc);
+ up.setParamDescription(locale, desc);
+ }
+
+ auth.setUiParam(id, up);
+ CMS.debug("AuthenticationManager: createAuthentication(): added param="
+ + id);
+
+ // map the auth mgr required cred to cred name in request message
+ IConfigStore credMapSub = uiParamSub.getSubStore(id + ".credMap");
+ if (credMapSub == null) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + uiParamSub.getName() + ".credMap" + " null or empty.");
+ continue;
+ }
+ String authCred = credMapSub.getString("authCred");
+ if (authCred.isEmpty()) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + credMapSub.getName() + ".authCred" + " null or empty.");
+ continue;
+ }
+
+ IConfigStore msgCredSub = credMapSub.getSubStore("msgCred");
+ if (msgCredSub == null) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + uiParamSub.getName() + ".msgCred" + " null or empty.");
+ continue;
+ }
+
+ String msgCred_login = msgCredSub.getString("login");
+ if (msgCred_login.isEmpty()) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + msgCredSub.getName() + ".login" + " null or empty.");
+ continue;
+ }
+ auth.setCredMap(authCred, msgCred_login,
+ false /* not extendedLogin*/);
+ CMS.debug("AuthenticationManager: createAuthentication(): added cred map_login="
+ + authCred + ":" + msgCred_login);
+
+ String msgCred_extlogin = msgCredSub.getString("extlogin");
+ if (msgCred_extlogin.isEmpty()) {
+ CMS.debug("AuthenticationManager: createAuthentication(): conf "
+ + msgCredSub.getName() + ".extlogin" + " null or empty.");
+ continue;
+ }
+
+ auth.setCredMap(authCred, msgCred_extlogin,
+ true /* extendedLogin*/);
+ CMS.debug("AuthenticationManager: createAuthentication(): added cred map_extlogin="
+ + authCred + ":" + msgCred_extlogin);
+
+ }
+
+ Integer retries = uiSub.getInteger("retries", 1);
+ auth.setNumOfRetries(retries.intValue());
+
+ CMS.debug("AuthenticationManager: createAuthentication(): completed for " +
+ authInstID);
+ return auth;
+ }
+
+ /*
+ * gets an established Authentication instance
+ */
+ public TPSAuthenticator getAuthInstance(String id) {
+ return authInstances.get(id);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java b/base/tps/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java
new file mode 100644
index 000000000..8d84cf5f6
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java
@@ -0,0 +1,148 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.authentication;
+
+import java.util.HashMap;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthSubsystem;
+import com.netscape.certsrv.base.EBaseException;
+
+/**
+ * Authentication is a class for an authentication instance
+ *
+ * @author cfu
+ */
+public class TPSAuthenticator {
+ private String id;
+ private IAuthManager authManager;
+
+ /*
+ * for auths instance ui <locale, value>
+ * e.g.
+ * auths.instance.ldap1.ui.description.en=
+ * This authenticates user against the LDAP directory.
+ * auths.instance.ldap1.ui.title.en=LDAP Authentication
+ */
+ private HashMap<String, String> uiTitle;
+ private HashMap<String, String> uiDescription;
+
+ private HashMap<String, AuthUIParameter> uiParameters;
+ /*
+ * credMap is for authentication manager required
+ * credential names (authCred) mapping to the
+ * client message credentail names (msgCred)
+ * e.g.
+ * auths.instance.ldap1.ui.id.UID.credMap.authCred=uid
+ * auths.instance.ldap1.ui.id.UID.credMap.msgCred=screen_name
+ * auths.instance.ldap1.ui.id.PASSWORD.credMap.authCred=pwd
+ * auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred=password
+ */
+ private HashMap<String, String> credMap_login;
+ private HashMap<String, String> credMap_extlogin;
+
+ // retries if the user entered the wrong password/securid
+ private int maxLoginRetries = 1;
+
+ private String authCredName;
+
+ /*
+ * Authentication constructor
+ * @param authId authentication instance id
+ */
+ public TPSAuthenticator(String authId)
+ throws EBaseException {
+ id = authId;
+ // retrieves and set authentication manager
+ IAuthSubsystem authSub =
+ (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH);
+ authManager = authSub.getAuthManager(authId);
+ uiTitle = new HashMap<String, String>();
+ uiDescription = new HashMap<String, String>();
+ uiParameters = new HashMap<String, AuthUIParameter>();
+ credMap_login = new HashMap<String, String>();
+ credMap_extlogin = new HashMap<String, String>();
+ }
+
+ public String getID() {
+ return id;
+ }
+
+ public IAuthManager getAuthManager() {
+ return authManager;
+ }
+
+ public void setUiTitle(String locale, String title) {
+ uiTitle.put(locale, title);
+ }
+
+ public String getUiTitle(String locale) {
+ return uiTitle.get(locale);
+ }
+
+ public void setUiDescription(String locale, String desc) {
+ uiDescription.put(locale, desc);
+ }
+
+ public String getUiDescription(String locale) {
+ return uiDescription.get(locale);
+ }
+
+ public void setUiParam(String id, AuthUIParameter up) {
+ uiParameters.put(id, up);
+ }
+
+ public AuthUIParameter getUiParam(String id) {
+ return uiParameters.get(id);
+ }
+
+ public HashMap<String, AuthUIParameter> getUiParamSet() {
+ return uiParameters;
+ }
+
+ public void setCredMap(String authCred, String msgCred, boolean extLogin) {
+ if (extLogin)
+ credMap_extlogin.put(authCred, msgCred);
+ else
+ credMap_login.put(authCred, msgCred);
+ }
+
+ public String getCredMap(String authCred, boolean extLogin) {
+ if (extLogin)
+ return credMap_extlogin.get(authCred);
+ else
+ return credMap_login.get(authCred);
+ }
+
+ public int getNumOfRetries() {
+ return maxLoginRetries;
+ }
+
+ public void setNumOfRetries(int num) {
+ maxLoginRetries = num;
+ }
+
+ public String getAuthCredName() {
+ return authCredName;
+ }
+
+ public void setAuthCredName(String authCredName) {
+ this.authCredName = authCredName;
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
new file mode 100644
index 000000000..7c3a01ba7
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java
@@ -0,0 +1,1045 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.channel;
+
+import java.io.IOException;
+
+import org.dogtagpki.server.tps.processor.TPSProcessor;
+import org.dogtagpki.tps.apdu.APDU;
+import org.dogtagpki.tps.apdu.APDUResponse;
+import org.dogtagpki.tps.apdu.CreateObjectAPDU;
+import org.dogtagpki.tps.apdu.CreatePinAPDU;
+import org.dogtagpki.tps.apdu.DeleteFileAPDU;
+import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU;
+import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
+import org.dogtagpki.tps.apdu.GenerateKeyAPDU;
+import org.dogtagpki.tps.apdu.GenerateKeyECCAPDU;
+import org.dogtagpki.tps.apdu.ImportKeyEncAPDU;
+import org.dogtagpki.tps.apdu.InstallAppletAPDU;
+import org.dogtagpki.tps.apdu.InstallLoadAPDU;
+import org.dogtagpki.tps.apdu.LifecycleAPDU;
+import org.dogtagpki.tps.apdu.LoadFileAPDU;
+import org.dogtagpki.tps.apdu.PutKeyAPDU;
+import org.dogtagpki.tps.apdu.ReadObjectAPDU;
+import org.dogtagpki.tps.apdu.SetIssuerInfoAPDU;
+import org.dogtagpki.tps.apdu.SetPinAPDU;
+import org.dogtagpki.tps.apdu.WriteObjectAPDU;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.main.Util;
+import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+import org.mozilla.jss.pkcs11.PK11SymKey;
+
+import sun.security.pkcs11.wrapper.PKCS11Constants;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+
+public class SecureChannel {
+
+ // Have not written all code to use all of these as of yet.
+
+ private TPSProcessor processor;
+ private PK11SymKey sessionKey;
+ private PK11SymKey encSessionKey;
+ private TPSBuffer drmDesKey;
+ private TPSBuffer kekDesKey;
+ private TPSBuffer keyCheck;
+ private TPSBuffer keyDiversificationData;
+ private TPSBuffer cardChallenge;
+ private TPSBuffer cardCryptogram;
+ private TPSBuffer hostChallenge;
+ private TPSBuffer hostCryptogram;
+ private TPSBuffer icv;
+ private TPSBuffer keyInfoData;
+ private SecurityLevel secLevel;
+
+ public enum TokenKeyType {
+ KEY_TYPE_ENCRYPTION,
+ KEY_TYPE_SIGNING,
+ KEY_TYPE_SIGNING_AND_ENCRYPTION
+ }
+
+ public SecureChannel(TPSProcessor processor, PK11SymKey sessionKey, PK11SymKey encSessionKey, TPSBuffer drmDesKey,
+ TPSBuffer kekDesKey, TPSBuffer keyCheck, TPSBuffer keyDiversificationData, TPSBuffer cardChallenge,
+ TPSBuffer cardCryptogram, TPSBuffer hostChallenge, TPSBuffer hostCryptogram, TPSBuffer keyInfoData)
+ throws TPSException {
+
+ if (processor == null || sessionKey == null | encSessionKey == null || keyDiversificationData == null
+ || cardChallenge == null || cardCryptogram == null || hostChallenge == null || hostCryptogram == null
+ || keyInfoData == null) {
+ throw new TPSException("SecureChannel.SecureChannel: Invalid data in constructor!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ this.processor = processor;
+ this.sessionKey = sessionKey;
+ this.encSessionKey = encSessionKey;
+ this.drmDesKey = drmDesKey;
+ this.setKekDesKey(kekDesKey);
+ this.keyCheck = keyCheck;
+ this.keyDiversificationData = keyDiversificationData;
+ this.cardChallenge = cardChallenge;
+ this.cardCryptogram = cardCryptogram;
+ this.hostChallenge = hostChallenge;
+ this.hostCryptogram = hostCryptogram;
+ this.icv = new TPSBuffer(8);
+ this.keyInfoData = keyInfoData;
+
+ this.secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
+ //ToDo: Write method that reads this from the config
+
+ }
+
+ public static void main(String[] args) {
+ }
+
+ public void appendPKCS11Attribute(TPSBuffer buffer, long type, TPSBuffer attribute) {
+
+ buffer.addLong4Bytes(type);
+
+ buffer.addInt2Bytes(attribute.size());
+ buffer.add(attribute);
+ }
+
+ public void appendKeyCapabilities(TPSBuffer buffer, String keyTypePrefix, String keyType) throws TPSException {
+
+ if (buffer == null || keyTypePrefix == null || keyType == null) {
+ throw new TPSException("SecureChannel.appdndKeyCabalities: Invalid input datat.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ final String keyCapabilities = "keyCapabilities";
+
+ try {
+
+ boolean value = false;
+ String configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "encrypt";
+
+ value = configStore.getBoolean(configName);
+
+ TPSBuffer attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_ENCRYPT, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "sign";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SIGN, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "signRecover";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SIGN_RECOVER, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "decrypt";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_DECRYPT, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "derive";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_DERIVE, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "unwrap";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_UNWRAP, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "wrap";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_WRAP, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "verifyRecover";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_VERIFY_RECOVER, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "verify";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_VERIFY, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "sensitive";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_SENSITIVE, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "private";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_PRIVATE, attr);
+
+ configName = keyTypePrefix + "." + keyType + "." + keyCapabilities + "." + "token";
+ value = configStore.getBoolean(configName);
+ attr = new TPSBuffer(Util.bool2Byte(value));
+ appendPKCS11Attribute(buffer, PKCS11Constants.CKA_TOKEN, attr);
+
+ CMS.debug("SecureChannel.appendKeyCapabilities: returning: " + buffer.toHexString());
+
+ } catch (EBaseException e) {
+ throw new TPSException("SecureChannel.appentKeyCapabilities. Can't obtain config value!",
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+ }
+
+ public void externalAuthenticate() throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.externalAuthenticate: entering.");
+
+ ExternalAuthenticateAPDU externalAuth = new ExternalAuthenticateAPDU(hostCryptogram,
+ secLevel);
+
+ computeAPDUMac(externalAuth);
+
+ APDUResponse response = processor.handleAPDURequest(externalAuth);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.eternalAuthenticate. Failed to external authenticate to token.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.externalAuthenticate: Successfully completed, exiting ...");
+
+ }
+
+ //This method computes the mac AND encryption if needed.
+ private void computeAPDU(APDU apdu) throws TPSException {
+
+ CMS.debug("SecureChannel.computeAPDU: entering..");
+
+ if (apdu == null) {
+ throw new TPSException("SecureChannel.computeAPDU: bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ computeAPDUMac(apdu);
+
+ if (secLevel == SecurityLevel.SECURE_MSG_MAC_ENC) {
+ try {
+ // CMS.debug("SecureChannel.computeAPDU: Before encryption data value: " + apdu.getData().toHexString());
+ apdu.secureMessage(encSessionKey);
+ // CMS.debug("SecureChannel.computeAPDU: After encryption data value: " + apdu.getData().toHexString());
+ } catch (EBaseException e) {
+ throw new TPSException("SecureChannel.computeAPDU: Can't encrypt outgoing data! " + e);
+ }
+
+ CMS.debug("SecureChannel.computeAPDU: Successfully encrypted apdu data.");
+ }
+ }
+
+ // This method computes MAC only.
+ private void computeAPDUMac(APDU apdu) throws TPSException {
+ TPSBuffer newMac = null;
+ TPSBuffer data = null;
+
+ if (apdu == null) {
+ throw new TPSException("SecureChannel.computeAPDUMac: bad input apdu!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ data = apdu.getDataToMAC();
+
+ CMS.debug("SecureChannel.computeAPDUMac: data To MAC: " + data.toHexString());
+
+ try {
+ newMac = Util.computeMAC(sessionKey, data, icv);
+ } catch (EBaseException e) {
+ CMS.debug("SecureChannel.compuatAPDUMac: Can't compute mac. " + e);
+ throw new TPSException("SecureChannel.compuatAPDUMac: Can't compute mac.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("SecureChannel.computeAPDUMac: computed MAC: " + newMac.toHexString());
+
+ apdu.setMAC(newMac);
+
+ icv.set(newMac);
+ }
+
+ public void deleteFileX(TPSBuffer aid) throws TPSException, IOException {
+ CMS.debug("SecureChannel.deleteFileX: entering...");
+ if (aid == null) {
+ throw new TPSException("SecureChannel.deleteFileX: no input aid!");
+ }
+
+ DeleteFileAPDU deleteFile = new DeleteFileAPDU(aid);
+
+ computeAPDU(deleteFile);
+
+ processor.handleAPDURequest(deleteFile);
+
+ }
+
+ // Begin process of loading applet onto token.
+ public void installLoad(TPSBuffer packageAID, TPSBuffer sdAID, int fileLength) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.installLoad: entering ...");
+
+ if (packageAID == null || sdAID == null || fileLength <= 0) {
+ throw new TPSException("SecureChannel.insallLoad bad input parameters!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ InstallLoadAPDU install = new InstallLoadAPDU(packageAID, sdAID, fileLength);
+
+ CMS.debug("SecureChannel.installLoad: Pre computed apdu: " + install.getEncoding().toHexString());
+
+ computeAPDU(install);
+
+ APDUResponse response = processor.handleAPDURequest(install);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.installLoad. Failed to perform installLoad operation.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ }
+
+ //Actually load applet file onto the token.
+
+ public void loadFile(TPSBuffer programFile, int blockSize, int startProgress, int endProgress) throws TPSException,
+ IOException {
+ CMS.debug("SecureChannel.loadFile entering...");
+
+ if (programFile == null || blockSize <= 0) {
+ throw new TPSException("ScureChannel.loadFile. Bad input data.", TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ TPSBuffer length = null;
+
+ TPSBuffer tag = new TPSBuffer(1, (byte) 0xC4);
+
+ int progSize = programFile.size();
+
+ if (progSize < 128) {
+ length = new TPSBuffer(1, (byte) progSize);
+ } else if (progSize <= 255) {
+ length = new TPSBuffer(1, (byte) 0x81);
+ length.add((byte) progSize);
+ } else {
+ length = new TPSBuffer(1, (byte) 0x82);
+ length.add((byte) ((progSize >> 8) & 0xff));
+ length.add((byte) (progSize & 0xff));
+
+ }
+
+ TPSBuffer tbsProgramFile = new TPSBuffer(tag);
+ tbsProgramFile.add(length);
+ tbsProgramFile.add(programFile);
+
+ int totalLen = tbsProgramFile.size();
+ int sizeToSend = totalLen;
+
+ int finalBlockSize = 0;
+ float progressBlockSize = 0;
+
+ if (secLevel == SecurityLevel.SECURE_MSG_MAC_ENC) {
+ // need leave room for possible encryption padding
+ finalBlockSize = blockSize - 0x10;
+ } else {
+ finalBlockSize = blockSize - 8;
+ }
+
+ //rough number is good enough
+ int numLoops = sizeToSend / blockSize;
+
+ if (numLoops == 0) { // We have bogus data here. Good bye.
+ throw new TPSException("SecureChannel.loadFile. Bad input data.", TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+ progressBlockSize = (float) (endProgress - startProgress) / numLoops;
+
+ int count = 0;
+ byte refControl = 0x00;
+
+ do {
+ if (sizeToSend < finalBlockSize) {
+ finalBlockSize = sizeToSend;
+ refControl = (byte) 0x80;
+
+ }
+
+ CMS.debug("SecureChannel.loadFile: taking data substring from: " + (totalLen - sizeToSend) + " size: "
+ + finalBlockSize + " to: " + ((totalLen - sizeToSend) + finalBlockSize));
+
+ TPSBuffer piece = tbsProgramFile.substr(totalLen - sizeToSend, finalBlockSize);
+
+ CMS.debug("SecureChannel.loadFile: attempting to send piece: " + sizeToSend);
+
+ loadFileSegment(refControl, count, piece);
+
+ if (processor.requiresStatusUpdate()) {
+ processor.statusUpdate(startProgress + (int) (count * progressBlockSize), "PROGRESS_APPLET_BLOCK");
+ }
+
+ sizeToSend -= finalBlockSize;
+
+ count++;
+
+ } while (sizeToSend > 0);
+
+ }
+
+ //Load one piece of the applet file onto the token.
+ private void loadFileSegment(byte refControl, int count, TPSBuffer piece) throws TPSException, IOException {
+
+ if (piece == null || count < 0) {
+ throw new TPSException("SecureChannel.loadFileSegment: invalid input data.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ LoadFileAPDU loadFile = new LoadFileAPDU(refControl, (byte) count, piece);
+
+ computeAPDU(loadFile);
+
+ APDUResponse response = processor.handleAPDURequest(loadFile);
+
+ if (!response.checkResult()) {
+ throw new TPSException(
+ "SecureChannel.loadFileSegment. Failed to perform loadFileSegmentInstallLoad operation.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ }
+
+ // Kick off the applet loading process.
+ public void installApplet(TPSBuffer netkeyPAIDBuff, TPSBuffer netkeyAIDBuff, byte appPrivileges,
+ int channelInstanceSize,
+ int channelAppletMemSize) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.installApplet: entering...");
+
+ // Would be tough to put a check on the various input sizes, let the applet
+ // decide if the values are appropriate for channelInstanceSize and channelAppletMemSize
+
+ if (netkeyPAIDBuff == null || netkeyAIDBuff == null || channelInstanceSize < 0 || channelAppletMemSize < 0) {
+ throw new TPSException("SecureChannel.installApplet. Invalid input parameters!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+ }
+
+ InstallAppletAPDU install = new InstallAppletAPDU(netkeyPAIDBuff, netkeyAIDBuff, appPrivileges,
+ channelInstanceSize, channelAppletMemSize);
+
+ computeAPDU(install);
+
+ APDUResponse response = processor.handleAPDURequest(install);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.installApplett. Failed installApplet operation.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ }
+
+ // Burn the phone home URL into the token.
+ public void setIssuerInfo(TPSBuffer issuerInfoBuff) throws TPSException, IOException {
+ CMS.debug("SecureChannel.setIssuerInfo entering...");
+
+ final int finalIssuerLength = 224;
+ final int approxMinUrlSize = 5;
+
+ if (issuerInfoBuff == null || issuerInfoBuff.size() < approxMinUrlSize) {
+ throw new TPSException("SecureChannel.setIssuerInfo: Invalid input data.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ int issuerLen = issuerInfoBuff.size();
+
+ int paddingLen = finalIssuerLength - issuerLen;
+
+ TPSBuffer paddingBuff = new TPSBuffer(paddingLen, (byte) 0x0);
+
+ TPSBuffer finalIssuerBuff = new TPSBuffer(issuerInfoBuff);
+
+ finalIssuerBuff.add(paddingBuff);
+
+ CMS.debug("finalIssuerBuff len: " + finalIssuerBuff.size() + " issuerInfo: " + finalIssuerBuff.toString());
+ SetIssuerInfoAPDU setIssuer = new SetIssuerInfoAPDU((byte) 0x0, (byte) 0x0, finalIssuerBuff);
+
+ computeAPDU(setIssuer);
+
+ APDUResponse response = processor.handleAPDURequest(setIssuer);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.setIssuerInfo. Failed to set issuer info!",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ CMS.debug("SecureChannel.setIssuerInfo: leaving...");
+
+ }
+
+ public TPSBuffer getKeyDiversificationData() {
+ return keyDiversificationData;
+ }
+
+ public TPSBuffer getCardChallenge() {
+ return cardChallenge;
+ }
+
+ public TPSBuffer getHostChallenge() {
+ return hostChallenge;
+ }
+
+ public TPSBuffer getHostCryptogram() {
+ return hostCryptogram;
+ }
+
+ public TPSBuffer getCardCryptogram() {
+ return cardCryptogram;
+ }
+
+ public TPSBuffer getKeyInfoData() {
+ return keyInfoData;
+ }
+
+ public void writeObject(TPSBuffer objectID, TPSBuffer objectData) throws TPSException, IOException {
+ CMS.debug("SecureChannel.writeObject: entering ...");
+
+ if (objectID == null || objectData == null) {
+ throw new TPSException("SecureChannel.writeObject: invalid input data.");
+ }
+
+ final int MAX_WRITE_SIZE = 0xd0;
+
+ int offset = 0;
+ int toSend = objectData.size();
+ int blockSize = 0;
+
+ boolean moreToGo = true;
+ do {
+
+ if (toSend > MAX_WRITE_SIZE) {
+ blockSize = MAX_WRITE_SIZE;
+ } else {
+ blockSize = toSend;
+ }
+
+ TPSBuffer blockToSend = objectData.substr(offset, blockSize);
+
+ WriteObjectAPDU write = new WriteObjectAPDU(objectID.toBytesArray(), offset, blockToSend);
+
+ computeAPDU(write);
+
+ APDUResponse response = processor.handleAPDURequest(write);
+
+ if (!response.checkResult()) {
+ CMS.debug("SecureChannel.writeObject: bad apdu return!");
+ //Throw this return code because this happens during enrollment and we don't have
+ // a more specific error code.
+ throw new TPSException("SecureChannel.writeObject. Failed in middle of writeObject.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ offset += blockSize;
+ toSend -= blockSize;
+
+ if (toSend <= 0) {
+ moreToGo = false;
+ }
+
+ } while (moreToGo);
+
+ }
+
+ public TPSBuffer readObject(TPSBuffer objectID, int offset, int len) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.readObject: entering ...");
+
+ if (objectID == null || len == 0) {
+ throw new TPSException("SecureChannel.readObject: invalid input data.",
+ TPSStatus.STATUS_ERROR_READ_OBJECT_PDU);
+ }
+
+ final int MAX_READ_BUFFER_SIZE = 0xd0;
+
+ ReadObjectAPDU read = null;
+ TPSBuffer result = new TPSBuffer();
+
+ int cur_read = 0;
+ int cur_offset = 0;
+ int sum = 0;
+
+ if (len > MAX_READ_BUFFER_SIZE) {
+ cur_offset = offset;
+ cur_read = MAX_READ_BUFFER_SIZE;
+ } else {
+ cur_offset = offset;
+ cur_read = len;
+ }
+
+ while (sum < len) {
+
+ read = new ReadObjectAPDU(objectID.toBytesArray(), cur_offset, cur_read);
+ computeAPDU(read);
+
+ APDUResponse response = processor.handleAPDURequest(read);
+
+ if (!response.checkResult()) {
+ CMS.debug("SecureChannel.readObject: bad apdu return!");
+ throw new TPSException("SecureChannel.installApplett. Failed in middle of readObject.",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ TPSBuffer resp = response.getResultDataNoCode();
+
+ result.add(resp);
+
+ sum += resp.size();
+ cur_offset += resp.size();
+
+ if ((len - sum) < MAX_READ_BUFFER_SIZE) {
+ cur_read = len - sum;
+ } else {
+ cur_read = MAX_READ_BUFFER_SIZE;
+ }
+
+ }
+
+ return result;
+ }
+
+ public void createObject(TPSBuffer objectID, TPSBuffer permissions, TPSBuffer object) throws TPSException,
+ IOException {
+
+ CMS.debug("SecureChannel.createObject: with full object. entering...");
+
+ if (objectID == null || permissions == null || object == null) {
+ throw new TPSException("SecureChannel.createObject, with full object. Bad input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+ }
+
+ createObject(objectID, permissions, object.size());
+
+ writeObject(objectID, object);
+
+ }
+
+ public void createCertificate(TPSBuffer objectID, TPSBuffer cert) throws TPSException, IOException {
+ CMS.debug("SecureChannel.createCertificate: entering...");
+
+ if (objectID == null || cert == null) {
+ throw new TPSException("SecureChannel.createCertificate. Bad input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 };
+
+ TPSBuffer permissions = new TPSBuffer(perms);
+
+ createObject(objectID, permissions, cert);
+
+ }
+
+ public void createPKCS11CertAttrs(TokenKeyType keyType, String id, String label, TPSBuffer keyid)
+ throws TPSException, IOException {
+
+ TPSBuffer buffer = createPKCS11CertAttrsBuffer(keyType, id, label, keyid);
+
+ byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 };
+
+ TPSBuffer permissions = new TPSBuffer(perms);
+
+ createObject(new TPSBuffer(id), permissions, buffer);
+
+ }
+
+ public TPSBuffer createPKCS11PriKeyAttrsBuffer(String id, String label, TPSBuffer keyid,
+ TPSBuffer modulus, String keyTypePrefix) throws TPSException {
+
+ TPSBuffer result = new TPSBuffer();
+
+ CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer: entering...");
+
+ if (id == null || label == null || keyid == null || modulus == null || keyTypePrefix == null) {
+ throw new TPSException("SecureChannel.craetePKCS11PriKeyAttrsBuffer: invalid input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer: id: " + id + " label: " + label + " keyid: "
+ + keyid.toHexString());
+
+ byte keytype[] = { 0, 0, 0, 0 };
+ byte p11class[] = { 3, 0, 0, 0 };
+
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_MODULUS, modulus);
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_KEY_TYPE, new TPSBuffer(keytype));
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_CLASS, new TPSBuffer(p11class));
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_ID, keyid);
+ appendKeyCapabilities(result, keyTypePrefix, "private");
+
+ finalizeObjectBuffer(result, id);
+
+ CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer: returing: " + result.toHexString());
+
+ return result;
+
+ }
+
+ public void createPKCS11PriKeyAttrs(String id, String label, TPSBuffer keyid,
+ TPSBuffer modulus, String keyTypePrefix) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.createPKCS11PriKeyAttrsBuffer: entering...");
+
+ if (id == null || label == null || keyid == null || modulus == null || keyTypePrefix == null) {
+ throw new TPSException("SecureChannel.craetePKCS11PriKeyAttrsBuffer: invalid input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ TPSBuffer buffer = createPKCS11PriKeyAttrsBuffer(id, label, keyid, modulus, keyTypePrefix);
+
+ byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 };
+
+ TPSBuffer permissions = new TPSBuffer(perms);
+
+ createObject(new TPSBuffer(id), permissions, buffer);
+ }
+
+ public TPSBuffer createPKCS11PublicKeyAttrsBuffer(String id, String label, TPSBuffer keyid,
+ TPSBuffer modulus, TPSBuffer exponent, String keyTypePrefix) throws TPSException {
+
+ TPSBuffer result = new TPSBuffer();
+ CMS.debug("SecureChannel.createPKCS11PublicKeyAttrsBuffer: entering...");
+
+ if (id == null || label == null || keyid == null || modulus == null || exponent == null
+ || keyTypePrefix == null) {
+ throw new TPSException("SecureChannel.craetePKCS11PublicKeyAttrsBuffer: invalid input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ byte p11class[] = { 2, 0, 0, 0 };
+
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_PUBLIC_EXPONENT, exponent);
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_MODULUS, modulus);
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_ID, keyid);
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_CLASS, new TPSBuffer(p11class));
+ appendKeyCapabilities(result, keyTypePrefix, "public");
+
+ finalizeObjectBuffer(result, id);
+
+ CMS.debug("SecureChannel.createPKCS11PublicKeyAttrsBuffer: returing: " + result.toHexString());
+
+ return result;
+
+ }
+
+ public void createPKCS11PublicKeyAttrs(String id, String label, TPSBuffer keyid,
+ TPSBuffer modulus, TPSBuffer exponent, String keyTypePrefix) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.createPKCS11PublicKeyAttrsBuffer: entering...");
+
+ if (id == null || label == null || keyid == null || modulus == null || exponent == null
+ || keyTypePrefix == null) {
+ throw new TPSException("SecureChannel.craetePKCS11PriKeyAttrsBuffer: invalid input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ TPSBuffer buffer = createPKCS11PriKeyAttrsBuffer(id, label, keyid, modulus, keyTypePrefix);
+
+ byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 };
+
+ TPSBuffer permissions = new TPSBuffer(perms);
+
+ createObject(new TPSBuffer(id), permissions, buffer);
+
+ }
+
+ public void finalizeObjectBuffer(TPSBuffer buffer, String id) {
+
+ TPSBuffer header = new TPSBuffer();
+
+ header.add((byte) 0);
+ header.add((byte) id.charAt(0));
+ header.add((byte) id.charAt(1));
+ header.add((byte) 0);
+ header.add((byte) 0);
+
+ header.add((byte) ((buffer.size()) / 256));
+ header.add((byte) ((buffer.size()) % 256));
+
+ buffer.prepend(header);
+
+ }
+
+ public TPSBuffer createPKCS11CertAttrsBuffer(TokenKeyType keyType, String id, String label, TPSBuffer keyid)
+ throws TPSException {
+
+ CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: entering... id: " + id);
+ if (keyType == null || id == null || label == null || keyid == null) {
+ throw new TPSException("SecureChannel.createPKCS11CertAttrsBuffer. Bad input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+ }
+
+ CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: ... id: " + id + " label: " + label + " keyid: "
+ + keyid.toHexString());
+
+ byte[] type = { 0x0, 0x0, 0x0, 0x0 };
+ byte[] p11class = { 0x1, 0x0, 0x0, 0x0 };
+ byte[] tokenFlag = { 0x1 };
+
+ TPSBuffer result = new TPSBuffer();
+
+ CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: label: " + label + " label bytes: "
+ + (new TPSBuffer(label)).toHexString());
+
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_LABEL, new TPSBuffer(label.getBytes()));
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_ID, keyid);
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_CERTIFICATE_TYPE, new TPSBuffer(type));
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_CLASS, new TPSBuffer(p11class));
+ appendPKCS11Attribute(result, PKCS11Constants.CKA_TOKEN, new TPSBuffer(tokenFlag));
+
+ finalizeObjectBuffer(result, id);
+
+ CMS.debug("SecureChannel.createPKCS11CertAttrsBuffer: returing: " + result.toHexString());
+
+ return result;
+
+ }
+
+ public void createObject(TPSBuffer objectID, TPSBuffer permissions, int len) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.createObject: entering...");
+ if (objectID == null || permissions == null || len <= 0) {
+ throw new TPSException("SecureChannel.createObject. Bad input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CreateObjectAPDU create = new CreateObjectAPDU(objectID.toBytesArray(), permissions.toBytesArray(), len);
+
+ computeAPDU(create);
+
+ APDUResponse response = processor.handleAPDURequest(create);
+
+ //Throw this return code because this happens during enrollment and we don't have
+ // a more specific error code.
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.createObject. Failed to create object on token.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ }
+
+ public int startEnrollment(int pe1, int pe2, TPSBuffer wrappedChallenge, TPSBuffer keyCheck, int algorithm,
+ int keySize, int option) throws TPSException, IOException {
+
+ if (wrappedChallenge == null) {
+ throw new TPSException("SecureChannel.startEnrollment. Bad input data.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("SecureChannel.startEnrollment: entering ...");
+
+ boolean isECC = processor.getTPSEngine().isAlgorithmECC(algorithm);
+
+ GenerateKeyAPDU generate_key_apdu = null;
+ GenerateKeyECCAPDU generate_ecc_key_apdu = null;
+
+ APDUResponse response = null;
+ if (isECC) {
+
+ generate_ecc_key_apdu = new GenerateKeyECCAPDU((byte) pe1, (byte) pe2, (byte) algorithm, keySize,
+ (byte) option, (byte) 0, wrappedChallenge, keyCheck);
+
+ computeAPDU(generate_ecc_key_apdu);
+
+ response = processor.handleAPDURequest(generate_ecc_key_apdu);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.startEnrollment. Failed generate key on token.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ } else {
+
+ generate_key_apdu = new GenerateKeyAPDU((byte) pe1, (byte) pe2, (byte) algorithm, keySize,
+ (byte) option, (byte) 0, wrappedChallenge, keyCheck);
+
+ computeAPDU(generate_key_apdu);
+
+ response = processor.handleAPDURequest(generate_key_apdu);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.startEnrollment. Failed generate key on token.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ }
+
+ TPSBuffer data = response.getData();
+
+ int size = data.getIntFrom2Bytes(0);
+
+ CMS.debug("SecureChannel.startEnrollment: returning key size: " + size);
+
+ return size;
+
+ }
+
+ public int tokenTypeToInt(TokenKeyType type) {
+
+ if (type == TokenKeyType.KEY_TYPE_ENCRYPTION)
+ return 0;
+
+ if (type == TokenKeyType.KEY_TYPE_SIGNING)
+ return 1;
+ else
+ return 2;
+ }
+
+ public void setLifeycleState(byte flag) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.setLifecycleState: flage: " + flag);
+
+ LifecycleAPDU life = new LifecycleAPDU(flag);
+
+ computeAPDU(life);
+
+ APDUResponse response = processor.handleAPDURequest(life);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.setLifecycleState. Failed to set Lifecycle State!.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ }
+
+ public void createPin(int pinNumber, int maxRetries, String pin) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.createPin: entering...");
+
+ if (pin == null) {
+ throw new TPSException("SecureChannel.createPin: invalid intput data.",
+ TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
+ }
+
+ TPSBuffer pinBuf = new TPSBuffer(pin.getBytes());
+ CreatePinAPDU create = new CreatePinAPDU((byte) pinNumber, (byte) maxRetries, pinBuf);
+
+ computeAPDU(create);
+
+ @SuppressWarnings("unused")
+ APDUResponse response = processor.handleAPDURequest(create);
+
+ //If the pin already exists we may get an error here, but we go on.
+
+ }
+
+ public void resetPin(int pinNumber, String new_pin) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.resetPin");
+
+ if (new_pin == null) {
+ throw new TPSException("SecureChannel.resetPin: invalid intput data.",
+ TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
+ }
+
+ TPSBuffer newPinBuf = new TPSBuffer(new_pin.getBytes());
+
+ SetPinAPDU reset = new SetPinAPDU((byte) 0x0, (byte) 0x0, newPinBuf);
+
+ computeAPDU(reset);
+
+ APDUResponse response = processor.handleAPDURequest(reset);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.resetPin: failed to reset pin.",
+ TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
+ }
+
+ }
+
+ public void putKeys(byte curVersion, byte curIndex, TPSBuffer keySetData) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.putKeys: entering..");
+
+ if (keySetData == null) {
+ throw new TPSException("SecureChannel.putKeys: Invalid input data!", TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+ }
+
+ byte keyVersion = curVersion;
+
+ if (curVersion == 0xff) {
+ keyVersion = 0x0;
+ }
+
+ PutKeyAPDU putKey = new PutKeyAPDU(keyVersion, (byte) (0x80 | curIndex), keySetData);
+
+ computeAPDU(putKey);
+
+ APDUResponse response = processor.handleAPDURequest(putKey);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.putKeys: failed to upgrade key set!",
+ TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+ }
+
+ }
+
+ public TPSBuffer getDRMWrappedDesKey() {
+ return drmDesKey;
+ }
+
+ public void setDRMWrappedDesKey(TPSBuffer drmDesKey) {
+ this.drmDesKey = drmDesKey;
+ }
+
+ public TPSBuffer getKeyCheck() {
+ return keyCheck;
+ }
+
+ public void setKeyCheck(TPSBuffer theKeyCheck) {
+ this.keyCheck = theKeyCheck;
+ }
+
+ public void importKeyEnc(int pe1, int pe2, TPSBuffer data) throws TPSException, IOException {
+
+ CMS.debug("SecureChannel.importKeyEnc entering...");
+
+ if(data == null) {
+ throw new TPSException("SecureChannel.importKeyEnc: Invalid input data!",TPSStatus.STATUS_ERROR_MAC_CERT_PDU);
+ }
+
+ ImportKeyEncAPDU importKeyEnc = new ImportKeyEncAPDU((byte)pe1,(byte) pe2, data);
+
+ computeAPDU(importKeyEnc);
+
+ APDUResponse response = processor.handleAPDURequest(importKeyEnc);
+
+ if (!response.checkResult()) {
+ throw new TPSException("SecureChannel.importKeyEnc: failed to import private key!",
+ TPSStatus.STATUS_ERROR_MAC_CERT_PDU);
+ }
+
+ }
+
+ public TPSBuffer getKekDesKey() {
+ return kekDesKey;
+ }
+
+ public void setKekDesKey(TPSBuffer kekDesKey) {
+ this.kekDesKey = kekDesKey;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/CAEnrollCertResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/CAEnrollCertResponse.java
new file mode 100644
index 000000000..9c83e0842
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/CAEnrollCertResponse.java
@@ -0,0 +1,52 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import netscape.security.x509.X509CertImpl;
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * CAEnrollCertResponse is the class for the response to
+ * CA Remote Request: enrollCertificate()
+ *
+ */
+public class CAEnrollCertResponse extends RemoteResponse
+{
+ public CAEnrollCertResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public String getCertB64() {
+ return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_b64);
+ }
+
+ public String getCertSerialHex() {
+ return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_serial);
+ }
+
+ public String getCertSubjectDN() {
+ return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN);
+ }
+
+ public X509CertImpl getCert() {
+ return (X509CertImpl) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_x509);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java
new file mode 100644
index 000000000..5851d2f69
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/CARemoteRequestHandler.java
@@ -0,0 +1,760 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.cert.CertificateException;
+import java.util.Hashtable;
+import java.util.List;
+
+import netscape.security.x509.RevocationReason;
+import netscape.security.x509.X509CertImpl;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.Util;
+import org.mozilla.jss.CryptoManager;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.crypto.X509Certificate;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmscore.connector.HttpConnector;
+import com.netscape.cmsutil.http.HttpResponse;
+import com.netscape.cmsutil.util.Utils;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * CARemoteRequestHandler is a class representing remote requests
+ * offered by the Certificate Authority (CA)
+ *
+ * @author cfu
+ */
+public class CARemoteRequestHandler extends RemoteRequestHandler
+{
+ public CARemoteRequestHandler(String connID)
+ throws EBaseException {
+ if (connID == null) {
+ throw new EBaseException("CARemoteRequestHandler: CARemoteRequestHandler(): connID null.");
+ }
+ connid = connID;
+ }
+
+ /**
+ * enrollCertificate enrolls a certificate in the CA
+ *
+ * @param pubKeybuf public key for enrollment
+ * @param uid uid for enrollment
+ * @param cuid token id
+ *
+ * @returns CAEnrollCertResponse
+ */
+ public CAEnrollCertResponse enrollCertificate(
+ TPSBuffer pubKeybuf,
+ String uid,
+ String cuid,
+ String tokenType,
+ String keyType)
+ throws EBaseException {
+
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): begins.");
+ if (pubKeybuf == null || uid == null || cuid == null) {
+ throw new EBaseException("CARemoteRequestHandler: enrollCertificate(): input parameter null.");
+ }
+
+ IConfigStore conf = CMS.getConfigStore();
+ String profileId =
+ conf.getString(TPSEngine.OP_ENROLL_PREFIX + "." +
+ tokenType + ".keyGen." +
+ keyType + ".ca.profileId");
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): sending request to CA");
+ String encodedPubKey = null;
+ try {
+ encodedPubKey = Util.uriEncode(CMS.BtoA(pubKeybuf.toBytesArray()));
+ } catch (Exception e) {
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): uriEncode of pubkey failed: " + e);
+ throw new EBaseException("CARemoteRequestHandler: enrollCertificate(): uriEncode of pubkey failed: " + e);
+ }
+ HttpResponse resp =
+ conn.send("enrollment",
+ IRemoteRequest.GET_XML + "=" +
+ true +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" +
+ cuid +
+ "&" + IRemoteRequest.CA_ENROLL_screenname + "=" +
+ uid +
+ "&" + IRemoteRequest.CA_ENROLL_publickey + "=" +
+ encodedPubKey +
+ "&" + IRemoteRequest.CA_ProfileId + "=" +
+ profileId);
+
+ String content = resp.getContent();
+
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): got content = " + content);
+
+ if (content != null && !content.equals("")) {
+ XMLObject xmlResponse =
+ getXMLparser(content);
+
+ Hashtable<String, Object> response =
+ new Hashtable<String, Object>();
+
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): received:" +
+ content);
+
+ /**
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ * Note: serverKeygen and !serverKeygen returns different set of
+ * response values so "missing" might not be bad
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = xmlResponse.getValue(IRemoteRequest.RESPONSE_STATUS_XML);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): Status not found.");
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): got content = " + content);
+ } else {
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): got Status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = xmlResponse.getValue("SubjectDN");
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN);
+ } else {
+ CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN = "
+ + value);
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN, value);
+ }
+
+ value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_serial);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.CA_RESPONSE_Certificate_serial);
+ } else {
+ CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_serial = 0x"
+ + value);
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_serial, value);
+ }
+
+ value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_b64);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler:: enrollCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.CA_RESPONSE_Certificate_b64);
+ } else {
+ try {
+ CMS.debug("CARemoteRequestHandler:: enrollCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_b64 = "
+ + value);
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_b64, value);
+ X509CertImpl newCert = new X509CertImpl(Utils.base64decode(value));
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_x509, newCert);
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): new cert parsed successfully");
+ } catch (Exception e) {
+ // we don't exit. Keep going.
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): exception:" + e);
+ }
+ }
+
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): ends.");
+ return new CAEnrollCertResponse(response);
+ } else {
+ CMS.debug("CARemoteRequestHandler: enrollCertificate(): no response content");
+ throw new EBaseException("CARemoteRequestHandler: enrollCertificate(): no response content.");
+ }
+ }
+
+ /**
+ * retrieveCertificate retrieves a certificate by serial number
+ *
+ * @param serialno the serial number of the cert to be retrieved
+ * @return CARetrieveCertResponse
+ */
+ public CARetrieveCertResponse retrieveCertificate(
+ BigInteger serialno)
+ throws EBaseException {
+
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): begins.");
+ if (serialno == null) {
+ throw new EBaseException("CARemoteRequestHandler: retrieveCertificate(): input parameter null.");
+ }
+
+ //ToDo: I"m not sure why these are not used, let's check this out.
+ //It's working though.
+
+ /*
+ IConfigStore conf = CMS.getConfigStore();
+ String configName = "tps.connector." + connid + ".uri.getBySerial";
+ String servlet = conf.getString(configName, "/ca/ee/ca/displayBySerial");
+ */
+
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): sending request to CA");
+ HttpResponse resp =
+ conn.send("getcert",
+ IRemoteRequest.GET_XML + "=" + true +
+ "&" + IRemoteRequest.CA_GET_CERT_B64CertOnly + "=" + true +
+ "&" + IRemoteRequest.CA_GET_CERT_SERIAL + "=" + serialno.toString());
+
+ String content = resp.getContent();
+ if (content != null && !content.equals("")) {
+ XMLObject xmlResponse =
+ getXMLparser(content);
+
+ Hashtable<String, Object> response =
+ new Hashtable<String, Object>();
+
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): received:" +
+ content);
+
+ /**
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = xmlResponse.getValue(IRemoteRequest.RESPONSE_STATUS_XML);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): Status not found.");
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): got content = " + content);
+ } else {
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): got Status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_chain_b64);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler:: retrieveCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.CA_RESPONSE_Certificate_chain_b64);
+ } else {
+ CMS.debug("CARemoteRequestHandler:: retrieveCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_chain_b64 = "
+ + value);
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_chain_b64, value);
+ try {
+ X509CertImpl newCert = new X509CertImpl(Utils.base64decode(value));
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_x509, newCert);
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): retrieved cert parsed successfully");
+ } catch (CertificateException e) {
+ // we don't exit. Keep going.
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): exception:" + e);
+ }
+ }
+
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): ends.");
+ return new CARetrieveCertResponse(response);
+ } else {
+ CMS.debug("CARemoteRequestHandler: retrieveCertificate(): no response content");
+ throw new EBaseException("CARemoteRequestHandler: retrieveCertificate(): no response content.");
+ }
+ }
+
+ /**
+ * renewCertificate renew a certificate by serial number
+ *
+ * @param serialno the serial number of the cert to be renewed
+ * @return CARenewCertResponse
+ */
+ public CARenewCertResponse renewCertificate(
+ BigInteger serialno,
+ String tokenType,
+ String keyType)
+ throws EBaseException {
+
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): begins.");
+ if (serialno == null) {
+ throw new EBaseException("CARemoteRequestHandler: renewCertificate(): input parameter null.");
+ }
+
+ IConfigStore conf = CMS.getConfigStore();
+
+ String profileId =
+ conf.getString(TPSEngine.OP_ENROLL_PREFIX + "." +
+ tokenType + ".renewal." +
+ keyType + ".ca.profileId");
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): sending request to CA");
+ HttpResponse resp =
+ conn.send("renewal",
+ IRemoteRequest.GET_XML + "=" + true +
+ "&" + IRemoteRequest.CA_RENEWAL + "=" + true +
+ "&" + IRemoteRequest.CA_RENEWAL_SerialNum + "=" + serialno.toString() +
+ "&" + IRemoteRequest.CA_ProfileId + "=" + profileId);
+
+ String content = resp.getContent();
+
+ if (content != null && !content.equals("")) {
+ XMLObject xmlResponse =
+ getXMLparser(content);
+
+ Hashtable<String, Object> response =
+ new Hashtable<String, Object>();
+
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): received:" +
+ content);
+
+ /**
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ * Note: serverKeygen and !serverKeygen returns different set of
+ * response values so "missing" might not be bad
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = xmlResponse.getValue(IRemoteRequest.RESPONSE_STATUS_XML);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): Status not found.");
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): got content = " + content);
+ } else {
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): got Status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = xmlResponse.getValue("SubjectDN");
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN);
+ } else {
+ CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN = "
+ + value);
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN, value);
+ }
+
+ value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_serial);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.CA_RESPONSE_Certificate_serial);
+ } else {
+ CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_serial = 0x"
+ + value);
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_serial, value);
+ }
+
+ value = xmlResponse.getValue(IRemoteRequest.CA_RESPONSE_Certificate_b64);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler:: renewCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.CA_RESPONSE_Certificate_b64);
+ } else {
+ CMS.debug("CARemoteRequestHandler:: renewCertificate(): got IRemoteRequest.CA_RESPONSE_Certificate_b64 = "
+ + value);
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_b64, value);
+ try {
+ X509CertImpl newCert = new X509CertImpl(Utils.base64decode(value));
+ response.put(IRemoteRequest.CA_RESPONSE_Certificate_x509, newCert);
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): new cert parsed successfully");
+ } catch (CertificateException e) {
+ // we don't exit. Keep going.
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): exception:" + e);
+ }
+ }
+
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): ends.");
+ return new CARenewCertResponse(response);
+ } else {
+ CMS.debug("CARemoteRequestHandler: renewCertificate(): no response content");
+ throw new EBaseException("CARemoteRequestHandler: renewCertificate(): no response content.");
+ }
+ }
+
+ /**
+ * revokeCertificate provides the basic revocation of a certificate from
+ * the CA
+ *
+ * @param serialno serial number of the cert to revoke
+ * @param reason reason to revoke per definition in RevocationReason
+ *
+ * @returns CARevokeCertResponse
+ */
+ private CARevokeCertResponse revokeCertificate(
+ String serialno,
+ RevocationReason reason)
+ throws EBaseException {
+
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): begins on serial#:"+ serialno);
+ if (serialno == null || reason == null) {
+ throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): input parameter null.");
+ }
+
+ // IConfigStore conf = CMS.getConfigStore();
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): sending request to CA");
+ HttpResponse resp =
+ conn.send("revoke",
+ IRemoteRequest.CA_OP + "=" + IRemoteRequest.CA_REVOKE +
+ "&" + IRemoteRequest.CA_REVOCATION_REASON + "=" + reason.getCode() +
+ "&" + IRemoteRequest.CA_REVOKE_ALL + "=(" +
+ IRemoteRequest.CA_REVOKE_SERIAL + "=" + serialno + ")&" +
+ IRemoteRequest.CA_REVOKE_COUNT + "=1");
+ String content = resp.getContent();
+
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): got content = " + content);
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /**
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): got status = " + value);
+ ist = Integer.parseInt(value);
+ if (ist != 0) {
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): status not 0, getting error string... ");
+ value = (String) response.get(IRemoteRequest.RESPONSE_ERROR_STRING);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.RESPONSE_ERROR_STRING);
+ } else {
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): got IRemoteRequest.RESPONSE_ERROR_STRING = "
+ + value);
+ response.put(IRemoteRequest.RESPONSE_ERROR_STRING, value);
+ }
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): ends.");
+ return new CARevokeCertResponse(response);
+ } else {
+ CMS.debug("CARemoteRequestHandler: revokeCertificate(): no response content.");
+ throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): no response content.");
+ }
+ }
+
+ /**
+ * unrevokeCertificate provides the basic unrevocation of a certificate from
+ * the CA
+ *
+ * @param serialno serial number of the cert to unrevoke
+ *
+ * @returns CARevokeCertResponse
+ */
+ private CARevokeCertResponse unrevokeCertificate(
+ String serialno)
+ throws EBaseException {
+
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): begins on serial#:"+ serialno);
+ if (serialno == null) {
+ throw new EBaseException("CARemoteRequestHandler: unrevokeCertificate(): input parameter null.");
+ }
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): sending request to CA");
+ HttpResponse resp =
+ conn.send("unrevoke",
+ IRemoteRequest.CA_UNREVOKE_SERIAL + "=" + serialno);
+ String content = resp.getContent();
+
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): got content = " + content);
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /**
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): got status = " + value);
+ ist = Integer.parseInt(value);
+ if (ist != 0) {
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): status not 0, getting error string... ");
+ value = (String) response.get(IRemoteRequest.RESPONSE_ERROR_STRING);
+ if (value == null) {
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): response missing name-value pair for: " +
+ IRemoteRequest.RESPONSE_ERROR_STRING);
+ } else {
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): got IRemoteRequest.RESPONSE_ERROR_STRING = "
+ + value);
+ response.put(IRemoteRequest.RESPONSE_ERROR_STRING, value);
+ }
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): ends.");
+ return new CARevokeCertResponse(response);
+ } else {
+ CMS.debug("CARemoteRequestHandler: unrevokeCertificate(): no response content.");
+ throw new EBaseException("CARemoteRequestHandler: unrevokeCertificate(): no response content.");
+ }
+ }
+
+ /**
+ * revokeFromOtherCA searches through all defined ca entries
+ * to find the cert's signing ca for revocation / unrevocation.
+ * It is called from revokeCertificate() when the cert's
+ * AKI does not match that of the current signing ca.
+ *
+ * @param revoke true to revoke; false to unrevoke
+ * @param cert cert to (un)revoke
+ * @param serialno parameter for the (Un)RevokeCertificate() functions
+ * @param reason RevocationReason for the base revokeCertificate() function
+ * @throws IOException
+ */
+ @SuppressWarnings("unused")
+ private CARevokeCertResponse revokeFromOtherCA(
+ boolean revoke, // true==revoke; false==unrevoke
+ X509CertImpl cert,
+ RevocationReason reason)
+ throws EBaseException, IOException {
+ if (cert == null) {
+ throw new EBaseException("CARemoteRequestHandler: revokeFromOtherCA(): input parameter cert null.");
+ }
+ String certAkiString = null;
+ try {
+ certAkiString = Util.getCertAkiString(cert);
+ } catch (Exception e) {
+ throw new EBaseException("CARemoteRequestHandler: revokeFromOtherCA(): getCertAkiString failed:" + e);
+ }
+ return revokeFromOtherCA(revoke, cert.getSerialNumber().toString(), certAkiString, reason);
+ }
+
+
+ private CARevokeCertResponse revokeFromOtherCA(
+ boolean revoke, // true==revoke; false==unrevoke
+ String serialno,
+ String certAkiString,
+ RevocationReason reason)
+ throws EBaseException {
+
+
+ CMS.debug("CARemoteRequestHandler: revokeFromOtherCA: begins");
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ List<String> caList =
+ subsystem.getConnectionManager().getCAList();
+
+ Exception exception = null;
+
+ for (String ca : caList) {
+ try {
+ String caSkiString = getCaSki(ca);
+ if (certAkiString.equals(caSkiString)) {
+ CMS.debug("CARemoteRequestHandler: revokeFromOtherCA() cert AKI and caCert SKI matched");
+ if (revoke) {
+ return revokeCertificate(serialno, reason);
+ } else {
+ return unrevokeCertificate(serialno);
+ }
+ } else { // not a match then iterate to next ca in list
+ CMS.debug("CARemoteRequestHandler: revokeFromOtherCA() cert AKI and caCert SKI not matched");
+ }
+ } catch (Exception e) {
+ // any issue then iterate to next ca in list
+ CMS.debug("CARemoteRequestHandler: revokeFromOtherCA() issue found, iterate to next ca in list. Exception:"
+ + e);
+ exception = e;
+ }
+ }
+ if (exception == null) {
+ throw new EBaseException("revokeFromOtherCA: signing ca not found");
+ } else {
+ throw new EBaseException(exception.toString());
+ }
+ }
+
+ /**
+ * getCaSki returns the CA's Subject Key Identifier (ski)
+ * associated with the connector id.
+ * If the ca's ski has not been calculated, it will do so and
+ * save to the connector's caSKI config entry
+ *
+ * @param conn connector id
+ * @returns ca's ski associated with conn
+ */
+ private String getCaSki(String conn)
+ throws EBaseException, IOException {
+
+ String caSkiString = null;
+ if (conn == null) {
+ throw new EBaseException("CARemoteRequestHandler: getCaSki(): input parameter conn null.");
+ }
+
+ IConfigStore conf = CMS.getConfigStore();
+
+ /*
+ * first, see if ca Subject Key Identifier (SKI) is in
+ * config store. If not, put it in, so we don't have to
+ * calculate that every time.
+ */
+ try {
+ String configName = "tps.connector." + conn + ".caSKI";
+ CMS.debug("CARemoteRequestHandler: getCaSki() retriving configName=" + configName);
+ return conf.getString(configName);
+ } catch (EPropertyNotFound e) {
+ // caSKI not yet calculated; proceed to calculate
+ CMS.debug("CARemoteRequestHandler: getCaSki() caSKI not yet calculated:" + e);
+ } catch (EBaseException e) {
+ throw e;
+ }
+
+ try {
+ String caNickname =
+ conf.getString("tps.connector." + conn + ".caNickname");
+ CMS.debug("CARemoteRequestHandler: getCaSki() Calculating caSKI...searching for ca cert in nss db:"
+ + caNickname);
+ CryptoManager cm = CryptoManager.getInstance();
+ try {
+ X509Certificate c = cm.findCertByNickname(caNickname);
+ X509CertImpl caCert = new X509CertImpl(c.getEncoded());
+ // now retrieve caSKI and store in config
+ caSkiString = Util.getCertSkiString(caCert);
+ CMS.debug("CARemoteRequestHandler: getCaSki() caSKI calculated. Saving it.");
+ conf.putString("tps.connector." + conn + ".caSKI", caSkiString);
+ conf.commit(false);
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception et) {
+ /* ca cert not found in nss db; no match needed */
+ CMS.debug("CARemoteRequestHandler: getCaSki() caSKI calculation failure." + et);
+ throw new EBaseException("CARemoteRequestHandler: getCaSki(): skip match.");
+ }
+ } catch (EBaseException e) {
+ /*
+ * if it gets here, that means config is missing both:
+ * 1. tps.connector.ca<n>.caSKI
+ * 2. tps.connector.ca<n>.caNickname
+ * now assume default of just using the issuing ca and
+ * no search performed
+ */
+ CMS.debug("CARemoteRequestHandler: getCaSki() caSKI calculation failure." + e);
+ throw e;
+ } catch (NotInitializedException e) {
+ CMS.debug("CARemoteRequestHandler: getCaSki() caSKI calculation failure." + e);
+ throw new EBaseException("CARemoteRequestHandler: getCaSki(): skip match.:" + e);
+ }
+
+ return caSkiString;
+ }
+
+
+
+ /**
+ * revokeCertificate() supports revocation routing by providing
+ * CA discovery. When needed, it searchs through all listed ca
+ * entries to find the cert's signing ca for revocation.
+ *
+ * Note: in the configuration, the ca signing cert of each ca
+ * id must be imported into the db and have its nickname present.
+ * e.g. tps.connector.ca1.caNickname=CA1nickname
+ *
+ * See design:
+ * http://pki.fedoraproject.org/wiki/TPS_-_Revocation_Routing
+ *
+ * @param revoke true to revoke; false to unrevoke
+ * @param serialno serial number for the (Un)RevokeCertificate() functions
+ * @param reason RevocationReason for the base revokeCertificate() function
+ */
+ public CARevokeCertResponse revokeCertificate(
+ boolean revoke, // true==revoke; false==unrevoke
+ X509CertImpl cert,
+ RevocationReason reason)
+ throws EBaseException {
+ if (cert == null) {
+ throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): input parameter cert null.");
+ }
+ String certAkiString = null;
+ try {
+ certAkiString = Util.getCertAkiString(cert);
+ } catch (IOException e) {
+ throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): getCertAkiString failed:" + e);
+ }
+
+ return revokeCertificate(revoke, cert.getSerialNumber().toString(), certAkiString, reason);
+ }
+
+ public CARevokeCertResponse revokeCertificate(
+ boolean revoke, // true==revoke; false==unrevoke
+ String serialno,
+ String certAkiString,
+ RevocationReason reason)
+ throws EBaseException {
+
+ CMS.debug("CARemoteRequestHandler: revokeCertificate() begins with CA discovery");
+
+ if (revoke == true && reason == null) {
+ throw new EBaseException("CARemoteRequestHandler: revokeCertificate(): input parameter reason null.");
+ }
+
+ boolean skipMatch = false;
+
+ String caSkiString = null;
+
+ try {
+ caSkiString = getCaSki(connid);
+ } catch (Exception e) {
+ CMS.debug("CARemoteRequestHandler: revokeCertificate() exception:" + e);
+ skipMatch = true;
+ }
+ if (!skipMatch) {
+ /* now compare cert's AKI to the ca's SKI
+ * if matched, continue,
+ * if not, search in the ca list
+ */
+ CMS.debug("CARemoteRequestHandler: revokeCertificate() cert AKI and caCert SKI matching begins");
+ if (certAkiString.equals(caSkiString)) {
+ CMS.debug("CARemoteRequestHandler: revokeCertificate() cert AKI and caCert SKI matched");
+ if (revoke) {
+ return revokeCertificate(serialno, reason);
+ } else {
+ return unrevokeCertificate(serialno);
+ }
+ } else {
+ CMS.debug("CARemoteRequestHandler: revokeCertificate() cert AKI and caCert SKI of the designated issuing ca do not match...calling revokeFromOtherCA to search for another ca");
+ return revokeFromOtherCA(revoke, serialno, certAkiString, reason);
+ }
+ } else {
+ if (revoke) {
+ return revokeCertificate(serialno, reason);
+ } else {
+ return unrevokeCertificate(serialno);
+ }
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/CARenewCertResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/CARenewCertResponse.java
new file mode 100644
index 000000000..bb9ebbb44
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/CARenewCertResponse.java
@@ -0,0 +1,52 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import netscape.security.x509.X509CertImpl;
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * CARenewCertResponse is the class for the response to
+ * CA Remote Request: renewCertificate()
+ *
+ */
+public class CARenewCertResponse extends RemoteResponse
+{
+ public CARenewCertResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public String getRenewedCertB64() {
+ return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_b64);
+ }
+
+ public String getRenewedCertSerialHex() {
+ return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_serial);
+ }
+
+ public String getRenewedCertSubjectDN() {
+ return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_SubjectDN);
+ }
+
+ public X509CertImpl getRenewedCert() {
+ return (X509CertImpl) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_x509);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/CARetrieveCertResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/CARetrieveCertResponse.java
new file mode 100644
index 000000000..a356907fa
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/CARetrieveCertResponse.java
@@ -0,0 +1,45 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import netscape.security.x509.X509CertImpl;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * CARetrieveCertResponse is the class for the response to
+ * CA Remote Request: retrieveCertificate()
+ *
+ */
+public class CARetrieveCertResponse extends RemoteResponse
+{
+ public CARetrieveCertResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public String getCertB64() {
+ return (String) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_chain_b64);
+ }
+
+ public X509CertImpl getCert() {
+ return (X509CertImpl) nameValTable.get(IRemoteRequest.CA_RESPONSE_Certificate_x509);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/CARevokeCertResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/CARevokeCertResponse.java
new file mode 100644
index 000000000..d7db5976c
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/CARevokeCertResponse.java
@@ -0,0 +1,39 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * CARevokeCertResponse is the class for the response to
+ * CA Remote Request: revoteCertificate()
+ *
+ */
+public class CARevokeCertResponse extends RemoteResponse
+{
+ public CARevokeCertResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public String getErrorString() {
+ return (String) nameValTable.get(IRemoteRequest.RESPONSE_ERROR_STRING);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/ConnectionManager.java b/base/tps/src/org/dogtagpki/server/tps/cms/ConnectionManager.java
new file mode 100644
index 000000000..2b5ab2208
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/ConnectionManager.java
@@ -0,0 +1,229 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.connector.IConnector;
+import com.netscape.cmscore.connector.HttpConnector;
+import com.netscape.cmscore.connector.RemoteAuthority;
+
+/**
+ * ConnectionManager is a class for connection management
+ * of its Remote Authorities
+ *
+ * @author cfu
+ */
+public class ConnectionManager
+{
+ private Hashtable<String, IConnector> connectors;
+ List<String> caList;
+
+ public ConnectionManager() {
+ // initialize the ca list for revocation routing:
+ // tps.connCAList=ca1,ca2...ca<n>
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ IConfigStore conf = subsystem.getConfigStore();
+ String caListString;
+ try {
+ caListString = conf.getString("connCAList");
+ CMS.debug("ConnectionManager: ConnectionManager(): Initializing CA routing list");
+ } catch (EBaseException e) {
+ CMS.debug("ConnectionManager: ConnectionManager(): no connCAList for ca discovery. No revocation routing");
+ return;
+ }
+
+ caList = Arrays.asList(caListString.split(","));
+ CMS.debug("ConnectionManager: ConnectionManager(): CA routing list initialized.");
+ }
+
+ public List<String> getCAList() {
+ return caList;
+ }
+
+ /*
+ * connector establishment with multi-uri support
+ *
+ * Initialize all connectors
+ * tps.connector.<connID>.xxx
+ *
+ * e.g. (with Failover list under "host", separated by a space)
+ *
+ * tps.connector.ca1.enable=true
+ * tps.connector.ca1.minHttpConns=1
+ * tps.connector.ca1.maxHttpConns=15
+ * tps.connector.ca1.host=host1.EXAMPLE.com:8445 host2.EXAMPLE.com:8445
+ * tps.connector.ca1.port=<port number; unused if for failover case>
+ * tps.connector.ca1.nickName=subsystemCert cert-pki-tomcat TPS
+ * tps.connector.ca1.timeout=30
+ * # In the example below,
+ * # "enrollment", "getcert", "renewal", "revoke", and "unrevoke"
+ * # are what's being referred to as "op" in the multi-uri support code
+ * tps.connector.ca1.uri.enrollment=/ca/ee/ca/profileSubmitSSLClient
+ * tps.connector.ca1.uri.renewal=/ca/ee/ca/profileSubmitSSLClient
+ * tps.connector.ca1.uri.getcert=/ca/ee/ca/displayBySerial
+ * tps.connector.ca1.uri.revoke=/ca/ee/subsystem/ca/doRevoke
+ * tps.connector.ca1.uri.unrevoke=/ca/ee/subsystem/ca/doUnrevoke
+ */
+ public void initConnectors() throws EBaseException {
+ CMS.debug("ConnectionManager: initConnectors(): begins.");
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ IConfigStore conf = subsystem.getConfigStore();
+ IConfigStore connectorSubstore = conf.getSubStore("connector");
+ Enumeration<String> connector_enu = connectorSubstore.getSubStoreNames();
+ connectors = new Hashtable<String, IConnector>();
+ while (connector_enu.hasMoreElements()) {
+ String connectorID = connector_enu.nextElement();
+ CMS.debug("ConnectionManager: initConnectors(): initializing connector " + connectorID);
+ IConfigStore connectorConfig =
+ connectorSubstore.getSubStore(connectorID);
+ IConnector conn = null;
+ boolean enable = connectorConfig.getBoolean("enable", false);
+ if (!enable) {
+ CMS.debug("ConnectionManager: initConnectors(): connector disabled.");
+ continue;
+ }
+ CMS.debug("ConnectionManager: initConnectors(): connector enabled.");
+ conn = createConnector(connectorConfig);
+
+ connectors.put(connectorID, conn);
+ CMS.debug("ConnectionManager: initConnectors(): connector "
+ + connectorID +
+ " initialized.");
+ }
+ CMS.debug("ConnectionManager: initConnectors(): ends.");
+ }
+
+ /*
+ * Creates and returns a connector
+ *
+ * @param conf config store of the connector
+ * @return IConnector the connector if created successfully; null if not
+ */
+ private IConnector createConnector(IConfigStore conf)
+ throws EBaseException {
+ IConnector connector = null;
+
+ CMS.debug("ConnectionManager: createConnector(): begins.");
+ if (conf == null || conf.size() <= 0) {
+ CMS.debug("ConnectionManager: createConnector(): conf null or empty.");
+ throw new EBaseException("called with null config store");
+ }
+
+ String host = conf.getString("host");
+ if (host == null) {
+ CMS.debug("ConnectionManager: createConnector(): host not found in config.");
+ throw new EBaseException("host not found in config");
+ }
+ // port doesn't have to contain anything if failover supplied in host
+ int port = conf.getInteger("port");
+
+ Hashtable<String, String> uris = new Hashtable<String, String>();
+ IConfigStore uriSubstore = conf.getSubStore("uri");
+ if (uriSubstore == null) {
+ CMS.debug("ConnectionManager: createConnector(): uri(s) not found in config.");
+ throw new EBaseException("uri(s) not found in config");
+ }
+ CMS.debug("ConnectionManager: createConnector(): uriSubstore name=" + uriSubstore.getName() + " size ="
+ + uriSubstore.size());
+
+ Enumeration<String> uri_enu = uriSubstore.getPropertyNames();
+ while (uri_enu.hasMoreElements()) {
+ String op = uri_enu.nextElement();
+ if ((op != null) && !op.equals(""))
+ CMS.debug("ConnectionManager: createConnector(): op name=" + op);
+ else
+ continue;
+
+ String uriValue = uriSubstore.getString(op);
+ if ((uriValue != null) && !uriValue.equals(""))
+ CMS.debug("ConnectionManager: createConnector(): uri value=" + uriValue);
+ else
+ continue;
+ uris.put(op, uriValue);
+ }
+
+ String nickname = conf.getString("nickName", null);
+ if (nickname != null)
+ CMS.debug("ConnectionManager: createConnector(): nickName=" + nickname);
+ else {
+ CMS.debug("ConnectionManager: createConnector(): nickName not found in config");
+ throw new EBaseException("nickName not found in config");
+ }
+
+ // "resendInterval" is for Request Queue, and not supported in TPS
+ int resendInterval = -1;
+ int timeout = conf.getInteger("timeout", 0);
+ RemoteAuthority remauthority =
+ new RemoteAuthority(host, port, uris, timeout, MediaType.APPLICATION_FORM_URLENCODED);
+
+ CMS.debug("ConnectionManager: createConnector(): establishing HttpConnector");
+ if (timeout == 0) {
+ connector =
+ new HttpConnector(null, nickname, remauthority, resendInterval, conf);
+ } else {
+ connector =
+ new HttpConnector(null, nickname, remauthority, resendInterval, conf, timeout);
+ }
+
+ CMS.debug("ConnectionManager: createConnector(): ends.");
+ return connector;
+ }
+
+ /*
+ * Gets an established connector to be used to send requests
+ * to a remote Authority (Note that Failover is supported in the
+ * underlying connector framework.
+ *
+ * Example usage (with example config for "ca1" defined above
+ * in initConnectors():
+ *
+ * TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ * HttpConnector testConn =
+ * (HttpConnector) subsystem.getConnectionManager().getConnector(connectionID);
+ * HttpResponse resp =
+ * testConn.send("renewal",
+ * "serial_num=6&profileId=caTokenUserEncryptionKeyRenewal&renewal=true");
+ * if (resp != null) {
+ * CMS.debug("Connector test: HttpResponse content:"+
+ * resp.getContent());
+ * } else {
+ * CMS.debug("Connector test: HttpResponse content null");
+ * }
+ *
+ * @param connID connection id per defined in the configuration
+ * @return IConnector the connector matching the connection id
+ */
+ public IConnector getConnector(String connID) {
+ return connectors.get(connID);
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/KRARecoverKeyResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/KRARecoverKeyResponse.java
new file mode 100644
index 000000000..9d0c5ff5f
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/KRARecoverKeyResponse.java
@@ -0,0 +1,51 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * KRARecoverKeyResponse is the class for the response to
+ * KRA Remote Request: recoverKey()
+ *
+ */
+public class KRARecoverKeyResponse extends RemoteResponse
+{
+ public KRARecoverKeyResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public String getErrorString() {
+ return (String) nameValTable.get(IRemoteRequest.RESPONSE_ERROR_STRING);
+ }
+
+ public String getPublicKey() {
+ return (String) nameValTable.get(IRemoteRequest.KRA_RESPONSE_PublicKey);
+ }
+
+ public String getWrappedPrivKey() {
+ return (String) nameValTable.get(IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey);
+ }
+
+ public String getIVParam() {
+ return (String) nameValTable.get(IRemoteRequest.KRA_RESPONSE_IV_Param);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java
new file mode 100644
index 000000000..87388ff99
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java
@@ -0,0 +1,322 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.server.tps.TPSSubsystem;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmscore.connector.HttpConnector;
+import com.netscape.cmsutil.http.HttpResponse;
+
+/**
+ * KRARemoteRequestHandler is a class representing remote requests
+ * offered by the Key Recovery Authority (KRA)
+ * On a successful return, name/value pairs are provided in a Hashtable where
+ * all contents are URL decoded if needed
+ *
+ * @author cfu
+ */
+public class KRARemoteRequestHandler extends RemoteRequestHandler
+{
+ public KRARemoteRequestHandler(String connID)
+ throws EBaseException {
+ if (connID == null) {
+ throw new EBaseException("KRARemoteRequestHandler: KRARemoteRequestHandler(): connID null.");
+ }
+
+ connid = connID;
+ }
+
+ /**
+ * serverSideKeyGen generates key pairs on the KRA
+ *
+ * @param cuid is the token id
+ * @param userid is the user id
+ * @param sDesKey is the des key provided by the TKS for key encryption
+ * @param archive true or false
+ *
+ * @returns KRAServerSideKeyGenResponse
+ */
+ public KRAServerSideKeyGenResponse serverSideKeyGen(
+ boolean isECC,
+ int keysize,
+ String cuid,
+ String userid,
+ String sDesKey,
+ boolean archive)
+ throws EBaseException {
+
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): begins.");
+ if (cuid == null || userid == null || sDesKey == null) {
+ throw new EBaseException("KRARemoteRequestHandler: serverSideKeyGen(): input parameter null.");
+ }
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): sending request to CA");
+ HttpResponse resp;
+ String request;
+ if (isECC) {
+ String eckeycurve;
+ if (keysize == 521) {
+ eckeycurve = "nistp521";
+ } else if (keysize == 384) {
+ eckeycurve = "nistp384";
+ } else if (keysize == 256) {
+ eckeycurve = "nistp256";
+ } else {
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): unrecognized ECC keysize" + keysize
+ + ", setting to nistp256");
+ keysize = 256;
+ eckeycurve = "nistp256";
+ }
+
+ request = IRemoteRequest.KRA_KEYGEN_Archive + "=" +
+ archive +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" +
+ cuid +
+ "&" + IRemoteRequest.KRA_UserId + "=" +
+ userid +
+ "&" + IRemoteRequest.KRA_KEYGEN_KeyType + "=" +
+ "EC" +
+ "&" + IRemoteRequest.KRA_KEYGEN_EC_KeyCurve + "=" +
+ eckeycurve +
+ "&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
+ sDesKey;
+
+ CMS.debug("KRARemoteRequestHandler: outgoing request for ECC: " + request);
+
+ resp =
+ conn.send("GenerateKeyPair",
+ request);
+ } else { // RSA
+
+ request = IRemoteRequest.KRA_KEYGEN_Archive + "=" +
+ archive +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" +
+ cuid +
+ "&" + IRemoteRequest.KRA_UserId + "=" +
+ userid +
+ "&" + IRemoteRequest.KRA_KEYGEN_KeyType + "=" +
+ "RSA" +
+ "&" + IRemoteRequest.KRA_KEYGEN_KeySize + "=" +
+ keysize +
+ "&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
+ sDesKey;
+
+ CMS.debug("KRARemoteRequestHandler: outgoing request for RSA: " + request);
+
+ resp =
+ conn.send("GenerateKeyPair",
+ request);
+ }
+
+ //For some reason the send method can return null and not throw an exception.
+ // Check here;
+
+ if(resp == null) {
+ throw new EBaseException("KRARemoteRequestHandler: serverSideKeyGen(): No response object returned from connection.");
+ }
+
+ String content = resp.getContent();
+
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): got content = " + content);
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /**
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ * Note: response values "missing" might not be bad for some cases
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+
+ if(value == null) {
+ throw new EBaseException("KRARemoteRequestHandler: serverSideKeyGen(): Invalide status returned!");
+ }
+
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): got status = " + value);
+ ist = Integer.parseInt(value);
+ if (ist != 0) {
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): status not 0, getting error string... ");
+ value = (String) response.get(IRemoteRequest.RESPONSE_ERROR_STRING);
+ if (value == null) {
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): response missing name-value pair for: " +
+ IRemoteRequest.RESPONSE_ERROR_STRING);
+ } else {
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): got IRemoteRequest.RESPONSE_ERROR_STRING = "
+ + value);
+ response.put(IRemoteRequest.RESPONSE_ERROR_STRING, value);
+ }
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = (String) response.get(IRemoteRequest.KRA_RESPONSE_PublicKey);
+ if (value == null) {
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): response missing name-value pair for: " +
+ IRemoteRequest.KRA_RESPONSE_PublicKey);
+ } else {
+ CMS.debug("KRARemoteRequestHandler:serverSideKeyGen(): got IRemoteRequest.KRA_RESPONSE_PublicKey= "
+ + value);
+ response.put(IRemoteRequest.KRA_RESPONSE_PublicKey, value);
+ }
+
+ value = (String) response.get(IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey);
+ if (value == null) {
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): response missing name-value pair for: " +
+ IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey);
+ } else {
+ CMS.debug("KRARemoteRequestHandler:serverSideKeyGen(): got IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey= "
+ + value);
+ response.put(IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey, value);
+ }
+
+ value = (String) response.get(IRemoteRequest.KRA_RESPONSE_IV_Param);
+ if (value == null) {
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): response missing name-value pair for: " +
+ IRemoteRequest.KRA_RESPONSE_IV_Param);
+ } else {
+ CMS.debug("KRARemoteRequestHandler:serverSideKeyGen(): got IRemoteRequest.KRA_RESPONSE_IV_Param= "
+ + value);
+ response.put(IRemoteRequest.KRA_RESPONSE_IV_Param, value);
+ }
+
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): ends.");
+ return new KRAServerSideKeyGenResponse(response);
+ } else {
+ CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): no response content.");
+ throw new EBaseException("KRARemoteRequestHandler: serverSideKeyGen(): no response content.");
+ }
+
+ }
+
+ /**
+ * recoverKey recovers keys from KRA
+ *
+ * @param cuid is the token id
+ * @param userid is the user id
+ * @param sDesKey is the des key provided by the TKS for key encryption
+ * @param b64cert is the Base64 encoding of a certificate used to recover
+ *
+ * @returns KRARecoverKeyResponse
+ */
+ public KRARecoverKeyResponse recoverKey(
+ String cuid,
+ String userid,
+ String sDesKey,
+ String b64cert)
+ throws EBaseException {
+
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): begins.");
+ if (cuid == null || userid == null || sDesKey == null || b64cert == null) {
+ throw new EBaseException("KRARemoteRequestHandler: recoverKey(): input parameter null.");
+ }
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): sending request to CA");
+
+ HttpResponse resp =
+ conn.send("TokenKeyRecovery",
+ "&" + IRemoteRequest.TOKEN_CUID + "=" +
+ cuid +
+ "&" + IRemoteRequest.KRA_UserId + "=" +
+ userid +
+ "&" + IRemoteRequest.KRA_RECOVERY_CERT + "=" +
+ b64cert +
+ "&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
+ sDesKey);
+
+ String content = resp.getContent();
+
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): got content = " + content);
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /**
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ * Note: response values "missing" might not be bad for some cases
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): got status = " + value);
+ ist = Integer.parseInt(value);
+ if (ist != 0) {
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): status not 0, getting error string... ");
+ value = (String) response.get(IRemoteRequest.RESPONSE_ERROR_STRING);
+ if (value == null) {
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): response missing name-value pair for: " +
+ IRemoteRequest.RESPONSE_ERROR_STRING);
+ } else {
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): got IRemoteRequest.RESPONSE_ERROR_STRING = "
+ + value);
+ response.put(IRemoteRequest.RESPONSE_ERROR_STRING, value);
+ }
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = (String) response.get(IRemoteRequest.KRA_RESPONSE_PublicKey);
+ if (value == null) {
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): response missing name-value pair for: " +
+ IRemoteRequest.KRA_RESPONSE_PublicKey);
+ } else {
+ CMS.debug("KRARemoteRequestHandler:recoverKey(): got IRemoteRequest.KRA_RESPONSE_PublicKey= " + value);
+ response.put(IRemoteRequest.KRA_RESPONSE_PublicKey, value);
+ }
+
+ value = (String) response.get(IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey);
+ if (value == null) {
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): response missing name-value pair for: " +
+ IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey);
+ } else {
+ CMS.debug("KRARemoteRequestHandler:recoverKey(): got IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey= "
+ + value);
+ response.put(IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey, value);
+ }
+
+ value = (String) response.get(IRemoteRequest.KRA_RESPONSE_IV_Param);
+ if (value == null) {
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): response missing name-value pair for: " +
+ IRemoteRequest.KRA_RESPONSE_IV_Param);
+ } else {
+ CMS.debug("KRARemoteRequestHandler:recoverKey(): got IRemoteRequest.KRA_RESPONSE_IV_Param= " + value);
+ response.put(IRemoteRequest.KRA_RESPONSE_IV_Param, value);
+ }
+
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): ends.");
+ return new KRARecoverKeyResponse(response);
+ } else {
+ CMS.debug("KRARemoteRequestHandler: recoverKey(): no response content.");
+ throw new EBaseException("KRARemoteRequestHandler: recoverKey(): no response content.");
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/KRAServerSideKeyGenResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/KRAServerSideKeyGenResponse.java
new file mode 100644
index 000000000..1836bcdbd
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/KRAServerSideKeyGenResponse.java
@@ -0,0 +1,51 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * KRAServerSideKeyGenResponse is the class for the response to
+ * KRA Remote Request: serverSideKeyGen()
+ *
+ */
+public class KRAServerSideKeyGenResponse extends RemoteResponse
+{
+ public KRAServerSideKeyGenResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public String getErrorString() {
+ return (String) nameValTable.get(IRemoteRequest.RESPONSE_ERROR_STRING);
+ }
+
+ public String getPublicKey() {
+ return (String) nameValTable.get(IRemoteRequest.KRA_RESPONSE_PublicKey);
+ }
+
+ public String getWrappedPrivKey() {
+ return (String) nameValTable.get(IRemoteRequest.KRA_RESPONSE_Wrapped_PrivKey);
+ }
+
+ public String getIVParam() {
+ return (String) nameValTable.get(IRemoteRequest.KRA_RESPONSE_IV_Param);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/RemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/RemoteRequestHandler.java
new file mode 100644
index 000000000..ceed1c11c
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/RemoteRequestHandler.java
@@ -0,0 +1,91 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.io.ByteArrayInputStream;
+import java.util.Hashtable;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmsutil.xml.XMLObject;
+
+/**
+ * RemoteRequestHandler is the base class for the remote authorities
+ *
+ * @author cfu
+ */
+public abstract class RemoteRequestHandler
+{
+ private static final String RESPONSE_SEPARATOR = "\\&";
+ private static final String NAME_VALUE_EQUAL = "=";
+
+ protected String connid;
+
+ /**
+ * parseResponse parses remote responses that take the form of '&'-separated
+ * name-value pairs
+ *
+ * @param content The exact string content in the HTTP response
+ * @return name-value pairs in a Hashtable
+ */
+ protected Hashtable<String, Object> parseResponse(String content)
+ throws EBaseException {
+ CMS.debug("RemoteRequestHandler: parseResponse(): begins:");
+ if (content == null) {
+ throw new EBaseException("RemoteRequestHandler: parserResponse(): no response content.");
+ }
+ Hashtable<String, Object> vars = new Hashtable<String, Object>();
+ String[] elements = content.split(RESPONSE_SEPARATOR);
+ CMS.debug("RemoteRequestHandler: parseResponse(): # of elements:" +
+ elements.length);
+ for (String nvs : elements) {
+ String[] nv = nvs.split(NAME_VALUE_EQUAL);
+ if (nv.length == 2) {
+ vars.put(nv[0], nv[1]);
+ } else {
+ // continue to parse through
+ CMS.debug("RemoteRequestHandler: parseResponse(): content contains element not conforming to <name>=<value>.");
+ }
+ }
+ return vars;
+ }
+
+ /**
+ * Get the XML parser for XML in text
+ *
+ * @param text XML in text
+ * @return XMLObject the parser
+ */
+ protected XMLObject getXMLparser(String text) {
+ if (text == null) {
+ return null;
+ } else {
+ CMS.debug("RemoteRequestHandler: getXMLparser(): parsing: " + text);
+ }
+ try {
+ ByteArrayInputStream bis =
+ new ByteArrayInputStream(text.getBytes());
+ return new XMLObject(bis);
+ } catch (Exception e) {
+ CMS.debug("RemoteRequestHandler: getXMLparser(): failed: " + e);
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/RemoteResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/RemoteResponse.java
new file mode 100644
index 000000000..c2c7818b0
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/RemoteResponse.java
@@ -0,0 +1,40 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * RemoteResponse is the base class for remote requests
+ *
+ */
+public abstract class RemoteResponse
+{
+ protected Hashtable<String, Object> nameValTable;
+
+ public int getStatus() {
+ Integer iValue = (Integer) nameValTable.get(IRemoteRequest.RESPONSE_STATUS);
+ if (iValue == null)
+ return IRemoteRequest.RESPONSE_STATUS_NOT_FOUND;
+ else
+ return iValue.intValue();
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java
new file mode 100644
index 000000000..f241c88ad
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeRandomDataResponse.java
@@ -0,0 +1,41 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.tps.main.TPSBuffer;
+
+/**
+ * TKSComputeRandomDataResponse is the class for the response to
+ * TKS Remote Request: computeRandomData()
+ *
+ */
+public class TKSComputeRandomDataResponse extends RemoteResponse
+{
+ public TKSComputeRandomDataResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public TPSBuffer getRandomData() {
+ byte [] random = (byte[]) nameValTable.get(IRemoteRequest.TKS_RESPONSE_RandomData);
+ return new TPSBuffer(random);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
new file mode 100644
index 000000000..2fe382539
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java
@@ -0,0 +1,65 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.tps.main.TPSBuffer;
+
+/**
+ * TKSComputeSessionKeyResponse is the class for the response to
+ * TKS Remote Request: computeSessionKey()
+ *
+ */
+public class TKSComputeSessionKeyResponse extends RemoteResponse
+{
+
+ public TKSComputeSessionKeyResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public TPSBuffer getKeySetData() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeySetData);
+ }
+
+ public TPSBuffer getSessionKey() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_SessionKey);
+ }
+
+ public TPSBuffer getEncSessionKey() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_EncSessionKey);
+ }
+
+ public TPSBuffer getDRM_Trans_DesKey() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+ }
+
+ public TPSBuffer getKeyCheck() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeyCheck);
+ }
+
+ public TPSBuffer getHostCryptogram() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+ }
+
+ public TPSBuffer getKekWrappedDesKey() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSCreateKeySetDataResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSCreateKeySetDataResponse.java
new file mode 100644
index 000000000..f887c63bb
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSCreateKeySetDataResponse.java
@@ -0,0 +1,41 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.tps.main.TPSBuffer;
+
+/**
+ * TKSCreateKeySetDataResponse is the class for the response to
+ * TKS Remote Request: createKeySetData
+ *
+ */
+public class TKSCreateKeySetDataResponse extends RemoteResponse
+{
+
+ public TKSCreateKeySetDataResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public TPSBuffer getKeySetData() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeySetData);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSEncryptDataResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSEncryptDataResponse.java
new file mode 100644
index 000000000..7dba17148
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSEncryptDataResponse.java
@@ -0,0 +1,41 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.tps.main.TPSBuffer;
+
+/**
+ * TKSEncryptDataResponse is the class for the response to
+ * TKS Remote Request: encryptData
+ *
+ */
+public class TKSEncryptDataResponse extends RemoteResponse
+{
+
+ public TKSEncryptDataResponse(Hashtable<String, Object> ht) {
+ nameValTable = ht;
+ }
+
+ public TPSBuffer getEncryptedData() {
+ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_EncryptedData);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
new file mode 100644
index 000000000..3c371a45e
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java
@@ -0,0 +1,448 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.Util;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmscore.connector.HttpConnector;
+import com.netscape.cmsutil.http.HttpResponse;
+
+/**
+ * TKSRemoteRequestHandler is a class representing remote requests
+ * offered by the Token Key Service Authority (TKS)
+ * On a successful return, name/value pairs are provided in a Hashtable where
+ * all contents are URL decoded if needed
+ *
+ * @author cfu
+ */
+public class TKSRemoteRequestHandler extends RemoteRequestHandler
+{
+ public TKSRemoteRequestHandler(String connID)
+ throws EBaseException {
+
+ if (connID == null) {
+ throw new EBaseException("TKSRemoteRequestHandler: TKSRemoteRequestHandler(): connID null.");
+ }
+
+ connid = connID;
+ }
+
+ /*
+ * computeSessionKey
+ *
+ * Usage Example:
+ * TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+ * TKSComputeSessionKeyResponse responseObj =
+ * tksReq.computeSessionKey(
+ * cuid,
+ * keyInfo,
+ * card_challenge,
+ * card_cryptogram,
+ * host_challenge);
+ * - on success return, one can say
+ * TPSBuffer value = responseObj.getSessionKey();
+ * to get response param value session key
+ *
+ * @param cuid token cuid
+ * @param keyInfo keyInfo
+ * @param card_challenge card challenge
+ * @param card_cryptogram card cryptogram
+ * @param host_challenge host challenge
+ * @return response TKSComputeSessionKeyResponse class object
+ */
+ public TKSComputeSessionKeyResponse computeSessionKey(
+ TPSBuffer cuid,
+ TPSBuffer keyInfo,
+ TPSBuffer card_challenge,
+ TPSBuffer card_cryptogram,
+ TPSBuffer host_challenge,
+ String tokenType)
+ throws EBaseException {
+
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): begins.");
+ if (cuid == null || keyInfo == null || card_challenge == null
+ || card_cryptogram == null || host_challenge == null) {
+ throw new EBaseException("TKSRemoteRequestHandler: computeSessionKey(): input parameter null.");
+ }
+
+ IConfigStore conf = CMS.getConfigStore();
+
+ boolean serverKeygen =
+ conf.getBoolean("op.enroll." +
+ tokenType + ".keyGen.encryption.serverKeygen.enable",
+ false);
+ String keySet =
+ conf.getString("connector." + connid + "keySet", "defKeySet");
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+
+ String requestString = IRemoteRequest.SERVER_SIDE_KEYGEN + "=" + serverKeygen +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid) +
+ "&" + IRemoteRequest.TOKEN_CARD_CHALLENGE + "=" + Util.specialURLEncode(card_challenge) +
+ "&" + IRemoteRequest.TOKEN_HOST_CHALLENGE + "=" + Util.specialURLEncode(host_challenge) +
+ "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(keyInfo) +
+ "&" + IRemoteRequest.TOKEN_CARD_CRYPTOGRAM + "="
+ + Util.specialURLEncode(card_cryptogram.toBytesArray()) +
+ "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet;
+
+ CMS.debug("TKSRemoteRequestHandler.computeSessionKey: outgoing message: " + requestString);
+
+ HttpResponse resp =
+ conn.send("computeSessionKey",
+ requestString
+ );
+
+ String content = resp.getContent();
+
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /*
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ * Note: serverKeygen and !serverKeygen returns different set of
+ * response values so "missing" might not be bad
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): status not found.");
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got content = " + content);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_SessionKey);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_SessionKey);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_SessionKey = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_SessionKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_EncSessionKey);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_EncSessionKey);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_EncSessionKey = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_EncSessionKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_KEK_DesKey);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_KEK_DesKey = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_KEK_DesKey, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeyCheck);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_KeyCheck);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_KeyCheck = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_KeyCheck, Util.specialDecode(value));
+ }
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_HostCryptogram);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_HostCryptogram = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_HostCryptogram, Util.specialDecode(value));
+ }
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): ends.");
+
+ return new TKSComputeSessionKeyResponse(response);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): no response content.");
+ throw new EBaseException("TKSRemoteRequestHandler: computeSessionKey(): no response content.");
+ }
+ }
+
+ /*
+ * createKeySetData
+ *
+ * Usage Example:
+ * TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+ * TKSCreateKeySetDataResponse responseObj =
+ * tksReq.createKeySetData(
+ * NewMasterVer,
+ * version,
+ * cuid)
+ * - on success return, one can say
+ * TPSBuffer value = responseObj.getKeySetData();
+ * to get response param value keySetData
+ *
+ * @param NewMasterVer newKeyInfo
+ * @param version keyInfo
+ * @param cuid token cuid
+ * @return response TKSCreateKeySetDataResponse class object
+ */
+ public TKSCreateKeySetDataResponse createKeySetData(
+ TPSBuffer NewMasterVer,
+ TPSBuffer version,
+ TPSBuffer cuid)
+ throws EBaseException {
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): begins.");
+ if (cuid == null || NewMasterVer == null || version == null) {
+ throw new EBaseException("TKSRemoteRequestHandler: createKeySetData(): input parameter null.");
+ }
+
+ IConfigStore conf = CMS.getConfigStore();
+ String keySet =
+ conf.getString("connector." + connid + "keySet", "defKeySet");
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): sending request to tks.");
+ HttpResponse resp =
+ conn.send("createKeySetData",
+ IRemoteRequest.TOKEN_NEW_KEYINFO + "=" + Util.specialURLEncode(NewMasterVer) +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid) +
+ "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(version) +
+ "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet);
+
+ String content = resp.getContent();
+
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+ if (response == null) {
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): parseResponse returned null.");
+ return null;
+ }
+
+ /*
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): status not found.");
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): got content = " + content);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): got status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeySetData);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_KeySetData);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): got IRemoteRequest.TKS_RESPONSE_KeySetData = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_KeySetData, Util.specialDecode(value));
+ }
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): ends.");
+
+ return new TKSCreateKeySetDataResponse(response);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): no response content.");
+ throw new EBaseException("TKSRemoteRequestHandler: createKeySetData(): no response content.");
+ }
+ }
+
+ /*
+ * computeRandomData
+ *
+ * Usage Example:
+ * TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+ * TKSComputeRandomDataResponse responseObj =
+ * tksReq.computeRandomData(
+ * dataSize)
+ * - on success return, one can say
+ * TPSBuffer value = responseObj.getRandomData();
+ * to get response param value random data
+ *
+ * @param dataSize size of random data to be generated in number of bytes
+ * @return response TKSComputeRandomDataResponse class object
+ */
+ public TKSComputeRandomDataResponse computeRandomData(int dataSize)
+ throws EBaseException {
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): begins.");
+ /*
+ * check for absurd dataSize values
+ */
+ if (dataSize <= 0 || dataSize > 1024) {
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): invalid dataSize requested:" + dataSize);
+ throw new EBaseException("TKSRemoteRequestHandler: computeRandomData(): invalid dataSize requested");
+ }
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): sending request to tks.");
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ HttpResponse resp =
+ conn.send("computeRandomData",
+ IRemoteRequest.TOKEN_DATA_NUM_BYTES + "=" + dataSize);
+
+ String content = resp.getContent();
+
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /*
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): status not found.");
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): got content = " + content);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): got status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_RandomData);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_RandomData);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): got IRemoteRequest.TKS_RESPONSE_RandomData = "
+ + value);
+ response.put(IRemoteRequest.TKS_RESPONSE_RandomData, Util.uriDecodeFromHex(value));
+ }
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): ends.");
+
+ return new TKSComputeRandomDataResponse(response);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: computeRandomData(): no response content.");
+ throw new EBaseException("TKSRemoteRequestHandler: computeRandomData(): no response content.");
+ }
+ }
+
+ /*
+ * encryptData
+ *
+ * Usage Example:
+ * TKSRemoteRequestHandler tksReq = new TKSRemoteRequestHandler("tks1");
+ * TKSEncryptDataResponse responseObj =
+ * tksReq.encryptData(
+ * dataSize)
+ * - on success return, one can say
+ * TPSBuffer value = responseObj.getEncryptedData();
+ * to get response param value encrypted data
+ *
+ * @param cuid token cuid
+ * @param version keyInfo
+ * @param inData data to be encrypted
+ * @return response TKSEncryptDataResponse class object
+ */
+ public TKSEncryptDataResponse encryptData(
+ TPSBuffer cuid,
+ TPSBuffer version,
+ TPSBuffer inData)
+ throws EBaseException {
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): begins.");
+ if (cuid == null || version == null || inData == null) {
+ throw new EBaseException("TKSRemoteRequestHandler: encryptData(): input parameter null.");
+ }
+
+ IConfigStore conf = CMS.getConfigStore();
+
+ String keySet =
+ conf.getString("connector." + connid + "keySet", "defKeySet");
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ HttpConnector conn =
+ (HttpConnector) subsystem.getConnectionManager().getConnector(connid);
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): sending request to tks.");
+ HttpResponse resp =
+ conn.send("encryptData",
+ IRemoteRequest.TOKEN_DATA + "=" + Util.specialURLEncode(inData) +
+ "&" + IRemoteRequest.TOKEN_CUID + "=" + Util.specialURLEncode(cuid) +
+ "&" + IRemoteRequest.TOKEN_KEYINFO + "=" + Util.specialURLEncode(version) +
+ "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet);
+
+ String content = resp.getContent();
+
+ if (content != null && !content.equals("")) {
+ Hashtable<String, Object> response =
+ parseResponse(content);
+
+ /*
+ * When a value is not found in response, keep going so we know
+ * what else is missing
+ */
+ Integer ist = new Integer(IRemoteRequest.RESPONSE_STATUS_NOT_FOUND);
+ String value = (String) response.get(IRemoteRequest.RESPONSE_STATUS);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): status not found.");
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): got content = " + content);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): got status = " + value);
+ ist = Integer.parseInt(value);
+ }
+ response.put(IRemoteRequest.RESPONSE_STATUS, ist);
+
+ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_EncryptedData);
+ if (value == null) {
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): response missing name-value pair for: " +
+ IRemoteRequest.TKS_RESPONSE_EncryptedData);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): got IRemoteRequest.TKS_RESPONSE_EncryptedData = ");
+ response.put(IRemoteRequest.TKS_RESPONSE_EncryptedData, Util.specialDecode(value));
+ }
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): ends.");
+
+ return new TKSEncryptDataResponse(response);
+ } else {
+ CMS.debug("TKSRemoteRequestHandler: encryptData(): no response content.");
+ throw new EBaseException("TKSRemoteRequestHandler: encryptData(): no response content.");
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSResponse.java
new file mode 100644
index 000000000..37269c765
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSResponse.java
@@ -0,0 +1,40 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.cms;
+
+import java.util.Hashtable;
+
+import org.dogtagpki.server.connector.IRemoteRequest;
+
+/**
+ * TKSResponse is the base class for TKS remote requests
+ *
+ */
+public abstract class TKSResponse
+{
+ protected Hashtable<String, Object> nameValTable;
+
+ public int getStatus() {
+ Integer iValue = (Integer) nameValTable.get(IRemoteRequest.RESPONSE_STATUS);
+ if (iValue == null)
+ return IRemoteRequest.RESPONSE_STATUS_NOT_FOUND;
+ else
+ return iValue.intValue();
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/AuthenticatorDatabase.java b/base/tps/src/org/dogtagpki/server/tps/config/AuthenticatorDatabase.java
new file mode 100644
index 000000000..292b80afb
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/AuthenticatorDatabase.java
@@ -0,0 +1,143 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmscore.dbs.CSCfgDatabase;
+
+/**
+ * This class provides access to the authenticators in CS.cfg.
+ *
+ * @author Endi S. Dewata
+ */
+public class AuthenticatorDatabase extends CSCfgDatabase<AuthenticatorRecord> {
+
+ public AuthenticatorDatabase() {
+ super("Authenticator", "Authentication_Sources");
+ }
+
+ public AuthenticatorRecord createAuthenticatorRecord(ConfigDatabase configDatabase, ConfigRecord configRecord, String authenticatorID) throws EBaseException {
+ AuthenticatorRecord authenticatorRecord = new AuthenticatorRecord();
+ authenticatorRecord.setID(authenticatorID);
+
+ String status = getRecordStatus(authenticatorID);
+ authenticatorRecord.setStatus(status);
+
+ Map<String, String> properties = configDatabase.getProperties(configRecord, authenticatorID);
+ authenticatorRecord.setProperties(properties);
+ return authenticatorRecord;
+ }
+
+ @Override
+ public Collection<AuthenticatorRecord> findRecords(String filter) throws Exception {
+
+ Collection<AuthenticatorRecord> result = new ArrayList<AuthenticatorRecord>();
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ for (String authenticatorID : configRecord.getKeys()) {
+ if (filter != null && !authenticatorID.contains(filter)) continue;
+ AuthenticatorRecord authenticatorRecord = createAuthenticatorRecord(configDatabase, configRecord, authenticatorID);
+ result.add(authenticatorRecord);
+ }
+
+ return result;
+ }
+
+ @Override
+ public AuthenticatorRecord getRecord(String authenticatorID) throws Exception {
+
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ return createAuthenticatorRecord(configDatabase, configRecord, authenticatorID);
+ }
+
+ @Override
+ public void addRecord(String authenticatorID, AuthenticatorRecord authenticatorRecord) throws Exception {
+
+ CMS.debug("AuthenticatorDatabase.addRecord(\"" + authenticatorID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // validate new properties
+ Map<String, String> properties = authenticatorRecord.getProperties();
+ configDatabase.validateProperties(configRecord, authenticatorID, properties);
+
+ // add new connection
+ configRecord.addKey(authenticatorID);
+ configDatabase.updateRecord(substoreName, configRecord);
+
+ // store new properties
+ configDatabase.addProperties(configRecord, authenticatorID, properties);
+
+ // create status
+ setRecordStatus(authenticatorID, authenticatorRecord.getStatus());
+
+ configDatabase.commit();
+ }
+
+ @Override
+ public void updateRecord(String authenticatorID, AuthenticatorRecord authenticatorRecord) throws Exception {
+
+ CMS.debug("AuthenticatorDatabase.updateRecord(\"" + authenticatorID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // validate new properties
+ Map<String, String> properties = authenticatorRecord.getProperties();
+ configDatabase.validateProperties(configRecord, authenticatorID, properties);
+
+ // remove old properties
+ configDatabase.removeProperties(configRecord, authenticatorID);
+
+ // add new properties
+ configDatabase.addProperties(configRecord, authenticatorID, properties);
+
+ // update status
+ setRecordStatus(authenticatorID, authenticatorRecord.getStatus());
+
+ configDatabase.commit();
+ }
+
+ @Override
+ public void removeRecord(String authenticatorID) throws Exception {
+
+ CMS.debug("AuthenticatorDatabase.removeRecord(\"" + authenticatorID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // remove properties
+ configDatabase.removeProperties(configRecord, authenticatorID);
+
+ // remove connection
+ configRecord.removeKey(authenticatorID);
+ configDatabase.updateRecord(substoreName, configRecord);
+
+ // remove status
+ removeRecordStatus(authenticatorID);
+
+ configDatabase.commit();
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/AuthenticatorRecord.java b/base/tps/src/org/dogtagpki/server/tps/config/AuthenticatorRecord.java
new file mode 100644
index 000000000..937a25e51
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/AuthenticatorRecord.java
@@ -0,0 +1,28 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import com.netscape.cmscore.dbs.CSCfgRecord;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+public class AuthenticatorRecord extends CSCfgRecord {
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ConfigDatabase.java b/base/tps/src/org/dogtagpki/server/tps/config/ConfigDatabase.java
new file mode 100644
index 000000000..db0fa9aa6
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ConfigDatabase.java
@@ -0,0 +1,191 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.ResourceNotFoundException;
+import com.netscape.cmscore.dbs.Database;
+
+/**
+ * This class implements in-memory connection database. In the future this
+ * will be replaced with LDAP database.
+ *
+ * @author Endi S. Dewata
+ */
+public class ConfigDatabase extends Database<ConfigRecord> {
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ public ConfigDatabase() throws EBaseException {
+ super("Configuration");
+ }
+
+ public String createFilter(ConfigRecord record, String key) {
+ String pattern = record.getPattern();
+ if (key == null) return pattern;
+ return pattern.replace("$name", key);
+ }
+
+ @Override
+ public Collection<ConfigRecord> findRecords(String filter) throws Exception {
+
+ CMS.debug("ConfigDatabase.findRecords()");
+
+ Collection<ConfigRecord> result = new ArrayList<ConfigRecord>();
+
+ Collection<String> configIDs = new LinkedHashSet<String>();
+ configIDs.add("Generals");
+
+ String list = configStore.get("target.configure.list");
+ if (list != null) {
+ configIDs.addAll(Arrays.asList(list.split(",")));
+ }
+
+ list = configStore.get("target.agent_approve.list");
+ if (list != null) {
+ configIDs.addAll(Arrays.asList(list.split(",")));
+ }
+
+ for (String configID : configIDs) {
+ if (filter != null && !configID.contains(filter)) continue;
+ ConfigRecord configData = getRecord(configID);
+ result.add(configData);
+ }
+
+ return result;
+ }
+
+ @Override
+ public ConfigRecord getRecord(String configID) throws Exception {
+
+ CMS.debug("ConfigDatabase.getRecord(\"" + configID + "\")");
+
+ ConfigRecord record = new ConfigRecord();
+ record.setID(configID);
+
+ String displayName = configStore.get("target." + configID + ".displayname");
+ if (StringUtils.isEmpty(displayName)) {
+ throw new ResourceNotFoundException("Configuration " + configID + " not found.");
+ }
+ record.setDisplayName(displayName);
+
+ String pattern = configStore.get("target." + configID + ".pattern");
+ if (StringUtils.isEmpty(pattern)) {
+ throw new ResourceNotFoundException("Missing pattern for " + configID + " configuration.");
+ }
+
+ // replace \| with |
+ record.setPattern(pattern.replace("\\|", "|"));
+
+ String list = configStore.get("target." + configID + ".list");
+ if (!StringUtils.isEmpty(list)) {
+ record.setKeys(Arrays.asList(list.split(",")));
+ }
+
+ return record;
+ }
+
+
+ @Override
+ public void updateRecord(String configID, ConfigRecord newRecord) throws Exception {
+
+ CMS.debug("ConfigDatabase.updateRecord(\"" + configID + "\")");
+
+ configStore.put("target." + configID + ".displayname", newRecord.getDisplayName());
+ configStore.put("target." + configID + ".pattern", newRecord.getPattern());
+ configStore.put("target." + configID + ".list", StringUtils.join(newRecord.getKeys(), ","));
+
+ configStore.commit(true);
+ }
+
+ public Map<String, String> getProperties(ConfigRecord record, String key) throws EBaseException {
+
+ CMS.debug("ConfigDatabase.getProperties(\"" + record.getID() + "\", \"" + key + "\")");
+
+ if (key != null && !record.containsKey(key)) {
+ throw new ResourceNotFoundException("Entry does not exist: " + key);
+ }
+
+ Map<String, String> properties = new TreeMap<String, String>();
+
+ // get properties that match the filter
+ String filter = createFilter(record, key);
+ Map<String, String> map = configStore.getProperties();
+ for (String name : map.keySet()) {
+ if (!name.matches(filter)) continue;
+
+ String value = map.get(name);
+ properties.put(name, value);
+ }
+
+ return properties;
+ }
+
+ public void validateProperties(ConfigRecord record, String key, Map<String, String> properties) throws Exception {
+
+ CMS.debug("ConfigDatabase.validateProperties(\"" + record.getID() + "\")");
+
+ String filter = createFilter(record, key);
+ for (String name : properties.keySet()) {
+ if (name.matches(filter)) continue;
+ CMS.debug("Property " + name + " doesn't match filter " + filter + ".");
+ throw new BadRequestException("Invalid property: " + name);
+ }
+ }
+
+ public void addProperties(ConfigRecord record, String key, Map<String, String> properties) throws Exception {
+
+ CMS.debug("ConfigDatabase.addProperties(\"" + record.getID() + "\")");
+
+ for (String name : properties.keySet()) {
+ String value = properties.get(name);
+ configStore.put(name, value);
+ }
+ }
+
+ public void removeProperties(ConfigRecord record, String key) throws Exception {
+
+ CMS.debug("ConfigDatabase.removeProperties(\"" + record.getID() + "\")");
+
+ Map<String, String> oldProperties = getProperties(record, key);
+ for (String name : oldProperties.keySet()) {
+ configStore.remove(name);
+ }
+ }
+
+ public void commit() throws Exception {
+
+ CMS.debug("ConfigDatabase.commit()");
+
+ // save configuration
+ configStore.commit(true);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ConfigRecord.java b/base/tps/src/org/dogtagpki/server/tps/config/ConfigRecord.java
new file mode 100644
index 000000000..f1a87ddfe
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ConfigRecord.java
@@ -0,0 +1,126 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+
+import com.netscape.certsrv.base.ConflictingOperationException;
+import com.netscape.certsrv.base.ResourceNotFoundException;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ConfigRecord {
+
+ String id;
+ String displayName;
+ String pattern;
+ Collection<String> keys = new LinkedHashSet<String>();
+
+ public String getID() {
+ return id;
+ }
+
+ public void setID(String id) {
+ this.id = id;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public String getPattern() {
+ return pattern;
+ }
+
+ public void setPattern(String pattern) {
+ this.pattern = pattern;
+ }
+
+ public Collection<String> getKeys() {
+ return keys;
+ }
+
+ public void setKeys(Collection<String> keys) {
+ this.keys.clear();
+ this.keys.addAll(keys);
+ }
+
+ public boolean containsKey(String key) {
+ return keys.contains(key);
+ }
+
+ public void addKey(String key) {
+ if (keys.contains(key)) throw new ConflictingOperationException("Entry already exists: " + key);
+ keys.add(key);
+ }
+
+ public void removeKey(String key) {
+ if (!keys.contains(key)) throw new ResourceNotFoundException("Entry does not exist: " + key);
+ keys.remove(key);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((displayName == null) ? 0 : displayName.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((keys == null) ? 0 : keys.hashCode());
+ result = prime * result + ((pattern == null) ? 0 : pattern.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ConfigRecord other = (ConfigRecord) obj;
+ if (displayName == null) {
+ if (other.displayName != null)
+ return false;
+ } else if (!displayName.equals(other.displayName))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (keys == null) {
+ if (other.keys != null)
+ return false;
+ } else if (!keys.equals(other.keys))
+ return false;
+ if (pattern == null) {
+ if (other.pattern != null)
+ return false;
+ } else if (!pattern.equals(other.pattern))
+ return false;
+ return true;
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ConfigService.java b/base/tps/src/org/dogtagpki/server/tps/config/ConfigService.java
new file mode 100644
index 000000000..6cd5e9f7d
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ConfigService.java
@@ -0,0 +1,135 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.tps.config.ConfigData;
+import com.netscape.certsrv.tps.config.ConfigResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ConfigService extends PKIService implements ConfigResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public ConfigService() {
+ CMS.debug("ConfigService.<init>()");
+ }
+
+ public ConfigData createConfigData(Map<String, String> properties) throws UnsupportedEncodingException {
+
+ ConfigData configData = new ConfigData();
+ configData.setProperties(properties);
+
+ URI uri = uriInfo.getBaseUriBuilder().path(ConfigResource.class).build();
+ configData.setLink(new Link("self", uri));
+
+ return configData;
+ }
+
+ @Override
+ public Response getConfig() {
+
+ CMS.debug("ConfigService.getConfig()");
+
+ try {
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord("Generals");
+
+ Map<String, String> properties = configDatabase.getProperties(configRecord, null);
+
+ return createOKResponse(createConfigData(properties));
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response updateConfig(ConfigData configData) {
+
+ if (configData == null) throw new BadRequestException("Config data is null.");
+
+ CMS.debug("ConfigService.updateConfig()");
+
+ try {
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord("Generals");
+
+ Map<String, String> properties = configData.getProperties();
+ if (properties != null) {
+ // validate new properties
+ configDatabase.validateProperties(configRecord, null, properties);
+
+ // remove old properties
+ configDatabase.removeProperties(configRecord, null);
+
+ // add new properties
+ configDatabase.addProperties(configRecord, null, properties);
+ }
+
+ configDatabase.commit();
+
+ properties = configDatabase.getProperties(configRecord, null);
+ configData = createConfigData(properties);
+
+ return Response
+ .ok(configData)
+ .build();
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ConnectorDatabase.java b/base/tps/src/org/dogtagpki/server/tps/config/ConnectorDatabase.java
new file mode 100644
index 000000000..4b1589797
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ConnectorDatabase.java
@@ -0,0 +1,242 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmscore.dbs.CSCfgDatabase;
+
+/**
+ * This class provides access to the connections in CS.cfg.
+ *
+ * @author Endi S. Dewata
+ */
+public class ConnectorDatabase extends CSCfgDatabase<ConnectorRecord> {
+
+ public String prefix = "tps.connector";
+
+ public ConnectorDatabase() {
+ super("Connector", "Subsystem_Connections");
+ }
+
+ public ConnectorRecord createConnectorRecord(ConfigDatabase configDatabase, ConfigRecord configRecord, String connectorID) throws EBaseException {
+ ConnectorRecord connectorRecord = new ConnectorRecord();
+ connectorRecord.setID(connectorID);
+
+ String status = getRecordStatus(connectorID);
+ connectorRecord.setStatus(status);
+
+ Map<String, String> properties = configDatabase.getProperties(configRecord, connectorID);
+ connectorRecord.setProperties(properties);
+ return connectorRecord;
+ }
+
+ @Override
+ public Collection<ConnectorRecord> findRecords(String filter) throws Exception {
+
+ Collection<ConnectorRecord> result = new ArrayList<ConnectorRecord>();
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ for (String connectorID : configRecord.getKeys()) {
+ if (filter != null && !connectorID.contains(filter)) continue;
+ ConnectorRecord connectorRecord = createConnectorRecord(configDatabase, configRecord, connectorID);
+ result.add(connectorRecord);
+ }
+
+ return result;
+ }
+
+ @Override
+ public ConnectorRecord getRecord(String connectionID) throws Exception {
+
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ return createConnectorRecord(configDatabase, configRecord, connectionID);
+ }
+
+ @Override
+ public void addRecord(String connectorID, ConnectorRecord connectorRecord) throws Exception {
+
+ CMS.debug("ConnectorDatabase.addRecord(\"" + connectorID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // validate new properties
+ Map<String, String> properties = connectorRecord.getProperties();
+ configDatabase.validateProperties(configRecord, connectorID, properties);
+
+ // add new connector
+ configRecord.addKey(connectorID);
+ configDatabase.updateRecord(substoreName, configRecord);
+
+ // store new properties
+ configDatabase.addProperties(configRecord, connectorID, properties);
+
+ // create status
+ setRecordStatus(connectorID, connectorRecord.getStatus());
+
+ configDatabase.commit();
+ }
+
+ @Override
+ public void updateRecord(String connectorID, ConnectorRecord connectorRecord) throws Exception {
+
+ CMS.debug("ConnectorDatabase.updateRecord(\"" + connectorID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // validate new properties
+ Map<String, String> properties = connectorRecord.getProperties();
+ configDatabase.validateProperties(configRecord, connectorID, properties);
+
+ // remove old properties
+ configDatabase.removeProperties(configRecord, connectorID);
+
+ // add new properties
+ configDatabase.addProperties(configRecord, connectorID, properties);
+
+ // update status
+ setRecordStatus(connectorID, connectorRecord.getStatus());
+
+ configDatabase.commit();
+ }
+
+ @Override
+ public void removeRecord(String connectorID) throws Exception {
+
+ CMS.debug("ConnectorDatabase.removeRecord(\"" + connectorID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // remove properties
+ configDatabase.removeProperties(configRecord, connectorID);
+
+ // remove connector
+ configRecord.removeKey(connectorID);
+ configDatabase.updateRecord(substoreName, configRecord);
+
+ // remove status
+ removeRecordStatus(connectorID);
+
+ configDatabase.commit();
+ }
+
+ public String getNextID(String type) throws Exception {
+
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+ Collection<String> keys = configRecord.getKeys();
+
+ String id;
+ int n = 1;
+
+ while (true) {
+ id = type + n;
+
+ if (keys.contains(id)) {
+ // ID is already used, find the next one.
+ n++;
+
+ } else {
+ // ID is available, use this one.
+ break;
+ }
+ }
+
+ return id;
+ }
+
+ public void addCAConnector(String hostname, Integer port, String nickname) throws Exception {
+
+ String id = getNextID("ca");
+
+ ConnectorRecord record = new ConnectorRecord();
+ record.setID(id);
+ record.setStatus("Enabled");
+
+ record.setProperty(prefix + "." + id + ".enable", "true");
+ record.setProperty(prefix + "." + id + ".host", hostname);
+ record.setProperty(prefix + "." + id + ".port", port.toString());
+ record.setProperty(prefix + "." + id + ".minHttpConns", "1");
+ record.setProperty(prefix + "." + id + ".maxHttpConns", "15");
+ record.setProperty(prefix + "." + id + ".nickName", nickname);
+ record.setProperty(prefix + "." + id + ".timeout", "30");
+ record.setProperty(prefix + "." + id + ".uri.enrollment", "/ca/ee/ca/profileSubmitSSLClient");
+ record.setProperty(prefix + "." + id + ".uri.getcert", "/ca/ee/ca/displayBySerial");
+ record.setProperty(prefix + "." + id + ".uri.renewal", "/ca/ee/ca/profileSubmitSSLClient");
+ record.setProperty(prefix + "." + id + ".uri.revoke", "/ca/ee/subsystem/ca/doRevoke");
+ record.setProperty(prefix + "." + id + ".uri.unrevoke", "/ca/ee/subsystem/ca/doUnrevoke");
+
+ addRecord(id, record);
+ }
+
+ public void addKRAConnector(String hostname, Integer port, String nickname) throws Exception {
+
+ String id = getNextID("kra");
+
+ ConnectorRecord record = new ConnectorRecord();
+ record.setID(id);
+ record.setStatus("Enabled");
+
+ record.setProperty(prefix + "." + id + ".enable", "true");
+ record.setProperty(prefix + "." + id + ".host", hostname);
+ record.setProperty(prefix + "." + id + ".port", port.toString());
+ record.setProperty(prefix + "." + id + ".minHttpConns", "1");
+ record.setProperty(prefix + "." + id + ".maxHttpConns", "15");
+ record.setProperty(prefix + "." + id + ".nickName", nickname);
+ record.setProperty(prefix + "." + id + ".timeout", "30");
+ record.setProperty(prefix + "." + id + ".uri.GenerateKeyPair", "/kra/agent/kra/GenerateKeyPair");
+ record.setProperty(prefix + "." + id + ".uri.TokenKeyRecovery", "/kra/agent/kra/TokenKeyRecovery");
+
+ addRecord(id, record);
+ }
+
+ public void addTKSConnector(String hostname, Integer port, String nickname, Boolean keygen) throws Exception {
+
+ String id = getNextID("tks");
+
+ ConnectorRecord record = new ConnectorRecord();
+ record.setID(id);
+ record.setStatus("Enabled");
+
+ record.setProperty(prefix + "." + id + ".enable", "true");
+ record.setProperty(prefix + "." + id + ".host", hostname);
+ record.setProperty(prefix + "." + id + ".port", port.toString());
+ record.setProperty(prefix + "." + id + ".minHttpConns", "1");
+ record.setProperty(prefix + "." + id + ".maxHttpConns", "15");
+ record.setProperty(prefix + "." + id + ".nickName", nickname);
+ record.setProperty(prefix + "." + id + ".timeout", "30");
+ record.setProperty(prefix + "." + id + ".generateHostChallenge", "true");
+ record.setProperty(prefix + "." + id + ".serverKeygen", keygen.toString());
+ record.setProperty(prefix + "." + id + ".keySet", "defKeySet");
+ record.setProperty(prefix + "." + id + ".tksSharedSymKeyName", "sharedSecret");
+ record.setProperty(prefix + "." + id + ".uri.computeRandomData", "/tks/agent/tks/computeRandomData");
+ record.setProperty(prefix + "." + id + ".uri.computeSessionKey", "/tks/agent/tks/computeSessionKey");
+ record.setProperty(prefix + "." + id + ".uri.createKeySetData", "/tks/agent/tks/createKeySetData");
+ record.setProperty(prefix + "." + id + ".uri.encryptData", "/tks/agent/tks/encryptData");
+
+ addRecord(id, record);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ConnectorRecord.java b/base/tps/src/org/dogtagpki/server/tps/config/ConnectorRecord.java
new file mode 100644
index 000000000..3123718b1
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ConnectorRecord.java
@@ -0,0 +1,28 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import com.netscape.cmscore.dbs.CSCfgRecord;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ConnectorRecord extends CSCfgRecord {
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ProfileDatabase.java b/base/tps/src/org/dogtagpki/server/tps/config/ProfileDatabase.java
new file mode 100644
index 000000000..01225d309
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ProfileDatabase.java
@@ -0,0 +1,144 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmscore.dbs.CSCfgDatabase;
+
+/**
+ * This class provides access to the profiles in CS.cfg.
+ *
+ * @author Endi S. Dewata
+ */
+public class ProfileDatabase extends CSCfgDatabase<ProfileRecord> {
+
+ public ProfileDatabase() {
+ super("Profile", "Profiles");
+ }
+
+ public ProfileRecord createProfileRecord(ConfigDatabase configDatabase, ConfigRecord configRecord, String profileID) throws EBaseException {
+ ProfileRecord profileRecord = new ProfileRecord();
+ profileRecord.setID(profileID);
+
+ String status = getRecordStatus(profileID);
+ profileRecord.setStatus(status);
+
+ Map<String, String> properties = configDatabase.getProperties(configRecord, profileID);
+ profileRecord.setProperties(properties);
+
+ return profileRecord;
+ }
+
+ @Override
+ public Collection<ProfileRecord> findRecords(String filter) throws Exception {
+
+ Collection<ProfileRecord> result = new ArrayList<ProfileRecord>();
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ for (String profileID : configRecord.getKeys()) {
+ if (filter != null && !profileID.contains(filter)) continue;
+ ProfileRecord profileRecord = createProfileRecord(configDatabase, configRecord, profileID);
+ result.add(profileRecord);
+ }
+
+ return result;
+ }
+
+ @Override
+ public ProfileRecord getRecord(String profileID) throws Exception {
+
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ return createProfileRecord(configDatabase, configRecord, profileID);
+ }
+
+ @Override
+ public void addRecord(String profileID, ProfileRecord profileRecord) throws Exception {
+
+ CMS.debug("ProfileDatabase.addRecord(\"" + profileID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // validate new properties
+ Map<String, String> properties = profileRecord.getProperties();
+ configDatabase.validateProperties(configRecord, profileID, properties);
+
+ // add new profile
+ configRecord.addKey(profileID);
+ configDatabase.updateRecord(substoreName, configRecord);
+
+ // store new properties
+ configDatabase.addProperties(configRecord, profileID, properties);
+
+ // create status
+ setRecordStatus(profileID, profileRecord.getStatus());
+
+ configDatabase.commit();
+ }
+
+ @Override
+ public void updateRecord(String profileID, ProfileRecord profileRecord) throws Exception {
+
+ CMS.debug("ProfileDatabase.updateRecord(\"" + profileID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // validate new properties
+ Map<String, String> properties = profileRecord.getProperties();
+ configDatabase.validateProperties(configRecord, profileID, properties);
+
+ // remove old properties
+ configDatabase.removeProperties(configRecord, profileID);
+
+ // add new properties
+ configDatabase.addProperties(configRecord, profileID, properties);
+
+ // update status
+ setRecordStatus(profileID, profileRecord.getStatus());
+
+ configDatabase.commit();
+ }
+
+ @Override
+ public void removeRecord(String profileID) throws Exception {
+
+ CMS.debug("ProfileDatabase.removeRecord(\"" + profileID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // remove properties
+ configDatabase.removeProperties(configRecord, profileID);
+
+ // remove profile
+ configRecord.removeKey(profileID);
+ configDatabase.updateRecord(substoreName, configRecord);
+
+ // remove status
+ removeRecordStatus(profileID);
+
+ configDatabase.commit();
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ProfileMappingDatabase.java b/base/tps/src/org/dogtagpki/server/tps/config/ProfileMappingDatabase.java
new file mode 100644
index 000000000..67a21d6ac
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ProfileMappingDatabase.java
@@ -0,0 +1,144 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.cmscore.dbs.CSCfgDatabase;
+
+/**
+ * This class provides access to the profileMappings in CS.cfg.
+ *
+ * @author Endi S. Dewata
+ */
+public class ProfileMappingDatabase extends CSCfgDatabase<ProfileMappingRecord> {
+
+ public ProfileMappingDatabase() {
+ super("Profile Mapping", "Profile_Mappings");
+ }
+
+ public ProfileMappingRecord createProfileMappingRecord(ConfigDatabase configDatabase, ConfigRecord configRecord, String profileMappingID) throws EBaseException {
+ ProfileMappingRecord profileMappingRecord = new ProfileMappingRecord();
+ profileMappingRecord.setID(profileMappingID);
+
+ String status = getRecordStatus(profileMappingID);
+ profileMappingRecord.setStatus(status);
+
+ Map<String, String> properties = configDatabase.getProperties(configRecord, profileMappingID);
+ profileMappingRecord.setProperties(properties);
+ return profileMappingRecord;
+ }
+
+ @Override
+ public Collection<ProfileMappingRecord> findRecords(String filter) throws Exception {
+
+ Collection<ProfileMappingRecord> result = new ArrayList<ProfileMappingRecord>();
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ for (String profileMappingID : configRecord.getKeys()) {
+ if (filter != null && !profileMappingID.contains(filter)) continue;
+ ProfileMappingRecord profileMappingRecord = createProfileMappingRecord(configDatabase, configRecord, profileMappingID);
+ result.add(profileMappingRecord);
+ }
+
+ return result;
+ }
+
+ @Override
+ public ProfileMappingRecord getRecord(String profileMappingID) throws Exception {
+
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ return createProfileMappingRecord(configDatabase, configRecord, profileMappingID);
+ }
+
+
+ @Override
+ public void addRecord(String profileMappingID, ProfileMappingRecord profileMappingRecord) throws Exception {
+
+ CMS.debug("ProfileMappingDatabase.addRecord(\"" + profileMappingID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // validate new properties
+ Map<String, String> properties = profileMappingRecord.getProperties();
+ configDatabase.validateProperties(configRecord, profileMappingID, properties);
+
+ // add new profileMapping
+ configRecord.addKey(profileMappingID);
+ configDatabase.updateRecord(substoreName, configRecord);
+
+ // store new properties
+ configDatabase.addProperties(configRecord, profileMappingID, properties);
+
+ // create status
+ setRecordStatus(profileMappingID, profileMappingRecord.getStatus());
+
+ configDatabase.commit();
+ }
+
+ @Override
+ public void updateRecord(String profileMappingID, ProfileMappingRecord profileMappingRecord) throws Exception {
+
+ CMS.debug("ProfileMappingDatabase.updateRecord(\"" + profileMappingID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // validate new properties
+ Map<String, String> properties = profileMappingRecord.getProperties();
+ configDatabase.validateProperties(configRecord, profileMappingID, properties);
+
+ // remove old properties
+ configDatabase.removeProperties(configRecord, profileMappingID);
+
+ // add new properties
+ configDatabase.addProperties(configRecord, profileMappingID, properties);
+
+ // update status
+ setRecordStatus(profileMappingID, profileMappingRecord.getStatus());
+
+ configDatabase.commit();
+ }
+
+ @Override
+ public void removeRecord(String profileMappingID) throws Exception {
+
+ CMS.debug("ProfileMappingDatabase.removeRecord(\"" + profileMappingID + "\")");
+ ConfigDatabase configDatabase = new ConfigDatabase();
+ ConfigRecord configRecord = configDatabase.getRecord(substoreName);
+
+ // remove properties
+ configDatabase.removeProperties(configRecord, profileMappingID);
+
+ // remove profileMapping
+ configRecord.removeKey(profileMappingID);
+ configDatabase.updateRecord(substoreName, configRecord);
+
+ // remove status
+ removeRecordStatus(profileMappingID);
+
+ configDatabase.commit();
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ProfileMappingRecord.java b/base/tps/src/org/dogtagpki/server/tps/config/ProfileMappingRecord.java
new file mode 100644
index 000000000..92793ce5e
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ProfileMappingRecord.java
@@ -0,0 +1,28 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import com.netscape.cmscore.dbs.CSCfgRecord;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ProfileMappingRecord extends CSCfgRecord {
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/config/ProfileRecord.java b/base/tps/src/org/dogtagpki/server/tps/config/ProfileRecord.java
new file mode 100644
index 000000000..a84b7f5ba
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/config/ProfileRecord.java
@@ -0,0 +1,28 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.config;
+
+import com.netscape.cmscore.dbs.CSCfgRecord;
+
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ProfileRecord extends CSCfgRecord {
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/dbs/ActivityDatabase.java b/base/tps/src/org/dogtagpki/server/tps/dbs/ActivityDatabase.java
new file mode 100644
index 000000000..9b4a4b28d
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/dbs/ActivityDatabase.java
@@ -0,0 +1,100 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.dbs;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.apache.commons.lang.StringUtils;
+import org.dogtagpki.tps.main.Util;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.cmscore.dbs.LDAPDatabase;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * This class implements in-memory activity database. In the future this
+ * will be replaced with LDAP database.
+ *
+ * @author Endi S. Dewata
+ */
+public class ActivityDatabase extends LDAPDatabase<ActivityRecord> {
+ public final static String OP_DO_TOKEN = "do_token";
+ public final static String OP_ADD = "add"; // add a token
+ public final static String OP_DELETE = "delete"; // delete a token
+ //public final static String OP_MODIFY_AUDIT_SIGNING = "modify_audit_signing";
+ public final static String OP_ENROLLMENT = "enrollment";
+ public final static String OP_RENEWAL = "renewal";
+ public final static String OP_PIN_RESET = "pin_reset";
+ public final static String OP_FORMAT = "format";
+
+ public ActivityDatabase(IDBSubsystem dbSubsystem, String baseDN) throws EBaseException {
+ super("Activity", dbSubsystem, baseDN, ActivityRecord.class);
+ }
+
+ public ActivityRecord log(
+ String ip, String tokenID, String operation, String result,
+ String message, String userID, String tokenType) throws Exception {
+ Calendar c = Calendar.getInstance();
+
+ String timeString = Util.getTimeStampString(true);
+ long threadID = Thread.currentThread().getId();
+ String threadIDS = String.format("%x", threadID);
+ String id = timeString + "." + threadIDS;
+
+ ActivityRecord activityRecord = new ActivityRecord();
+ activityRecord.setId(id);
+ activityRecord.setIP(ip);
+ activityRecord.setTokenID(tokenID);
+ activityRecord.setOperation(operation);
+ activityRecord.setResult(result);
+ activityRecord.setMessage(message);
+ activityRecord.setUserID(userID);
+ activityRecord.setType(tokenType);
+ activityRecord.setDate(c.getTime());
+
+ super.addRecord(id, activityRecord);
+
+ return activityRecord;
+ }
+
+ @Override
+ public void addRecord(String id, ActivityRecord activityRecord) throws Exception {
+ activityRecord.setDate(new Date());
+
+ super.addRecord(id, activityRecord);
+ }
+
+ @Override
+ public String createDN(String id) {
+ return "cn=" + id + "," + baseDN;
+ }
+
+ @Override
+ public String createFilter(String filter) {
+
+ if (StringUtils.isEmpty(filter)) {
+ return "(id=*)";
+ }
+
+ filter = LDAPUtil.escapeFilter(filter);
+ return "(|(tokenID=*" + filter + "*)(userID=*" + filter + "*))";
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/dbs/ActivityRecord.java b/base/tps/src/org/dogtagpki/server/tps/dbs/ActivityRecord.java
new file mode 100644
index 000000000..fe5b1f91c
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/dbs/ActivityRecord.java
@@ -0,0 +1,214 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.dbs;
+
+import java.util.Date;
+
+import com.netscape.cmscore.dbs.DBAttribute;
+import com.netscape.cmscore.dbs.DBObjectClasses;
+import com.netscape.cmscore.dbs.DBRecord;
+
+/**
+ * @author Endi S. Dewata
+ */
+@DBObjectClasses({ "top", "tokenActivity" })
+public class ActivityRecord extends DBRecord {
+
+ private static final long serialVersionUID = 1L;
+
+ String id;
+ String tokenID;
+ String userID;
+ String ip;
+ String operation;
+ String result;
+ String message;
+ String extensions;
+ String type;
+ Date date;
+
+ @DBAttribute("cn")
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @DBAttribute("tokenID")
+ public String getTokenID() {
+ return tokenID;
+ }
+
+ public void setTokenID(String tokenID) {
+ this.tokenID = tokenID;
+ }
+
+ @DBAttribute("tokenUserID")
+ public String getUserID() {
+ return userID;
+ }
+
+ public void setUserID(String userID) {
+ this.userID = userID;
+ }
+
+ @DBAttribute("tokenIP")
+ public String getIP() {
+ return ip;
+ }
+
+ public void setIP(String ip) {
+ this.ip = ip;
+ }
+
+ @DBAttribute("tokenOp")
+ public String getOperation() {
+ return operation;
+ }
+
+ public void setOperation(String operation) {
+ this.operation = operation;
+ }
+
+ @DBAttribute("tokenResult")
+ public String getResult() {
+ return result;
+ }
+
+ public void setResult(String result) {
+ this.result = result;
+ }
+
+ @DBAttribute("tokenMsg")
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ @DBAttribute("extensions")
+ public String getExtensions() {
+ return extensions;
+ }
+
+ public void setExtensions(String extensions) {
+ this.extensions = extensions;
+ }
+
+ @DBAttribute("tokenType")
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ @DBAttribute("dateOfCreate")
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((date == null) ? 0 : date.hashCode());
+ result = prime * result + ((extensions == null) ? 0 : extensions.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((ip == null) ? 0 : ip.hashCode());
+ result = prime * result + ((message == null) ? 0 : message.hashCode());
+ result = prime * result + ((operation == null) ? 0 : operation.hashCode());
+ result = prime * result + ((this.result == null) ? 0 : this.result.hashCode());
+ result = prime * result + ((tokenID == null) ? 0 : tokenID.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ result = prime * result + ((userID == null) ? 0 : userID.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ActivityRecord other = (ActivityRecord) obj;
+ if (date == null) {
+ if (other.date != null)
+ return false;
+ } else if (!date.equals(other.date))
+ return false;
+ if (extensions == null) {
+ if (other.extensions != null)
+ return false;
+ } else if (!extensions.equals(other.extensions))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (ip == null) {
+ if (other.ip != null)
+ return false;
+ } else if (!ip.equals(other.ip))
+ return false;
+ if (message == null) {
+ if (other.message != null)
+ return false;
+ } else if (!message.equals(other.message))
+ return false;
+ if (operation == null) {
+ if (other.operation != null)
+ return false;
+ } else if (!operation.equals(other.operation))
+ return false;
+ if (result == null) {
+ if (other.result != null)
+ return false;
+ } else if (!result.equals(other.result))
+ return false;
+ if (tokenID == null) {
+ if (other.tokenID != null)
+ return false;
+ } else if (!tokenID.equals(other.tokenID))
+ return false;
+ if (type == null) {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ if (userID == null) {
+ if (other.userID != null)
+ return false;
+ } else if (!userID.equals(other.userID))
+ return false;
+ return true;
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/dbs/TPSCertDatabase.java b/base/tps/src/org/dogtagpki/server/tps/dbs/TPSCertDatabase.java
new file mode 100644
index 000000000..7450b0665
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/dbs/TPSCertDatabase.java
@@ -0,0 +1,71 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.dbs;
+
+import java.util.Date;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.cmscore.dbs.LDAPDatabase;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * This class implements in-memory activity database. In the future this
+ * will be replaced with LDAP database.
+ *
+ * @author Endi S. Dewata
+ */
+public class TPSCertDatabase extends LDAPDatabase<TPSCertRecord> {
+
+ public TPSCertDatabase(IDBSubsystem dbSubsystem, String baseDN) throws EBaseException {
+ super("Certificate", dbSubsystem, baseDN, TPSCertRecord.class);
+ }
+
+ @Override
+ public void addRecord(String id, TPSCertRecord certRecord) throws Exception {
+ certRecord.setCreateTime(new Date());
+
+ super.addRecord(id, certRecord);
+ }
+
+ @Override
+ public void updateRecord(String id, TPSCertRecord certRecord) throws Exception {
+ certRecord.setModifyTime(new Date());
+
+ super.updateRecord(id, certRecord);
+ }
+
+ @Override
+ public String createDN(String id) {
+ return "cn=" + id + "," + baseDN;
+ }
+
+ @Override
+ public String createFilter(String filter) {
+
+ if (StringUtils.isEmpty(filter)) {
+ return "(id=*)";
+ }
+
+ filter = LDAPUtil.escapeFilter(filter);
+ return "(|(id=*" + filter + "*)(tokenID=*" + filter + "*)(userID=*" + filter + "*))";
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/dbs/TPSCertRecord.java b/base/tps/src/org/dogtagpki/server/tps/dbs/TPSCertRecord.java
new file mode 100644
index 000000000..288f25f53
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/dbs/TPSCertRecord.java
@@ -0,0 +1,313 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.dbs;
+
+import java.util.Date;
+
+import com.netscape.cmscore.dbs.DBAttribute;
+import com.netscape.cmscore.dbs.DBObjectClasses;
+import com.netscape.cmscore.dbs.DBRecord;
+
+/**
+ * @author Endi S. Dewata
+ */
+@DBObjectClasses({ "top", "tokenCert" })
+public class TPSCertRecord extends DBRecord {
+
+ private static final long serialVersionUID = 1L;
+
+ String id;
+ String serialNumber;
+ String subject;
+ String tokenID;
+ String keyType;
+ String status;
+ String userID;
+ String certificate;
+ String issuedBy;
+ String origin;
+ String type;
+ Date validNotBefore;
+ Date validNotAfter;
+ String extensions;
+ Date createTime;
+ Date modifyTime;
+
+ @DBAttribute("cn")
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ // the serial number is in HEX
+ @DBAttribute("tokenSerial")
+ public String getSerialNumber() {
+ return serialNumber;
+ }
+
+ public void setSerialNumber(String serialNumber) {
+ this.serialNumber = serialNumber;
+ }
+
+ @DBAttribute("tokenSubject")
+ public String getSubject() {
+ return subject;
+ }
+
+ public void setSubject(String subject) {
+ this.subject = subject;
+ }
+
+ @DBAttribute("tokenID")
+ public String getTokenID() {
+ return tokenID;
+ }
+
+ public void setTokenID(String tokenID) {
+ this.tokenID = tokenID;
+ }
+
+ @DBAttribute("tokenKeyType")
+ public String getKeyType() {
+ return keyType;
+ }
+
+ public void setKeyType(String keyType) {
+ this.keyType = keyType;
+ }
+
+ @DBAttribute("tokenStatus")
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ @DBAttribute("tokenUserID")
+ public String getUserID() {
+ return userID;
+ }
+
+ public void setUserID(String userID) {
+ this.userID = userID;
+ }
+
+ @DBAttribute("userCertificate")
+ // Alternative to the actual certificate -- certificate AKI
+ public String getCertificate() {
+ return certificate;
+ }
+
+ // Alternative to the actual certificate -- certificate AKI
+ public void setCertificate(String certificate) {
+ this.certificate = certificate;
+ }
+
+ @DBAttribute("tokenIssuer")
+ public String getIssuedBy() {
+ return issuedBy;
+ }
+
+ public void setIssuedBy(String issuedBy) {
+ this.issuedBy = issuedBy;
+ }
+
+ @DBAttribute("tokenOrigin")
+ public String getOrigin() {
+ return origin;
+ }
+
+ public void setOrigin(String origin) {
+ this.origin = origin;
+ }
+
+ @DBAttribute("tokenType")
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ @DBAttribute("tokenNotBefore")
+ public Date getValidNotBefore() {
+ return validNotBefore;
+ }
+
+ public void setValidNotBefore(Date validNotBefore) {
+ this.validNotBefore = validNotBefore;
+ }
+
+ @DBAttribute("tokenNotAfter")
+ public Date getValidNotAfter() {
+ return validNotAfter;
+ }
+
+ public void setValidNotAfter(Date validNotAfter) {
+ this.validNotAfter = validNotAfter;
+ }
+
+ @DBAttribute("extensions")
+ public String getExtensions() {
+ return extensions;
+ }
+
+ public void setExtensions(String extensions) {
+ this.extensions = extensions;
+ }
+
+ @DBAttribute("dateOfCreate")
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ @DBAttribute("dateOfModify")
+ public Date getModifyTime() {
+ return modifyTime;
+ }
+
+ public void setModifyTime(Date modifyTime) {
+ this.modifyTime = modifyTime;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((certificate == null) ? 0 : certificate.hashCode());
+ result = prime * result + ((createTime == null) ? 0 : createTime.hashCode());
+ result = prime * result + ((extensions == null) ? 0 : extensions.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((issuedBy == null) ? 0 : issuedBy.hashCode());
+ result = prime * result + ((keyType == null) ? 0 : keyType.hashCode());
+ result = prime * result + ((modifyTime == null) ? 0 : modifyTime.hashCode());
+ result = prime * result + ((origin == null) ? 0 : origin.hashCode());
+ result = prime * result + ((serialNumber == null) ? 0 : serialNumber.hashCode());
+ result = prime * result + ((status == null) ? 0 : status.hashCode());
+ result = prime * result + ((subject == null) ? 0 : subject.hashCode());
+ result = prime * result + ((tokenID == null) ? 0 : tokenID.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ result = prime * result + ((userID == null) ? 0 : userID.hashCode());
+ result = prime * result + ((validNotAfter == null) ? 0 : validNotAfter.hashCode());
+ result = prime * result + ((validNotBefore == null) ? 0 : validNotBefore.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TPSCertRecord other = (TPSCertRecord) obj;
+ if (certificate == null) {
+ if (other.certificate != null)
+ return false;
+ } else if (!certificate.equals(other.certificate))
+ return false;
+ if (createTime == null) {
+ if (other.createTime != null)
+ return false;
+ } else if (!createTime.equals(other.createTime))
+ return false;
+ if (extensions == null) {
+ if (other.extensions != null)
+ return false;
+ } else if (!extensions.equals(other.extensions))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (issuedBy == null) {
+ if (other.issuedBy != null)
+ return false;
+ } else if (!issuedBy.equals(other.issuedBy))
+ return false;
+ if (keyType == null) {
+ if (other.keyType != null)
+ return false;
+ } else if (!keyType.equals(other.keyType))
+ return false;
+ if (modifyTime == null) {
+ if (other.modifyTime != null)
+ return false;
+ } else if (!modifyTime.equals(other.modifyTime))
+ return false;
+ if (origin == null) {
+ if (other.origin != null)
+ return false;
+ } else if (!origin.equals(other.origin))
+ return false;
+ if (serialNumber == null) {
+ if (other.serialNumber != null)
+ return false;
+ } else if (!serialNumber.equals(other.serialNumber))
+ return false;
+ if (status == null) {
+ if (other.status != null)
+ return false;
+ } else if (!status.equals(other.status))
+ return false;
+ if (subject == null) {
+ if (other.subject != null)
+ return false;
+ } else if (!subject.equals(other.subject))
+ return false;
+ if (tokenID == null) {
+ if (other.tokenID != null)
+ return false;
+ } else if (!tokenID.equals(other.tokenID))
+ return false;
+ if (type == null) {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ if (userID == null) {
+ if (other.userID != null)
+ return false;
+ } else if (!userID.equals(other.userID))
+ return false;
+ if (validNotAfter == null) {
+ if (other.validNotAfter != null)
+ return false;
+ } else if (!validNotAfter.equals(other.validNotAfter))
+ return false;
+ if (validNotBefore == null) {
+ if (other.validNotBefore != null)
+ return false;
+ } else if (!validNotBefore.equals(other.validNotBefore))
+ return false;
+ return true;
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java b/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java
new file mode 100644
index 000000000..f86c6e203
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/dbs/TokenDatabase.java
@@ -0,0 +1,68 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.dbs;
+
+import java.util.Date;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.cmscore.dbs.LDAPDatabase;
+import com.netscape.cmsutil.ldap.LDAPUtil;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class TokenDatabase extends LDAPDatabase<TokenRecord> {
+
+ public TokenDatabase(IDBSubsystem dbSubsystem, String baseDN) throws EBaseException {
+ super("Token", dbSubsystem, baseDN, TokenRecord.class);
+ }
+
+ @Override
+ public void addRecord(String id, TokenRecord tokenRecord) throws Exception {
+ tokenRecord.setCreateTimestamp(new Date());
+
+ super.addRecord(id, tokenRecord);
+ }
+
+ @Override
+ public void updateRecord(String id, TokenRecord tokenRecord) throws Exception {
+ tokenRecord.setModifyTimestamp(new Date());
+
+ super.updateRecord(id, tokenRecord);
+ }
+
+ @Override
+ public String createDN(String id) {
+ return "cn=" + id + "," + baseDN;
+ }
+
+ @Override
+ public String createFilter(String filter) {
+
+ if (StringUtils.isEmpty(filter)) {
+ return "(id=*)";
+ }
+
+ filter = LDAPUtil.escapeFilter(filter);
+ return "(|(id=*" + filter + "*)(userID=*" + filter + "*))";
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/dbs/TokenRecord.java b/base/tps/src/org/dogtagpki/server/tps/dbs/TokenRecord.java
new file mode 100644
index 000000000..a1aef5720
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/dbs/TokenRecord.java
@@ -0,0 +1,271 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.dbs;
+
+import java.util.Date;
+
+import com.netscape.certsrv.tps.token.TokenStatus;
+import com.netscape.cmscore.dbs.DBAttribute;
+import com.netscape.cmscore.dbs.DBObjectClasses;
+import com.netscape.cmscore.dbs.DBRecord;
+
+/**
+ * @author Endi S. Dewata
+ */
+@DBObjectClasses({ "top", "tokenRecord" })
+public class TokenRecord extends DBRecord {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * objectClasses: ( tokenRecord-oid
+ * NAME 'tokenRecord'
+ * DESC 'CMS defined class'
+ * SUP top
+ * STRUCTURAL
+ * MUST cn
+ * MAY (
+ * dateOfCreate $
+ * dateOfModify $
+ * modified $ (unused)
+ * tokenReason $
+ * tokenUserID $
+ * tokenStatus $
+ * tokenAppletID $
+ * keyInfo $
+ * tokenPolicy $
+ * extensions $ (unused)
+ * numberOfResets $ (unused)
+ * numberOfEnrollments $ (unused)
+ * numberOfRenewals $ (unused)
+ * numberOfRecoveries $ (unused)
+ * userCertificate $ (unused)
+ * tokenType )
+ * X-ORIGIN 'user defined' )
+ */
+ String id;
+ String userID;
+ String type;
+ String status;
+ String reason;
+ String appletID;
+ String keyInfo;
+ String policy;
+ Date createTimestamp;
+ Date modifyTimestamp;
+
+ @DBAttribute("cn")
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @DBAttribute("tokenUserID")
+ public String getUserID() {
+ return userID;
+ }
+
+ public void setUserID(String userID) {
+ this.userID = userID;
+ }
+
+ @DBAttribute("tokenType")
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ @DBAttribute("tokenStatus")
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ @DBAttribute("tokenReason")
+ public String getReason() {
+ return reason;
+ }
+
+ public void setReason(String reason) {
+ this.reason = reason;
+ }
+
+ @DBAttribute("tokenAppletID")
+ public String getAppletID() {
+ return appletID;
+ }
+
+ public void setAppletID(String appletID) {
+ this.appletID = appletID;
+ }
+
+ @DBAttribute("keyInfo")
+ public String getKeyInfo() {
+ return keyInfo;
+ }
+
+ public void setKeyInfo(String keyInfo) {
+ this.keyInfo = keyInfo;
+ }
+
+ @DBAttribute("tokenPolicy")
+ public String getPolicy() {
+ return policy;
+ }
+
+ public void setPolicy(String policy) {
+ this.policy = policy;
+ }
+
+ @DBAttribute("dateOfCreate")
+ public Date getCreateTimestamp() {
+ return createTimestamp;
+ }
+
+ public void setCreateTimestamp(Date createTimestamp) {
+ this.createTimestamp = createTimestamp;
+ }
+
+ @DBAttribute("dateOfModify")
+ public Date getModifyTimestamp() {
+ return modifyTimestamp;
+ }
+
+ public void setModifyTimestamp(Date modifyTimestamp) {
+ this.modifyTimestamp = modifyTimestamp;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((appletID == null) ? 0 : appletID.hashCode());
+ result = prime * result + ((createTimestamp == null) ? 0 : createTimestamp.hashCode());
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((keyInfo == null) ? 0 : keyInfo.hashCode());
+ result = prime * result + ((modifyTimestamp == null) ? 0 : modifyTimestamp.hashCode());
+ result = prime * result + ((policy == null) ? 0 : policy.hashCode());
+ result = prime * result + ((reason == null) ? 0 : reason.hashCode());
+ result = prime * result + ((status == null) ? 0 : status.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ result = prime * result + ((userID == null) ? 0 : userID.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TokenRecord other = (TokenRecord) obj;
+ if (appletID == null) {
+ if (other.appletID != null)
+ return false;
+ } else if (!appletID.equals(other.appletID))
+ return false;
+ if (createTimestamp == null) {
+ if (other.createTimestamp != null)
+ return false;
+ } else if (!createTimestamp.equals(other.createTimestamp))
+ return false;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (keyInfo == null) {
+ if (other.keyInfo != null)
+ return false;
+ } else if (!keyInfo.equals(other.keyInfo))
+ return false;
+ if (modifyTimestamp == null) {
+ if (other.modifyTimestamp != null)
+ return false;
+ } else if (!modifyTimestamp.equals(other.modifyTimestamp))
+ return false;
+ if (policy == null) {
+ if (other.policy != null)
+ return false;
+ } else if (!policy.equals(other.policy))
+ return false;
+ if (reason == null) {
+ if (other.reason != null)
+ return false;
+ } else if (!reason.equals(other.reason))
+ return false;
+ if (status == null) {
+ if (other.status != null)
+ return false;
+ } else if (!status.equals(other.status))
+ return false;
+ if (type == null) {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ if (userID == null) {
+ if (other.userID != null)
+ return false;
+ } else if (!userID.equals(other.userID))
+ return false;
+ return true;
+ }
+
+ public TokenStatus getTokenStatus() {
+ String status = getStatus();
+
+ if ("uninitialized".equals(status)) {
+ return TokenStatus.UNINITIALIZED;
+
+ } else if ("active".equals(status)) {
+ return TokenStatus.ACTIVE;
+
+ } else if ("lost".equals(status)) {
+ String reason = getReason();
+
+ if ("keyCompromise".equals(reason)) {
+ return TokenStatus.PERM_LOST;
+
+ } else if ("destroyed".equals(reason)) {
+ return TokenStatus.DAMAGED;
+
+ } else if ("onHold".equals(reason)) {
+ return TokenStatus.TEMP_LOST;
+ }
+
+ } else if ("terminated".equals(status)) {
+ return TokenStatus.TERMINATED;
+ }
+
+ return TokenStatus.PERM_LOST;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
new file mode 100644
index 000000000..c4b485c45
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java
@@ -0,0 +1,589 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.engine;
+
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+
+import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
+import org.dogtagpki.server.tps.cms.CARenewCertResponse;
+import org.dogtagpki.server.tps.cms.CARetrieveCertResponse;
+import org.dogtagpki.server.tps.cms.KRARecoverKeyResponse;
+import org.dogtagpki.server.tps.cms.KRARemoteRequestHandler;
+import org.dogtagpki.server.tps.cms.KRAServerSideKeyGenResponse;
+import org.dogtagpki.server.tps.cms.TKSComputeSessionKeyResponse;
+import org.dogtagpki.server.tps.cms.TKSCreateKeySetDataResponse;
+import org.dogtagpki.server.tps.cms.TKSRemoteRequestHandler;
+import org.dogtagpki.server.tps.dbs.TPSCertRecord;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.main.Util;
+import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.tps.token.TokenStatus;
+
+public class TPSEngine {
+
+ public enum RA_Algs {
+ ALG_RSA,
+ ALG_RSA_CRT,
+ ALG_DSA,
+ ALG_EC_F2M,
+ ALG_EC_FP
+ };
+
+ public enum ENROLL_MODES {
+ MODE_ENROLL,
+ MODE_RECOVERY,
+ MODE_RENEWAL
+ }
+
+ public static final String CFG_DEBUG_ENABLE = "logging.debug.enable";
+ public static final String CFG_DEBUG_FILENAME = "logging.debug.filename";
+ public static final String CFG_DEBUG_LEVEL = "logging.debug.level";
+ public static final String CFG_AUDIT_ENABLE = "logging.audit.enable";
+ public static final String CFG_AUDIT_FILENAME = "logging.audit.filename";
+ public static final String CFG_SIGNED_AUDIT_FILENAME = "logging.audit.signedAuditFilename";
+ public static final String CFG_AUDIT_LEVEL = "logging.audit.level";
+ public static final String CFG_AUDIT_SIGNED = "logging.audit.logSigning";
+ public static final String CFG_AUDIT_SIGNING_CERT_NICK = "logging.audit.signedAuditCertNickname";
+ public static final String CFG_ERROR_ENABLE = "logging.error.enable";
+ public static final String CFG_ERROR_FILENAME = "logging.error.filename";
+ public static final String CFG_ERROR_LEVEL = "logging.error.level";
+ public static final String CFG_SELFTEST_ENABLE = "selftests.container.logger.enable";
+ public static final String CFG_SELFTEST_FILENAME = "selftests.container.logger.fileName";
+ public static final String CFG_SELFTEST_LEVEL = "selftests.container.logger.level";
+ public static final String CFG_CHANNEL_SEC_LEVEL = "channel.securityLevel";
+ public static final String CFG_CHANNEL_ENCRYPTION = "channel.encryption";
+ public static final String CFG_APPLET_CARDMGR_INSTANCE_AID = "applet.aid.cardmgr_instance";
+ public static final String CFG_APPLET_NETKEY_INSTANCE_AID = "applet.aid.netkey_instance";
+ public static final String CFG_APPLET_NETKEY_FILE_AID = "applet.aid.netkey_file";
+ public static final String CFG_APPLET_NETKEY_OLD_INSTANCE_AID = "applet.aid.netkey_old_instance";
+ public static final String CFG_APPLET_NETKEY_OLD_FILE_AID = "applet.aid.netkey_old_file";
+ public static final String CFG_APPLET_SO_PIN = "applet.so_pin";
+ public static final String CFG_APPLET_DELETE_NETKEY_OLD = "applet.delete_old";
+ public static final String CFG_AUDIT_SELECTED_EVENTS = "logging.audit.selected.events";
+ public static final String CFG_AUDIT_NONSELECTABLE_EVENTS = "logging.audit.nonselectable.events";
+ public static final String CFG_AUDIT_SELECTABLE_EVENTS = "logging.audit.selectable.events";
+ public static final String CFG_AUDIT_BUFFER_SIZE = "logging.audit.buffer.size";
+ public static final String CFG_AUDIT_FLUSH_INTERVAL = "logging.audit.flush.interval";
+ public static final String CFG_AUDIT_FILE_TYPE = "logging.audit.file.type";
+ public static final String CFG_DEBUG_FILE_TYPE = "logging.debug.file.type";
+ public static final String CFG_ERROR_FILE_TYPE = "logging.error.file.type";
+ public static final String CFG_SELFTEST_FILE_TYPE = "selftests.container.logger.file.type";
+ public static final String CFG_AUDIT_PREFIX = "logging.audit";
+ public static final String CFG_ERROR_PREFIX = "logging.error";
+ public static final String CFG_DEBUG_PREFIX = "logging.debug";
+ public static final String CFG_SELFTEST_PREFIX = "selftests.container.logger";
+ public static final String CFG_TOKENDB_ALLOWED_TRANSITIONS = "tokendb.allowedTransitions";
+ public static final String CFG_OPERATIONS_ALLOWED_TRANSITIONS = "tps.operations.allowedTransitions";
+
+ public static final String CFG_PRINTBUF_FULL = "tps.printBufFull";
+ public static final String CFG_RECV_BUF_SIZE = "tps.recvBufSize";
+ public static final String CFG_AUTHS_ENABLE = "auth.enable";
+ public static final String CFG_PROFILE_MAPPING_ORDER = "mapping.order";
+ public static final String CFG_ALLOW_UNKNOWN_TOKEN = "allowUnkonwnToken";
+ public static final String CFG_ALLOW_NO_APPLET = "update.applet.emptyToken.enable";
+ public static final String CFG_APPLET_UPDATE_REQUIRED_VERSION = "update.applet.requiredVersion";
+ public static final String CFG_APPLET_DIRECTORY = "update.applet.directory";
+ public static final String CFG_APPLET_EXTENSION = "general.applet_ext";
+
+ public static final String CFG_CHANNEL_BLOCK_SIZE = "channel.blockSize";
+ public static final String CFG_CHANNEL_INSTANCE_SIZE = "channel.instanceSize";
+ public static final String CFG_CHANNEL_DEFKEY_VERSION = "channel.defKeyVersion";
+ public static final String CFG_CHANNEL_APPLET_MEMORY_SIZE = "channel.appletMemorySize";
+ public static final String CFG_CHANNEL_DEFKEY_INDEX = "channel.defKeyIndex";
+ public static final String CFG_ISSUER_INFO_ENABLE = "issuerinfo.enable";
+ public static final String CFG_ISSUER_INFO_VALUE = "issuerinfo.value";
+ public static final String CFG_UPDATE_APPLET_ENCRYPTION = "update.applet.encryption";
+ public static final String CFG_UPDATE_APPLET_ENABLE = "update.applet.enable";
+ public static final String CFG_SYMM_KEY_UPGRADE_ENABLED = "update.symmetricKeys.enable";
+
+ /* default values */
+ public static final String CFG_DEF_CARDMGR_INSTANCE_AID = "A0000000030000";
+ public static final String CFG_DEF_NETKEY_INSTANCE_AID = "627601FF000000";
+ public static final String CFG_DEF_NETKEY_FILE_AID = "627601FF0000";
+ public static final String CFG_DEF_NETKEY_OLD_INSTANCE_AID = "A00000000101";
+ public static final String CFG_DEF_NETKEY_OLD_FILE_AID = "A000000001";
+ public static final String CFG_DEF_APPLET_SO_PIN = "000000000000";
+ public static final String CFG_ENABLED = "Enabled";
+
+ public static final int CFG_CHANNEL_DEF_BLOCK_SIZE = 242;
+ public static final int CFG_CHANNEL_DEF_INSTANCE_SIZE = 18000;
+ public static final int CFG_CHANNEL_DEF_APPLET_MEMORY_SIZE = 5000;
+
+ /* token enrollment values */
+ public static final String CFG_SIGNING = "signing";
+ public static final String CFG_ENCRYPTION = "encryption";
+ public static final String CFG_KEYGEN_ENCRYPTION = "keyGen." + CFG_ENCRYPTION;
+ public static final String CFG_KEYGEN_SIGNING = "keyGen." + CFG_SIGNING;
+ public static final String CFG_KEYTYPE_NUM = "keyType.num";
+ public static final String CFG_KEYTYPE_VALUE = "keyType.value";
+ public static final String CFG_KEYGEN_KEYTYPE_NUM = "keyGen." + CFG_KEYTYPE_NUM;
+ public static final String CFG_KEYGEN_KEYTYPE_VALUE = "keyGen." + CFG_KEYTYPE_VALUE;
+ public static final String CFG_SERVER_KEYGEN_ENABLE = "serverKeygen.enable";
+ public static final String CFG_SERVER_KEY_ARCHIVAL = "serverKeygen.archive";
+ public static final String CFG_DRM_CONNECTOR = "serverKeygen.drm.conn";
+ public static final String CFG_KEYGEN = "keyGen";
+ public static final String CFG_ALG = "alg";
+
+ /* token renewal values */
+ public static final String CFG_RENEW_KEYTYPE_NUM = "renewal.keyType.num";
+ public static final String CFG_RENEW_KEYTYPE_VALUE = "renewal.keyType.value";
+
+ /* External reg values */
+
+ public static final String CFG_EXTERNAL_REG = "externalReg";
+
+ /* misc values */
+
+ public static final String ENROLL_OP = "enroll";
+ public static final String FORMAT_OP = "format";
+ public static final String RECOVERY_OP = "recovery";
+ public static final String RENEWAL_OP = "renewal";
+
+ public static final String OP_FORMAT_PREFIX = "op." + FORMAT_OP;
+ public static final String CFG_PROFILE_RESOLVER = "tokenProfileResolver";
+ public static final String CFG_DEF_FORMAT_PROFILE_RESOLVER = "formatMappingResolver";
+ public static final String CFG_DEF_ENROLL_PROFILE_RESOLVER = "enrollMappingResolver";
+ public static final String CFG_DEF_PIN_RESET_PROFILE_RESOLVER = "pinResetMappingResolver";
+ public static final String OP_ENROLL_PREFIX = "op." + ENROLL_OP;
+ public static final String OP_RECOVERY_PREFIX = "op." + RECOVERY_OP;
+
+ public static final String OP_PIN_RESET_PREFIX = "op.pinReset";
+ public static final String CFG_PIN_RESET_ENABLE = "pinReset.enable";
+ public static final String CFG_PIN_RESET_MIN_LEN = "pinReset.pin.minLen";
+ public static final String CFG_PIN_RESET_MAX_LEN = "pinReset.pin.maxLen";
+ public static final String CFG_PIN_RESET_MAX_RETRIES = "pinReset.pin.maxRetries";
+ public static final String CFG_PIN_RESET_STRING = "create_pin.string";
+
+ public static final String CFG_SCHEME = "scheme";
+ public static final String RECOVERY_SCHEME_GENERATE_NEW_KEY_AND_RECOVER_LAST = "GenerateNewKeyandRecoverLast";
+ public static final Object RECOVERY_GENERATE_NEW_KEY = "GenerateNewKey";
+ public static final Object RECOVERY_RECOVER_LAST = "RecoverLast";
+
+ public static final String CFG_OVERWRITE = "overwrite";
+ public static final String PIN_RESET_OP = "pin_reset";
+ public static final String ENROLL_MODE_ENROLLMENT = ENROLL_OP;
+ public static final String ENROLL_MODE_RECOVERY = RECOVERY_OP;
+ public static final String ERNOLL_MODE_RENEWAL = RENEWAL_OP;
+ private static final String CFG_OPERATIONS_TRANSITIONS = "tps.operations.allowedTransitions";
+
+ private static String transitionList;
+
+ public void init() {
+ //ToDo
+ }
+
+ public TPSEngine() {
+ }
+
+ public int initialize(String cfg_path) {
+
+ int rc = -1;
+
+ return rc;
+ }
+
+ public TKSComputeSessionKeyResponse computeSessionKey(TPSBuffer cuid,
+ TPSBuffer keyInfo,
+ TPSBuffer card_challenge,
+ TPSBuffer host_challenge,
+ TPSBuffer card_cryptogram,
+ String connId,
+ String tokenType) throws TPSException {
+
+ if (cuid == null || keyInfo == null || card_challenge == null || host_challenge == null
+ || card_cryptogram == null || connId == null || tokenType == null) {
+
+ throw new TPSException("TPSEngine.computeSessionKey: Invalid input data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+ }
+
+ CMS.debug("TPSEngine.computeSessionKey");
+
+ TKSRemoteRequestHandler tks = null;
+
+ TKSComputeSessionKeyResponse resp = null;
+ try {
+ tks = new TKSRemoteRequestHandler(connId);
+ resp = tks.computeSessionKey(cuid, keyInfo, card_challenge, card_cryptogram, host_challenge, tokenType);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEngine.computeSessionKey: Error computing session key!" + e,
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ int status = resp.getStatus();
+ if (status != 0) {
+ CMS.debug("TPSEngine.computeSessionKey: Non zero status result: " + status);
+ throw new TPSException("TPSEngine.computeSessionKey: invalid returned status: " + status);
+
+ }
+
+ return resp;
+
+ }
+
+ public CARetrieveCertResponse recoverCertificate(TPSCertRecord cert, String serialS, String keyType, String caConnID)
+ throws TPSException {
+
+ String method = "TPSEngine.recoverCertificate";
+
+ CMS.debug(method + ": serial # =" + serialS);
+
+ if (cert == null || serialS == null || keyType == null || caConnID == null) {
+ throw new TPSException(method + " Invalid input data!", TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ String serialhex = serialS.substring(2); // strip off the "0x"
+ BigInteger serialBI = new BigInteger(serialhex, 16);
+
+ CARetrieveCertResponse retrieveResponse = null;
+
+ String retrievedCertB64 = null;
+
+ try {
+
+ CARemoteRequestHandler caRH = new CARemoteRequestHandler(caConnID);
+
+ retrieveResponse = caRH.retrieveCertificate(serialBI);
+ retrievedCertB64 = retrieveResponse.getCertB64();
+ CMS.debug(method + ": retrieved cert: " + retrievedCertB64);
+ // test ends - remove up to here
+
+ } catch (EBaseException e) {
+ CMS.debug(method + ":" + e);
+ throw new TPSException(method + ": Exception thrown: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ if (retrievedCertB64 == null) {
+ throw new TPSException(method + " Unable to get valid cert blob.", TPSStatus.STATUS_ERROR_CA_RESPONSE);
+ }
+
+ return retrieveResponse;
+
+ }
+
+ public CARenewCertResponse renewCertificate(TPSCertRecord cert, String serialS, String tokenType, String keyType,
+ String caConnID) throws TPSException {
+
+ String method = "TPSEngine.renewCertificate";
+
+ CMS.debug(method + " entering...");
+
+ if (cert == null || serialS == null || keyType == null || tokenType == null || caConnID == null) {
+ throw new TPSException(method + " Invalid input data!", TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ CMS.debug(method + ": serial # =" + serialS);
+ String serialhex = serialS.substring(2); // strip off the "0x"
+ BigInteger serialBI = new BigInteger(serialhex, 16);
+
+ CARenewCertResponse renewResponse = null;
+
+ String retrievedCertB64 = null;
+
+ try {
+
+ CARemoteRequestHandler caRH = new CARemoteRequestHandler(caConnID);
+
+ /*
+ * testing retrieveCertificate() to retrieve the old cert (to be used by Recovery)
+ * TODO: remove
+ */
+ renewResponse = caRH.renewCertificate(serialBI, tokenType, keyType);
+ retrievedCertB64 = renewResponse.getRenewedCertB64();
+ CMS.debug(method + ": retrieved cert: " + retrievedCertB64);
+
+ } catch (EBaseException e) {
+ CMS.debug(method + ":" + e);
+ throw new TPSException(method + ": Exception thrown: " + e,
+ TPSStatus.STATUS_ERROR_RENEWAL_FAILED);
+ }
+
+ if (retrievedCertB64 == null) {
+ throw new TPSException(method + " Unable to get valid cert blob.", TPSStatus.STATUS_ERROR_CA_RESPONSE);
+ }
+
+ return renewResponse;
+
+ }
+
+ public TPSBuffer createKeySetData(TPSBuffer newMasterVersion, TPSBuffer oldVersion, TPSBuffer cuid, String connId)
+ throws TPSException {
+ CMS.debug("TPSEngine.createKeySetData. entering...");
+
+ if (newMasterVersion == null || oldVersion == null || cuid == null || connId == null) {
+ throw new TPSException("TPSEngine.createKeySetData: Invalid input data",
+ TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+ }
+
+ TKSRemoteRequestHandler tks = null;
+
+ TKSCreateKeySetDataResponse resp = null;
+
+ try {
+ tks = new TKSRemoteRequestHandler(connId);
+ resp = tks.createKeySetData(newMasterVersion, oldVersion, cuid);
+ } catch (EBaseException e) {
+
+ throw new TPSException("TPSEngine.createKeySetData, failure to get key set data from TKS",
+ TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+ }
+
+ int status = resp.getStatus();
+ if (status != 0) {
+ CMS.debug("TPSEngine.createKeySetData: Non zero status result: " + status);
+ throw new TPSException("TPSEngine.computeSessionKey: invalid returned status: " + status,
+ TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+
+ }
+
+ TPSBuffer keySetData = resp.getKeySetData();
+
+ if (keySetData == null) {
+ CMS.debug("TPSEngine.createKeySetData: No valid key set data returned.");
+ throw new TPSException("TPSEngine.createKeySetData: No valid key set data returned.",
+ TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER);
+
+ }
+
+ return keySetData;
+ }
+
+ public static void main(String[] args) {
+
+ }
+
+ public boolean raForceTokenFormat(String cuid) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isAlgorithmECC(int algorithm) {
+
+ RA_Algs algEnum = intToRAAlgs(algorithm);
+
+ boolean isECC = false;
+
+ if (algEnum == RA_Algs.ALG_EC_F2M || algEnum == RA_Algs.ALG_EC_FP) {
+ isECC = true;
+ }
+
+ CMS.debug("TPSEngine.isAlgorithmECC: result: " + isECC);
+ return isECC;
+
+ }
+
+ public static RA_Algs intToRAAlgs(int alg) {
+
+ RA_Algs def = RA_Algs.ALG_RSA;
+
+ switch (alg) {
+
+ case 1:
+ return RA_Algs.ALG_RSA;
+
+ case 2:
+ return RA_Algs.ALG_RSA_CRT;
+ case 3:
+ return RA_Algs.ALG_DSA;
+ case 4:
+ return RA_Algs.ALG_EC_F2M;
+ case 5:
+ return RA_Algs.ALG_EC_FP;
+
+ default:
+ return def;
+
+ }
+
+ }
+
+ public KRARecoverKeyResponse recoverKey(String cuid,
+ String userid,
+ TPSBuffer sDesKey,
+ String b64cert, String drmConnId) throws TPSException {
+ String method = "TPSEngine.recoverKey";
+ CMS.debug("TPSEngine.recoverKey");
+ if (cuid == null)
+ CMS.debug(method + ": cuid null");
+ else if (userid == null)
+ CMS.debug(method + ": userid null");
+ else if (sDesKey == null)
+ CMS.debug(method + ": isDesKey null");
+ else if (b64cert == null)
+ CMS.debug(method + ": b64cert null");
+ else if (drmConnId == null)
+ CMS.debug(method + ": drmConnId null");
+
+ if (cuid == null || userid == null || sDesKey == null || b64cert == null || drmConnId == null) {
+ throw new TPSException("TPSEngine.recoverKey: invalid input data!", TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ KRARecoverKeyResponse resp = null;
+ KRARemoteRequestHandler kra = null;
+
+ try {
+ kra = new KRARemoteRequestHandler(drmConnId);
+
+ resp = kra.recoverKey(cuid, userid, Util.specialURLEncode(sDesKey), Util.uriEncode(b64cert));
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEngine.recoverKey: Problem creating or using KRARemoteRequestHandler! "
+ + e.toString(), TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+
+ } catch (UnsupportedEncodingException e) {
+ throw new TPSException("TPSEngine.recoverKey: Problem creating or using KRARemoteRequestHandler! "
+ + e.toString(), TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ int status = resp.getStatus();
+
+ if (status != 0) {
+ throw new TPSException("TPSEngine.recoverKey: Bad status from server: " + status,
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ if (resp.getPublicKey() == null) {
+ throw new TPSException("TPSEngine.recoverKey: invalid public key from server! ",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ if (resp.getWrappedPrivKey() == null) {
+ throw new TPSException("TPSEngine.recoverKey: invalid private key from server! ",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+
+ }
+
+ if (resp.getIVParam() == null) {
+ throw new TPSException("TPSEngine.recoverKey: invalid iv vector from server!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ return resp;
+
+ }
+
+ public KRAServerSideKeyGenResponse serverSideKeyGen(int keySize, String cuid, String userid, String drmConnId,
+ TPSBuffer wrappedDesKey,
+ boolean archive,
+ boolean isECC) throws TPSException {
+
+ CMS.debug("TPSEngine.serverSideKeyGen entering... keySize: " + keySize + " cuid: " + cuid + " userid: "
+ + userid + " drConnId: " + drmConnId + " wrappedDesKey: " + wrappedDesKey + " archive: " + archive
+ + " isECC: " + isECC);
+
+ if (cuid == null || userid == null || drmConnId == null || wrappedDesKey == null) {
+ throw new TPSException("TPSEngine.serverSideKeyGen: Invalid input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ KRARemoteRequestHandler kra = null;
+ KRAServerSideKeyGenResponse resp = null;
+
+ try {
+ kra = new KRARemoteRequestHandler(drmConnId);
+
+ resp = kra.serverSideKeyGen(isECC, keySize, cuid, userid,
+ Util.specialURLEncode(wrappedDesKey), archive);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEngine.serverSideKeyGen: Problem creating or using KRARemoteRequestHandler! "
+ + e.toString());
+ }
+
+ int status = resp.getStatus();
+
+ if (status != 0) {
+ throw new TPSException("TPSEngine.serverSideKeyGen: Bad status from server: " + status,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ if (resp.getPublicKey() == null) {
+ throw new TPSException("TPSEngine.serverSideKeyGen: invalid public key from server! ",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ if (resp.getWrappedPrivKey() == null) {
+ throw new TPSException("TPSEngine.serverSideKeyGen: invalid private key from server! ",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+ }
+
+ if (resp.getIVParam() == null) {
+ throw new TPSException("TPSEngine.serverSideKeyGen: invalid iv vector from server!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ //We return this resonse we know that all the data is present and can be accessed
+ return resp;
+
+ }
+
+ //Check to see if special operations transition is allowed
+
+ public boolean isOperationTransitionAllowed(TokenStatus oldState, TokenStatus newState) throws TPSException {
+ boolean allowed = true;
+
+ if(transitionList == null) {
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String transConfig = CFG_OPERATIONS_TRANSITIONS;
+
+ CMS.debug("TPSEngine.isOperationTransistionAllowed: getting config: " + transConfig);
+ try {
+ transitionList = configStore.getString(transConfig,null);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSProcessor.isOperationTransitionAllowed: Internal error getting config value for operations transition list!",
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+
+ if(transitionList == null) {
+ throw new TPSException(
+ "TPSProcessor.isOperationTransitionAllowed: Can't find non null config value for operations transition list!",
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+
+ CMS.debug("TPSEngine.isOperationTransistionAllowed: transitionList is: " + transitionList);
+
+
+ }
+
+ String transition = oldState.toInt() + ":" + newState.toInt();
+
+ CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition);
+
+ if(transitionList.indexOf(transition) == -1) {
+ CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition);
+ allowed = false;
+ }
+
+ CMS.debug("TPSEngine.isOperationTransistionAllowed: checking for transition: " + transition + " allowed: " + allowed);
+
+ return allowed;
+
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/installer/CAInfoPanel.java b/base/tps/src/org/dogtagpki/server/tps/installer/CAInfoPanel.java
new file mode 100644
index 000000000..4c5371f20
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/installer/CAInfoPanel.java
@@ -0,0 +1,171 @@
+package org.dogtagpki.server.tps.installer;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.cert.CertificateException;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.velocity.context.Context;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.crypto.TokenException;
+import org.xml.sax.SAXException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.csadmin.ConfigurationUtils;
+import com.netscape.cms.servlet.csadmin.WizardPanelBase;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+
+public class CAInfoPanel extends WizardPanelBase {
+
+ public CAInfoPanel() {
+ }
+
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("CA Information");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("CA Information");
+ setId(id);
+ }
+
+ public boolean shouldSkip() {
+ return false;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.cainfo.select", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.cainfo.select", "");
+ if (s != null && !s.isEmpty()) {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ return new PropertySet();
+ }
+
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ String errorString = "";
+ context.put("title", "CA Information");
+ context.put("panel", "admin/console/config/cainfopanel.vm");
+ IConfigStore config = CMS.getConfigStore();
+
+ if (isPanelDone()) {
+ // TODO - put the selected URL in selection box.
+ // String s = config.getString("preop.cainfo.select");
+ }
+
+ // get CA URLs
+ Vector<String> v;
+ try {
+ v = null;
+ v = ConfigurationUtils.getUrlListFromSecurityDomain(config, "CA", "SecurePort");
+ if (v == null) {
+ errorString = "No CA found. CA, TKS and optionally DRM " +
+ " must be installed prior to TPS installation";
+ context.put("errorString", errorString);
+ context.put("preop.cainfo.errorString", errorString);
+ return;
+ }
+
+ config.putString("preop.ca.list", StringUtils.join(v,","));
+ config.commit(false);
+ } catch (EBaseException | IOException | SAXException | ParserConfigurationException e) {
+ e.printStackTrace();
+ errorString = "Failed to get CA information from security domain. " + e;
+ context.put("errorString", errorString);
+ context.put("preop.cainfo.errorString", errorString);
+ return;
+ }
+
+ context.put("urls", v);
+ context.put("urls_size", v.size());
+ context.put("errorString", "");
+ context.put("preop.cainfo.errorString", "");
+ }
+
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String subsystemNick;
+ try {
+ subsystemNick = config.getString("preop.cert.subsystem.nickname");
+ } catch (EBaseException e1) {
+ e1.printStackTrace();
+ throw new IOException("Failed to get subsystem certificate nickname");
+ }
+
+ String url = HttpInput.getString(request, "urls");
+ URI caUri = null;
+ String parsedURI = url.substring(url.lastIndexOf("http"));
+ try {
+ caUri = new URI(parsedURI);
+ } catch (URISyntaxException e) {
+ throw new IOException("Invalid URI " + parsedURI);
+ }
+
+ // TODO: get installer from session
+ TPSInstaller installer = new TPSInstaller();
+ installer.configureCAConnector(caUri, subsystemNick);
+
+ String host = caUri.getHost();
+ int port = caUri.getPort();
+
+ // Note -
+ // list contains EE port. If admin port is different, it needs to
+ // be obtained from security domain and used to get the cert chain
+
+ /* int admin_port = ConfigurationUtils.getPortFromSecurityDomain(domainXML,
+ host, port, "CA", "SecurePort", "SecureAdminPort");
+ */
+
+ try {
+ ConfigurationUtils.importCertChain(host, port, "/ca/admin/ca/getCertChain", "ca");
+ } catch (CertificateException | SAXException | ParserConfigurationException
+ | NotInitializedException | TokenException | EBaseException e) {
+ e.printStackTrace();
+ throw new IOException("Failed to import certificate chain from CA");
+ }
+
+ context.put("updateStatus", "success");
+ }
+
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/installer/DRMInfoPanel.java b/base/tps/src/org/dogtagpki/server/tps/installer/DRMInfoPanel.java
new file mode 100644
index 000000000..2237f9e53
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/installer/DRMInfoPanel.java
@@ -0,0 +1,154 @@
+package org.dogtagpki.server.tps.installer;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.velocity.context.Context;
+import org.xml.sax.SAXException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.csadmin.ConfigurationUtils;
+import com.netscape.cms.servlet.csadmin.WizardPanelBase;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+
+public class DRMInfoPanel extends WizardPanelBase {
+
+ public DRMInfoPanel() {
+ }
+
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("DRM Information");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("DRM Information");
+ setId(id);
+ }
+
+ public boolean shouldSkip() {
+ return false;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.krainfo.select", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.krainfo.select", "");
+ if (s != null && ! s.isEmpty()) {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ return new PropertySet();
+ }
+
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ String errorString = "";
+ context.put("title", "DRM Information");
+ context.put("panel", "admin/console/config/drminfopanel.vm");
+ IConfigStore config = CMS.getConfigStore();
+
+ if (isPanelDone()) {
+ //TODO - put selected entry in selection box.
+ //String s = config.getString("preop.krainfo.select");
+ }
+
+ // get KRA URLs
+ Vector<String> v = null;
+ try {
+ v = ConfigurationUtils.getUrlListFromSecurityDomain(config, "KRA", "SecurePort");
+ if (v == null) {
+ errorString = "No DRM found. CA, TKS and optionally DRM " +
+ " must be installed prior to TPS installation";
+ context.put("errorString", errorString);
+ context.put("preop.krainfo.errorString", errorString);
+ return;
+ }
+
+ config.putString("preop.kra.list", StringUtils.join(v,","));
+ config.commit(false);
+ } catch (EBaseException | IOException | SAXException | ParserConfigurationException e1) {
+ e1.printStackTrace();
+ errorString = "Failed to get DRM information from security domain. " + e1;
+ context.put("errorString", errorString);
+ context.put("preop.krainfo.errorString", errorString);
+ return;
+ }
+
+ context.put("urls", v);
+ context.put("urls_size", v.size());
+ context.put("errorString", "");
+ context.put("preop.krainfo.errorString", "");
+ }
+
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String subsystemNick;
+ try {
+ subsystemNick = config.getString("preop.cert.subsystem.nickname");
+ } catch (EBaseException e1) {
+ e1.printStackTrace();
+ throw new IOException("Failed to get subsystem certificate nickname");
+ }
+
+ String url = HttpInput.getString(request, "urls");
+ String parsedURI = url.substring(url.lastIndexOf("http"));
+ URI kraUri = null;
+ try {
+ kraUri = new URI(parsedURI);
+ } catch (URISyntaxException e) {
+ throw new IOException("Invalid URI " + parsedURI);
+ }
+
+ String choice = HttpInput.getString(request, "choice");
+ boolean keyGen = choice.equalsIgnoreCase("keygen");
+
+ // TODO: get installer from session
+ TPSInstaller installer = new TPSInstaller();
+ installer.configureKRAConnector(keyGen, kraUri, subsystemNick);
+
+ context.put("updateStatus", "success");
+ }
+
+ /**
+ * If validate() returns false, this method will be called.
+ */
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/installer/TKSInfoPanel.java b/base/tps/src/org/dogtagpki/server/tps/installer/TKSInfoPanel.java
new file mode 100644
index 000000000..0c0cf62a7
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/installer/TKSInfoPanel.java
@@ -0,0 +1,150 @@
+package org.dogtagpki.server.tps.installer;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Vector;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.velocity.context.Context;
+import org.xml.sax.SAXException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.property.PropertySet;
+import com.netscape.certsrv.util.HttpInput;
+import com.netscape.cms.servlet.csadmin.ConfigurationUtils;
+import com.netscape.cms.servlet.csadmin.WizardPanelBase;
+import com.netscape.cms.servlet.wizard.WizardServlet;
+
+public class TKSInfoPanel extends WizardPanelBase {
+
+ public TKSInfoPanel() {
+ }
+
+ public void init(ServletConfig config, int panelno)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("TKS Information");
+ }
+
+ public void init(WizardServlet servlet, ServletConfig config, int panelno, String id)
+ throws ServletException {
+ setPanelNo(panelno);
+ setName("TKS Information");
+ setId(id);
+ }
+
+ public boolean shouldSkip() {
+ return false;
+ }
+
+ public void cleanUp() throws IOException {
+ IConfigStore cs = CMS.getConfigStore();
+ cs.putString("preop.tksinfo.select", "");
+ }
+
+ public boolean isPanelDone() {
+ IConfigStore cs = CMS.getConfigStore();
+ try {
+ String s = cs.getString("preop.tksinfo.select", "");
+ if (s != null && !s.isEmpty()) {
+ return true;
+ }
+ } catch (EBaseException e) {
+ }
+ return false;
+ }
+
+ public PropertySet getUsage() {
+ return new PropertySet();
+ }
+
+
+ public void display(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ String errorString = "";
+ context.put("title", "TKS Information");
+ context.put("panel", "admin/console/config/tksinfopanel.vm");
+ IConfigStore config = CMS.getConfigStore();
+
+ if (isPanelDone()) {
+ // TODO - put selected URL in selection box
+ // String s = config.getString("preop.tksinfo.select");
+ }
+
+ // get TKS URLs
+ Vector<String> v = null;
+ try {
+ v = ConfigurationUtils.getUrlListFromSecurityDomain(config, "TKS", "SecureAdminPort");
+ if (v == null) {
+ errorString = "No TKS found. CA, TKS and optionally DRM " +
+ " must be installed prior to TPS installation";
+ context.put("errorString", errorString);
+ context.put("preop.tksinfo.errorString", errorString);
+ return;
+ }
+
+ config.putString("preop.tks.list", StringUtils.join(v,","));
+ config.commit(false);
+ } catch (EBaseException | IOException | SAXException | ParserConfigurationException e) {
+ e.printStackTrace();
+ errorString = "Failed to get TKS information from security domain. " + e;
+ context.put("errorString", errorString);
+ context.put("preop.tksinfo.errorString", errorString);
+ return;
+ }
+
+ context.put("urls", v);
+ context.put("urls_size", v.size());
+ context.put("errorString", "");
+ context.put("preop.tksinfo.errorString", "");
+ }
+
+ public void validate(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ }
+
+ public void update(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) throws IOException {
+ IConfigStore config = CMS.getConfigStore();
+ String subsystemNick;
+ try {
+ subsystemNick = config.getString("preop.cert.subsystem.nickname");
+ } catch (EBaseException e1) {
+ e1.printStackTrace();
+ throw new IOException("Failed to get subsystem certificate nickname");
+ }
+
+ String url = HttpInput.getString(request, "urls");
+ String parsedURI = url.substring(url.lastIndexOf("http"));
+ URI tksUri = null;
+ try {
+ tksUri = new URI(parsedURI);
+ } catch (URISyntaxException e) {
+ throw new IOException("Invalid URI " + parsedURI);
+ }
+
+ // TODO: get installer from session
+ TPSInstaller installer = new TPSInstaller();
+ installer.configureTKSConnector(tksUri, subsystemNick);
+
+ context.put("updateStatus", "success");
+ }
+
+ public void displayError(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context) {
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/installer/TPSInstaller.java b/base/tps/src/org/dogtagpki/server/tps/installer/TPSInstaller.java
new file mode 100644
index 000000000..2779e5b98
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/installer/TPSInstaller.java
@@ -0,0 +1,124 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.installer;
+
+import java.net.URI;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.config.ConnectorDatabase;
+import org.dogtagpki.server.tps.config.ConnectorRecord;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+
+/**
+ * Utility class for TPS installation to be used both by the RESTful installer
+ * and the UI Panels.
+ *
+ * @author alee
+ *
+ */
+
+public class TPSInstaller {
+
+ public TPSInstaller() {
+ }
+
+ public void configureCAConnector(URI uri, String nickname) {
+
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+ IConfigStore cs = CMS.getConfigStore();
+
+ // TODO: see if this is only needed by wizard-based installation
+ cs.putString("preop.cainfo.select", uri.toString());
+
+ try {
+ database.addCAConnector(uri.getHost(), uri.getPort(), nickname);
+
+ } catch (Exception e) {
+ throw new PKIException("Unable to create CA connector", e);
+ }
+ }
+
+ public void configureTKSConnector(URI uri, String nickname) {
+
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+ IConfigStore cs = CMS.getConfigStore();
+
+ // TODO: see if this is only needed by wizard-based installation
+ cs.putString("preop.tksinfo.select", uri.toString());
+
+ try {
+ database.addTKSConnector(uri.getHost(), uri.getPort(), nickname, false);
+
+ } catch (Exception e) {
+ throw new PKIException("Unable to create TKS connector", e);
+ }
+ }
+
+ public void configureKRAConnector(Boolean keygen, URI uri, String nickname) {
+
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+ IConfigStore cs = CMS.getConfigStore();
+
+ if (keygen) {
+ // TODO: see if this is only needed by wizard-based installation
+ cs.putString("preop.krainfo.select", uri.toString());
+
+ // TODO: see if there are other profiles need to be configured
+ cs.putString("op.enroll.userKey.keyGen.encryption.serverKeygen.enable", "true");
+ cs.putString("op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.enable", "true");
+ cs.putString("op.enroll.soKey.keyGen.encryption.serverKeygen.enable", "true");
+ cs.putString("op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.enable", "true");
+
+ try {
+ database.addKRAConnector(uri.getHost(), uri.getPort(), nickname);
+
+ } catch (Exception e) {
+ throw new PKIException("Unable to create KRA connector", e);
+ }
+
+ } else { // no keygen
+ // TODO: see if there are other profiles need to be configured
+ cs.putString("op.enroll.userKey.keyGen.encryption.serverKeygen.enable", "false");
+ cs.putString("op.enroll.userKeyTemporary.keyGen.encryption.serverKeygen.enable", "false");
+ cs.putString("op.enroll.userKey.keyGen.encryption.recovery.destroyed.scheme", "GenerateNewKey");
+ cs.putString("op.enroll.userKeyTemporary.keyGen.encryption.recovery.onHold.scheme", "GenerateNewKey");
+ cs.putString("op.enroll.soKey.keyGen.encryption.serverKeygen.enable", "false");
+ cs.putString("op.enroll.soKeyTemporary.keyGen.encryption.serverKeygen.enable", "false");
+ cs.putString("op.enroll.soKey.keyGen.encryption.recovery.destroyed.scheme", "GenerateNewKey");
+ cs.putString("op.enroll.soKeyTemporary.keyGen.encryption.recovery.onHold.scheme", "GenerateNewKey");
+ }
+
+ try {
+ String id = "tks1"; // there is only one default TKS connector
+
+ // update keygen in TKS connector
+ ConnectorRecord record = database.getRecord(id);
+ record.setProperty(database.prefix + "." + id + ".serverKeygen", keygen.toString());
+ database.updateRecord(id, record);
+
+ } catch (Exception e) {
+ throw new PKIException("Unable to update TKS connector", e);
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/main/AttributeSpec.java b/base/tps/src/org/dogtagpki/server/tps/main/AttributeSpec.java
new file mode 100644
index 000000000..444f22c4b
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/main/AttributeSpec.java
@@ -0,0 +1,71 @@
+package org.dogtagpki.server.tps.main;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+public class AttributeSpec {
+
+ public AttributeSpec() {
+ }
+
+ private long id;
+ private byte type;
+ private TPSBuffer data;
+
+ public void setAttributeID(long attribute_id) {
+ id = attribute_id;
+ }
+
+ public long getAttributeID() {
+ return id;
+ }
+
+ public void setType(byte type) {
+ this.type = type;
+ }
+
+ public byte getType() {
+ return type;
+ }
+
+ public void setData(TPSBuffer data) {
+ this.data = data;
+
+ }
+
+ public TPSBuffer getData() {
+ TPSBuffer theData = new TPSBuffer();
+ theData.addLong4Bytes(id);
+ theData.add(type);
+
+ if (type == 0) { /* String */
+ theData.addInt2Bytes(data.size());
+ }
+ theData.add(data);
+ return theData;
+ }
+
+ public TPSBuffer getValue() {
+ return data;
+ }
+
+ public static AttributeSpec parse(TPSBuffer b, int offset) {
+ AttributeSpec o = new AttributeSpec();
+
+ long id = b.getLongFrom4Bytes(offset);
+
+ o.setAttributeID(id);
+
+ o.setType(b.at(offset + 4));
+ // DatatypeString contains two bytes for AttributeLen of AttributeData
+ TPSBuffer theData;
+ if (o.getType() == (byte) 0)
+ theData = b.substr(offset + 5 + 2, b.size() - 5 - 2);
+ else
+ theData = b.substr(offset + 5, b.size() - 5);
+
+ o.setData(theData);
+ return o;
+
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java b/base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java
new file mode 100644
index 000000000..a8dbdb1bc
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/main/ObjectSpec.java
@@ -0,0 +1,456 @@
+package org.dogtagpki.server.tps.main;
+
+import java.util.ArrayList;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.TPSException;
+
+import sun.security.pkcs11.wrapper.PKCS11Constants;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class ObjectSpec {
+
+ public ObjectSpec()
+ {
+ attributeSpecs = new ArrayList<AttributeSpec>();
+ }
+
+ final static int DATATYPE_STRING = 0;
+ final static int DATATYPE_INTEGER = 1;
+ final static int DATATYPE_BOOL_FALSE = 2;
+ final static int DATATYPE_BOOL_TRUE = 3;
+
+ private long objectID;
+ private long fixedAttributes;
+ private ArrayList<AttributeSpec> attributeSpecs;
+ private int parseRead;
+
+ public int getParseReadSize() {
+ return parseRead;
+ }
+
+ /**
+ * Parse 'c' object.
+ */
+ public static void parseAttributes(String objectID, ObjectSpec objectSpec, TPSBuffer b)
+ {
+ int curpos = 7;
+ long fixedAttrs = 0;
+ int xclass = 0;
+ int id = 0;
+
+ /* skip first 7 bytes */
+
+ while (curpos < ((b.size()))) {
+ long attribute_id = b.getLongFrom4Bytes(curpos);
+ int attribute_size = b.getIntFrom2Bytes(curpos + 4);
+
+ byte type = 0;
+ TPSBuffer data = new TPSBuffer();
+ boolean found = false;
+ /* modify fixed attributes */
+
+ switch ((int) attribute_id) {
+ case (int) PKCS11Constants.CKA_TOKEN:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00000080;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_PRIVATE:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00000100;
+ } else {
+ }
+ break;
+ case (int) PKCS11Constants.CKA_MODIFIABLE:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00000200;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_DERIVE:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00000400;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_LOCAL:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00000800;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_ENCRYPT:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00001000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_DECRYPT:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00002000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_WRAP:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00004000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_UNWRAP:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00008000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_SIGN:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00010000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_SIGN_RECOVER:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00020000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_VERIFY:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00040000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_VERIFY_RECOVER:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00080000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_SENSITIVE:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00100000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_ALWAYS_SENSITIVE:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00200000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_EXTRACTABLE:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00400000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_NEVER_EXTRACTABLE:
+ if (b.at(curpos + 6) != 0) {
+ fixedAttrs |= 0x00800000;
+ }
+ break;
+ case (int) PKCS11Constants.CKA_SUBJECT:
+ type = DATATYPE_STRING;
+ data = b.substr(curpos + 6, attribute_size);
+ /* build by PKCS11 */
+ break;
+ case (int) PKCS11Constants.CKA_LABEL:
+ type = DATATYPE_STRING;
+ data = b.substr(curpos + 6, attribute_size);
+ found = true;
+ break;
+ case (int) PKCS11Constants.CKA_MODULUS:
+ type = DATATYPE_STRING;
+ data = b.substr(curpos + 6, attribute_size);
+ /* build by PKCS11 */
+ break;
+ case (int) PKCS11Constants.CKA_ID:
+ type = DATATYPE_STRING;
+ data = b.substr(curpos + 6, attribute_size);
+ /* build by PKCS11 */
+ break;
+ case (int) PKCS11Constants.CKA_KEY_TYPE:
+ type = DATATYPE_INTEGER;
+ data = b.substr(curpos + 6, 4);
+ found = true;
+ /* build by PKCS11 */
+ break;
+ case (int) PKCS11Constants.CKA_CLASS:
+ type = DATATYPE_INTEGER;
+ data = b.substr(curpos + 6, 4);
+ xclass = data.at(0);
+ /* build by PKCS11 */
+ break;
+ case (int) PKCS11Constants.CKA_PUBLIC_EXPONENT:
+ type = DATATYPE_STRING;
+ data = b.substr(curpos + 6, attribute_size);
+ /* build by PKCS11 */
+ break;
+ case (int) PKCS11Constants.CKA_CERTIFICATE_TYPE:
+ type = DATATYPE_INTEGER;
+ data = b.substr(curpos + 6, 4);
+ /* build by PKCS11 */
+ break;
+
+ case (int) PKCS11Constants.CKA_EC_PARAMS:
+ type = DATATYPE_STRING;
+ data = b.substr(curpos + 6, attribute_size);
+ found = true;
+ break;
+
+ case (int) PKCS11Constants.CKA_EC_POINT:
+ type = DATATYPE_STRING;
+ data = b.substr(curpos + 6, attribute_size);
+ found = true;
+ break;
+ default:
+ CMS.debug("ObjectSpec.parseKeyBlob" +
+ "skipped attribute_id = " +
+ attribute_id);
+ break;
+ }
+
+ if (found) {
+ /* add attribute spec */
+ AttributeSpec attrSpec = new AttributeSpec();
+ attrSpec.setAttributeID(attribute_id);
+ attrSpec.setType(type);
+
+ switch (type) {
+ case DATATYPE_STRING:
+ attrSpec.setData(data);
+ break;
+ case DATATYPE_INTEGER:
+ attrSpec.setData(data);
+ break;
+ case DATATYPE_BOOL_FALSE:
+ break;
+ case DATATYPE_BOOL_TRUE:
+ break;
+ default:
+ break;
+ }
+
+ objectSpec.addAttributeSpec(attrSpec);
+ }
+
+ curpos += 4 + 2 + attribute_size;
+ }
+
+ //Here the objectID fixed attribute gets massaged. Here's how:
+ // The objectID becomes the cert container id, ex: 01
+ // Each key pair associated with the cert must have the same ID.
+ // This is done by math using the following formula:
+ // Given a cert id of "2", the keyAttrIds of the keys are originally
+ // configured as k4 and k5. Note that one is twice the cert id, and
+ // the other is twice the cert id plus 1. In order to map the key ids
+ // down to the cert's id, the code below changes both "4" and "5" back
+ // to "2".
+
+ int val = (objectID.charAt(1) - '0');
+ switch (objectID.charAt(0)) {
+ case 'c':
+
+ id = val;
+
+ break;
+ case 'k':
+ if ((val % 2) != 0) {
+ id = (val - 1) / 2;
+ } else {
+ id = (val / 2);
+
+ }
+
+ break;
+ }
+
+ objectSpec.setFixedAttributes(fixedAttrs | (xclass << 4) | id);
+ }
+
+ /**
+ * Parse 'c' object.
+ */
+ public static void parseCertificateAttributes(String objectID, ObjectSpec objectSpec, TPSBuffer b)
+ {
+ parseAttributes(objectID, objectSpec, b);
+ }
+
+ /**
+ * Parse 'k' object.
+ */
+ public static void parseKeyAttributes(String objectID, ObjectSpec objectSpec, TPSBuffer b)
+ {
+ parseAttributes(objectID, objectSpec, b);
+ }
+
+ /**
+ * Parse 'C' object.
+ */
+ public static void parseCertificateBlob(String objectID, ObjectSpec objectSpec, TPSBuffer b)
+ {
+ long fixedAttrs = 0;
+ int xclass = 0;
+ int id = 0;
+
+ AttributeSpec value = new AttributeSpec();
+ value.setAttributeID((int) PKCS11Constants.CKA_VALUE);
+ value.setType((byte) DATATYPE_STRING);
+ value.setData(b);
+ objectSpec.addAttributeSpec(value);
+
+ fixedAttrs = 0x00000080; /* CKA_TOKEN */
+ xclass = (int) PKCS11Constants.CKO_CERTIFICATE;
+ id = objectID.charAt(1) - '0';
+
+ objectSpec.setFixedAttributes(fixedAttrs | (xclass << 4) | id);
+ }
+
+ /**
+ * Convert object from token into object spec.
+ *
+ * Reference:
+ * http://netkey/design/applet_readable_object_spec-0.1.txt
+ * http://netkey/design/pkcs11obj.txt
+ *
+ * @throws TPSException
+ */
+ public static ObjectSpec parseFromTokenData(long objid, TPSBuffer b) throws TPSException
+ {
+ String objectID = null;
+
+ StringBuilder idBuilder = new StringBuilder();
+
+ ObjectSpec o = new ObjectSpec();
+ o.setObjectID(objid);
+
+ char[] b1 = new char[4];
+ b1[0] = (char) ((objid >> 24) & 0xff);
+ b1[1] = (char) ((objid >> 16) & 0xff);
+ b1[2] = (char) ((objid >> 8) & 0xff);
+ b1[3] = (char) (objid & 0xff);
+
+ idBuilder.append(b1[0]);
+ idBuilder.append(b1[1]);
+ idBuilder.append(b1[2]);
+ idBuilder.append(b1[3]);
+
+ objectID = idBuilder.toString();
+ switch (b1[0]) {
+ case 'c': /* certificate attributes */
+ parseCertificateAttributes(objectID, o, b);
+ break;
+ case 'k': /* public key or private key attributes */
+ parseKeyAttributes(objectID, o, b);
+ break;
+ case 'C': /* certificate in DER */
+ parseCertificateBlob(objectID, o, b);
+ break;
+ default:
+ CMS.debug("ObjectSpec::ParseKeyBlob" +
+ "unknown objectID = " + objectID.charAt(0));
+ throw new TPSException("ObjectSpec parseFromToken data: Invalid object type, aborting..");
+ }
+
+ return o;
+ }
+
+ public static ObjectSpec parse(TPSBuffer b, int offset) throws TPSException
+ {
+ int sum = 0;
+
+ if ((b.size() - offset) < 10)
+ return null;
+
+ ObjectSpec o = new ObjectSpec();
+ long id = b.getLongFrom4Bytes(offset);
+
+ o.setObjectID(id);
+ long attribute = b.getLongFrom4Bytes(offset + 4);
+
+ o.setFixedAttributes(attribute);
+ int count = b.getIntFrom2Bytes(offset + 8);
+ sum += 10;
+ int curpos = offset + 10;
+ for (int i = 0; i < count; i++) {
+ int len = 0;
+ switch (b.at(curpos + 4)) {
+ case DATATYPE_STRING:
+ len = 4 + 1 + 2 + b.getIntFrom2Bytes(curpos + 5);
+ break;
+ case DATATYPE_INTEGER:
+ len = 4 + 1 + 4;
+ break;
+ case DATATYPE_BOOL_FALSE:
+ len = 4 + 1;
+ break;
+ case DATATYPE_BOOL_TRUE:
+ len = 4 + 1;
+ break;
+ default:
+ CMS.debug("ObjectSpec::parse" +
+ "unknown DataType = " + b.at(curpos + 4));
+ throw new TPSException("ObjectSpec parse: Invalid data type, aborting..");
+ }
+ TPSBuffer attr = b.substr(curpos, len);
+ AttributeSpec attrSpec = AttributeSpec.parse(attr, 0);
+ o.addAttributeSpec(attrSpec);
+ curpos += len;
+ sum += len;
+ }
+ o.setParseRead(sum);
+ return o;
+ }
+
+ private void setParseRead(int nread) {
+ parseRead = nread;
+ }
+
+ void setObjectID(long v)
+ {
+ objectID = v;
+ }
+
+ public long getObjectID()
+ {
+ return objectID;
+ }
+
+ public void setFixedAttributes(long v)
+ {
+ fixedAttributes = v;
+ }
+
+ public long getFixedAttributes()
+ {
+ return fixedAttributes;
+ }
+
+ public int getAttributeSpecCount()
+ {
+ return attributeSpecs.size();
+ }
+
+ public AttributeSpec getAttributeSpec(int p)
+ {
+ return attributeSpecs.get(p);
+ }
+
+ public void addAttributeSpec(AttributeSpec p)
+ {
+ attributeSpecs.add(p);
+ }
+
+ public void removeAttributeSpec(int p)
+ {
+ attributeSpecs.remove(p);
+
+ }
+
+ TPSBuffer getData()
+ {
+ TPSBuffer data = new TPSBuffer();
+
+ data.addLong4Bytes(objectID);
+ data.addLong4Bytes(fixedAttributes);
+
+ int attributeCount = getAttributeSpecCount();
+ data.addInt2Bytes(attributeCount);
+ for (int i = 0; i < attributeCount; i++) {
+ AttributeSpec spec = getAttributeSpec(i);
+ data.add(spec.getData());
+ }
+
+ return data;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/main/PKCS11Obj.java b/base/tps/src/org/dogtagpki/server/tps/main/PKCS11Obj.java
new file mode 100644
index 000000000..6224c3f81
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/main/PKCS11Obj.java
@@ -0,0 +1,689 @@
+package org.dogtagpki.server.tps.main;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.main.Util;
+
+import sun.security.pkcs11.wrapper.PKCS11Constants;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class PKCS11Obj {
+
+ private ArrayList<ObjectSpec> objectSpecs;
+
+ public PKCS11Obj() {
+ objectSpecs = new ArrayList<ObjectSpec>();
+ }
+
+ private int oldFormatVersion;
+ private int oldObjectVersion;
+
+ private int formatVersion;
+ private int objectVersion;
+
+ private TPSBuffer tokenName;
+ private TPSBuffer cuid;
+
+ public static PKCS11Obj parse(TPSBuffer b, int offset) throws TPSException, DataFormatException, IOException
+ {
+ PKCS11Obj o = new PKCS11Obj();
+
+ int formatVersion = b.getIntFrom2Bytes(0);
+
+ CMS.debug("PKCS11Obj.parse: formatVersion read from blob: " + formatVersion);
+
+ o.setFormatVersion(formatVersion);
+ int objectVersion = b.getIntFrom2Bytes(2);
+
+ CMS.debug("PKCS11Obj.parse: objectVersion read from blob: " + objectVersion);
+
+ o.setObjectVersion(objectVersion);
+ o.setCUID(b.substr(offset + 4, 10));
+
+ int compressionType = b.getIntFrom2Bytes(14);
+ int dataSize = b.getIntFrom2Bytes(16);
+
+ int dataOffset = b.getIntFrom2Bytes(18);
+
+ CMS.debug("PKCS11Obj.parse: commpressionType: " + compressionType + " DataSize:"
+ + dataSize + "DataOffset: " + dataOffset + " data: " + b.toHexString());
+
+ TPSBuffer data = new TPSBuffer();
+
+ if (compressionType == 0) { /* no compression */
+ data.add(b.substr(offset + dataOffset, dataSize));
+ } else if (compressionType == 1) { /* zlib */
+ TPSBuffer compressedData = b.substr(offset + dataOffset, dataSize);
+
+ TPSBuffer uncompressedData = uncompress(
+ compressedData);
+
+ data = new TPSBuffer(uncompressedData);
+ } else {
+ throw new TPSException("PKCS11Obj.parse: error parsing object data!");
+ }
+
+ CMS.debug("PKCS11Obj.parse: uncompressed data: " + data.toHexString());
+
+ int objOffset = data.getIntFrom2Bytes(0);
+ int objCount = data.getIntFrom2Bytes(2);
+
+ //Check for absurd number of objects
+ if (objCount < 0 || objCount > 100) {
+ throw new TPSException("PKCS11Obj.parse: error parsing object data!");
+ }
+
+ TPSBuffer tokenName = data.substr(5, data.at(4));
+ o.setTokenName(tokenName);
+
+ if (tokenName != null)
+ System.out.println("tokenName: " + tokenName.toHexString());
+ System.out.println("uncompressed data size: " + data.size());
+
+ CMS.debug("PKCS11Obj.parse" + "objcount = " + objCount);
+
+ int curpos = objOffset;
+ int nread = 0;
+ for (int i = 0; i < objCount; i++) {
+ CMS.debug("PKCS11Ob.parse: working on object " + i);
+ ObjectSpec objSpec = ObjectSpec.parse(data, curpos);
+
+ if (objSpec == null)
+ continue;
+
+ nread = objSpec.getParseReadSize();
+ o.addObjectSpec(objSpec);
+
+ long oid = objSpec.getObjectID();
+ char[] b1 = new char[2];
+
+ b1[0] = (char) ((oid >> 24) & 0xff);
+ b1[1] = (char) ((oid >> 16) & 0xff);
+
+ CMS.debug("PKCS11Obj.parse " + "About to parse = " + b1[0] + ":" + b1[1]);
+ System.out.println("PKCS11Obj.parse " + "About to parse = " + b1[0] + ":" + b1[1]);
+
+ // add corresponding 'C' object for 'c'
+ if (b1[0] == 'c') {
+ for (int j = 0; j < objSpec.getAttributeSpecCount(); j++) {
+ AttributeSpec as = objSpec.getAttributeSpec(j);
+ if (as.getAttributeID() == PKCS11Constants.CKA_VALUE) {
+ if (as.getType() == (byte) 0) {
+ TPSBuffer cert = as.getValue();
+
+ long l1 = 0x43; // 'C'
+ long l2 = b1[1];
+
+ l1 = (l1 & 0xff) << 24;
+ l2 = (l2 & 0xff) << 16;
+ long certid = l1 + l2;
+
+ ObjectSpec certSpec =
+ ObjectSpec.parseFromTokenData(
+ certid, cert);
+ o.addObjectSpec(certSpec);
+
+ objSpec.removeAttributeSpec(j);
+ break;
+ }
+ }
+ }
+
+ }
+
+ curpos += nread;
+ }
+ return o;
+ }
+
+ public boolean doesCertIdExist(String certId) {
+
+ boolean foundObj = false;
+ char[] certChars = certId.toCharArray();
+
+ for (ObjectSpec objSpec : objectSpecs) {
+
+ long oid = objSpec.getObjectID();
+
+ char[] b1 = new char[2];
+
+ b1[0] = (char) ((oid >> 24) & 0xff);
+ b1[1] = (char) ((oid >> 16) & 0xff);
+
+ if (Arrays.equals(b1, certChars)) {
+ foundObj = true;
+ CMS.debug("PKCD11Obj.doesCertIdExist: match found!");
+ break;
+ }
+
+ }
+
+ return foundObj;
+ }
+
+ public void setFormatVersion(int v)
+ {
+ formatVersion = v;
+ }
+
+ public void setObjectVersion(int v)
+ {
+ CMS.debug("PKCS11Obj.setObjectVersion: setting to: " + v);
+ objectVersion = v;
+ }
+
+ public int getFormatVersion()
+ {
+ return formatVersion;
+ }
+
+ public int getObjectVersion()
+ {
+ return objectVersion;
+ }
+
+ public void setCUID(TPSBuffer cuid)
+ {
+ this.cuid = cuid;
+ ;
+ }
+
+ public TPSBuffer getCUID()
+ {
+ return cuid;
+ }
+
+ public void setTokenName(TPSBuffer tokenName)
+ {
+ this.tokenName = tokenName;
+ }
+
+ public TPSBuffer getTokenName()
+ {
+ return tokenName;
+ }
+
+ int getObjectSpecCount()
+ {
+ return objectSpecs.size();
+ }
+
+ public ObjectSpec getObjectSpec(int p)
+ {
+ return objectSpecs.get(p);
+ }
+
+ public void addObjectSpec(ObjectSpec p)
+ {
+ CMS.debug("PKCS11Obj.adObjectSpec entering.. " + p);
+ for (ObjectSpec objSpec : objectSpecs) {
+
+ long oid = objSpec.getObjectID();
+
+ if (oid == p.getObjectID()) {
+ objectSpecs.remove(objSpec);
+ char[] b1 = new char[2];
+
+ b1[0] = (char) ((oid >> 24) & 0xff);
+ b1[1] = (char) ((oid >> 16) & 0xff);
+ String oidStr = new String(b1);
+ CMS.debug("PKCS11Obj.addObjectSpec: found dup, removing...: " + oidStr);
+ break;
+ }
+ }
+
+ objectSpecs.add(p);
+ }
+
+ public void removeObjectSpec(int p)
+ {
+ objectSpecs.remove(p);
+
+ }
+
+ public void removeAllObjectSpecs() {
+
+ objectSpecs.clear();
+ }
+
+ private TPSBuffer getRawHeaderData(int compressionType, TPSBuffer data) {
+ TPSBuffer header = new TPSBuffer();
+
+ CMS.debug("PKCS11Obj.getRawHeaderData: " + " formatVersion: " + formatVersion + " objectVersion: "
+ + objectVersion);
+ header.add((byte) ((formatVersion >> 8) & 0xff));
+ header.add((byte) (formatVersion & 0xff));
+ header.add((byte) ((objectVersion >> 8) & 0xff));
+ header.add((byte) (objectVersion & 0xff));
+ header.add(cuid);
+ // COMP_NONE = 0x00
+ // COMP_ZLIB = 0x01
+
+ header.add((byte) ((compressionType >> 8) & 0xff));
+ header.add((byte) (compressionType & 0xff));
+ int compressedDataSize = data.size();
+ header.add((byte) ((compressedDataSize >> 8) & 0xff));
+ header.add((byte) (compressedDataSize & 0xff));
+ int compressedDataOffset = 20;
+ header.add((byte) ((compressedDataOffset >> 8) & 0xff));
+ header.add((byte) (compressedDataOffset & 0xff));
+
+ CMS.debug("PKCS11Obj.getRawHeaderData: returning: " + header.toHexString());
+
+ return header;
+
+ }
+
+ private TPSBuffer getRawData() {
+ TPSBuffer data = new TPSBuffer();
+
+ int objectOffset = tokenName.size() + 2 + 3;
+
+ data.add((byte) ((objectOffset >> 8) & 0xff));
+ data.add((byte) (objectOffset & 0xff));
+ int objectCount = getObjectSpecCount();
+ int objectCountX = objectCount;
+ if (objectCountX == 0) {
+ objectCountX = 0;
+ } else {
+ objectCountX = objectCountX - (objectCountX / 4);
+ }
+
+ data.add((byte) ((objectCountX >> 8) & 0xff));
+ data.add((byte) (objectCountX & 0xff));
+ data.add((byte) (tokenName.size() & 0xff));
+ data.add(tokenName);
+
+ CMS.debug("PKCS11Obj:getRawData: objectCount: " + objectCount);
+
+ for (int i = 0; i < objectCount; i++) {
+ ObjectSpec spec = getObjectSpec(i);
+ long objectID = spec.getObjectID();
+ char c = (char) ((objectID >> 24) & 0xff);
+ long fixedAttrs = spec.getFixedAttributes();
+ int xclass = (int) ((fixedAttrs & 0x70) >> 4);
+ char cont_id = (char) ((objectID >> 16) & 0xff);
+ long id = (int) (fixedAttrs & 0x0f);
+ /* locate all certificate objects */
+ if (c == 'c' && xclass == PKCS11Constants.CKO_CERTIFICATE) {
+
+ //We need to use the container id, there may be more than one cert
+ //with the same CKA_ID byte
+
+ id = cont_id - '0';
+
+ /* locate the certificate object */
+ for (int u = 0; u < objectCount; u++) {
+ ObjectSpec u_spec = getObjectSpec(u);
+ long u_objectID = u_spec.getObjectID();
+ char u_c = (char) ((u_objectID >> 24) & 0xff);
+ long u_fixedAttrs =
+ u_spec.getFixedAttributes();
+ int u_xclass = (int) ((u_fixedAttrs & 0x70) >> 4);
+ int u_id = (int) (u_fixedAttrs & 0x0f);
+ if (u_c == 'C' && u_xclass == PKCS11Constants.CKO_CERTIFICATE && u_id == id) {
+ CMS.debug("PKCSObj:getRawData: found cert object: id: " + id + " u_id: " + u_id);
+
+ AttributeSpec u_attr =
+ u_spec.getAttributeSpec(0);
+ AttributeSpec n_attr = new AttributeSpec();
+ n_attr.setAttributeID(u_attr.getAttributeID());
+ n_attr.setType(u_attr.getType());
+ n_attr.setData(u_attr.getValue());
+ spec.addAttributeSpec(n_attr);
+ }
+ }
+
+ data.add(spec.getData());
+
+ /* locate public object */
+ for (int x = 0; x < objectCount; x++) {
+ ObjectSpec x_spec = getObjectSpec(x);
+ long x_fixedAttrs =
+ x_spec.getFixedAttributes();
+ int x_xclass = (int) ((x_fixedAttrs & 0x70) >> 4);
+ int x_id = (int) (x_fixedAttrs & 0x0f);
+ if (x_xclass == PKCS11Constants.CKO_PUBLIC_KEY && x_id == id) {
+ CMS.debug("PKCSObj:getRawData: found public key object: id: " + id);
+ data.add(x_spec.getData());
+ }
+ }
+
+ /* locate private object */
+ for (int y = 0; y < objectCount; y++) {
+ ObjectSpec y_spec = getObjectSpec(y);
+ long y_fixedAttrs =
+ y_spec.getFixedAttributes();
+ int y_xclass = (int) ((y_fixedAttrs & 0x70) >> 4);
+ int y_id = (int) (y_fixedAttrs & 0x0f);
+ if (y_xclass == PKCS11Constants.CKO_PRIVATE_KEY && y_id == id) {
+ CMS.debug("PKCSObj:getRawData: found private key object: id: " + id);
+ data.add(y_spec.getData());
+ }
+ }
+ }
+ }
+
+ return data;
+
+ }
+
+ public TPSBuffer getData()
+ {
+ TPSBuffer data = getRawData();
+ TPSBuffer header = getRawHeaderData(0, data);
+
+ TPSBuffer result = new TPSBuffer(header);
+ result.add(data);
+ return result;
+ }
+
+ public TPSBuffer getCompressedData() throws TPSException, IOException
+ {
+ TPSBuffer data = getRawData(); // new TPSBuffer();
+
+ CMS.debug("PKCS11Obj.getCompressedData: " + "before compress length = " + data.size());
+ CMS.debug("PKCS11Obj.getCompressedData: " + "before compress data = " + data.toHexString());
+
+ System.out.println("Raw data before compress length: " + data.size());
+
+ TPSBuffer src_buffer = new TPSBuffer(data);
+
+ CMS.debug("PKCS11Obj.getCompressedData: " + "sizeof src_buffer = " + src_buffer.size());
+ CMS.debug("PKCS11Obj.getCompressedData: " + "data size = " + data.size());
+
+ TPSBuffer compressed = compress(src_buffer);
+ TPSBuffer header = getRawHeaderData(0x01, compressed);
+
+ TPSBuffer result = new TPSBuffer(header);
+ result.add(compressed);
+
+ CMS.debug("PKCS11Obj.getCompressedData: PKCS11 Data: " + result.toHexString());
+
+ return result;
+ }
+
+ static private TPSBuffer compress(TPSBuffer uncompressedData) throws TPSException, IOException {
+
+ if (uncompressedData == null) {
+ throw new TPSException("PKCS11Obj.uncompress: bad input data!");
+ }
+
+ byte[] data = uncompressedData.toBytesArray();
+
+ Deflater deflater = new Deflater();
+
+ deflater.setInput(data);
+
+ byte[] buffer = new byte[1024];
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
+ deflater.finish();
+ while (!deflater.finished()) {
+ int count = deflater.deflate(buffer);
+ outputStream.write(buffer, 0, count);
+ }
+ outputStream.close();
+ byte[] output = outputStream.toByteArray();
+ CMS.debug("Original: " + data.length);
+ CMS.debug("Compressed: " + output.length);
+
+ TPSBuffer result = new TPSBuffer(output);
+
+ return result;
+
+ }
+
+ static private TPSBuffer uncompress(TPSBuffer compressedData) throws TPSException, DataFormatException, IOException {
+
+ if (compressedData == null) {
+ throw new TPSException("PKCS11Obj.uncompress: bad input data!");
+ }
+ byte[] data = compressedData.toBytesArray();
+
+ Inflater inflater = new Inflater();
+ inflater.setInput(data);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
+ byte[] buffer = new byte[1024];
+ while (!inflater.finished()) {
+ int count = inflater.inflate(buffer);
+ outputStream.write(buffer, 0, count);
+ }
+ outputStream.close();
+ byte[] output = outputStream.toByteArray();
+ CMS.debug("Original: " + data.length);
+ CMS.debug("Uncompressed: " + output.length);
+
+ TPSBuffer result = new TPSBuffer(output);
+
+ return result;
+ }
+
+ public static void main(String[] args) throws TPSException, DataFormatException, IOException {
+
+ //Sample token data taken from previous server for
+ // testing this functionality.
+
+ String compressedTokenData =
+
+ "%01%00%38%4c%53%4e%06%50%00%01" +
+ "%00%00%01%08%00%01%04%03%00%14" +
+ "%78%9c%63%e0%61%e0%64%cf%ca%4d" +
+ "%4c%cf%4b%55%48%36%64%00%81%89" +
+ "%0c%4c%40%92%99%81%41%ac%38%33" +
+ "%3d%2f%33%2f%5d%21%3b%b5%52%21" +
+ "%2d%bf%48%01%a2%0e%28%29%c8%c0" +
+ "%f8%c7%a0%89%f1%07%10%cf%59%c0" +
+ "%cc%c4%c8%c4%c4%e8%69%c0%c3%c6" +
+ "%a1%d5%e6%71%ce%96%85%99%89%95" +
+ "%c1%20%d2%50%c1%40%8e%8d%39%94" +
+ "%85%4b%58%3c%28%35%45%c1%23%b1" +
+ "%44%21%38%35%b9%b4%28%b3%a4%52" +
+ "%c1%25%3f%37%31%33%cf%50%d4%40" +
+ "%18%a4%82%5b%98%a7%20%3b%53%37" +
+ "%39%51%37%2b%31%39%db%c8%50%ce" +
+ "%40%06%24%cc%2c%2c%ea%9c%5a%54" +
+ "%92%99%96%99%9c%58%92%aa%e0%58" +
+ "%5a%92%91%0f%d2%6d%20%27%ce%6b" +
+ "%68%62%60%68%60%61%60%64%68%69" +
+ "%6a%10%05%e4%5a%02%b9%e6%50%ae" +
+ "%81%a1%a1%b8%81%28%c4%6a%be%90" +
+ "%fc%ec%d4%3c%05%6f%a0%07%42%8b" +
+ "%53%8b%0c%c5%0c%44%d8%b8%38%27" +
+ "%a9%75%4e%fe%a4%93%c2%c8%28%cc" +
+ "%06%f1%92%41%24%d0%25%ec%60%d7" +
+ "%33%31%42%bd%c1%cc%c8%ce%ec%c4" +
+ "%c0%12%dc%1d%9d%b7%91%ef%a6%dd" +
+ "%8a%27%01%3f%cf%3e%3d%7e%23%78" +
+ "%4e%8f%8c%c4%89%f7%ad%4b%1c%92" +
+ "%0c%2e%1d%5d%b5%46%ad%7a%aa%d9" +
+ "%7b%13%c7%6d%07%fb%0d%67%f5%45" +
+ "%ce%3e%52%b6%fc%ed%14%87%8a%04" +
+ "%29%3d%4e%b5%b5%2e%0f%33%fc%17" +
+ "%57%1b%54%1a%f0%01%5d%23%cb%cf" +
+ "%c8%f8%9f%05%18%38%6c%07%c0%fe" +
+ "%93%15%64%01%fa%bf%51%10%e2%02" +
+ "%87%a2%d4%94%8c%c4%12%bd%e4%fc" +
+ "%5c%03%59%90%2c%1f%8b%18%8b%88" +
+ "%d6%6f%81%1f%09%45%05%16%cf%64" +
+ "%27%1d%fe%e2%99%df%c7%64%c1%37" +
+ "%cf%40%1e%24%ad%cc%22%61%20%d6" +
+ "%20%72%ec%2a%6b%5d%94%e1%bb%c0" +
+ "%6f%05%33%5a%0e%ec%90%bb%b6%29" +
+ "%b1%d4%d1%80%13%a4%40%98%85%c9" +
+ "%80%01%35%4e%98%3d%18%0c%5c%99" +
+ "%14%19%16%d6%14%64%1c%9b%d2%a4" +
+ "%90%6e%1b%e3%56%cc%d6%36%7f%5a" +
+ "%8b%1a%87%f9%79%a7%a8%92%24%c7" +
+ "%49%4b%59%02%1e%32%29%78%9a%f0" +
+ "%70%45%1c%57%b9%77%60%b7%82%c6" +
+ "%fc%fc%09%8b%f7%a8%ec%6e%51%3d" +
+ "%60%cb%58%b3%e5%5d%af%c0%f9%a6" +
+ "%c7%d9%c6%c0%44%c0%c3%b0%10%94" +
+ "%4a%18%81%10%9c%5c%18%1b%18%18" +
+ "%b8%10%81%07%14%68%64%60%70%a4" +
+ "%38%00%b3%8d%80%c6%0b%33%6e%04" +
+ "%a5%4a%5c%76%25%1b%81%53%ee%24" +
+ "%58%ca%95%4c%cd%4b%2e%aa%2c%28" +
+ "%c9%cc%cf%c3%9a%78%7f%03%13%ee" +
+ "%77%a4%c4%eb%35%50%89%d7%10%35" +
+ "%f1%1a%52%39%f1%06%de%54%65%71" +
+ "%10%e3%2a%fe%5e%aa%7a%9e%77%f3" +
+ "%fe%e6%0d%ed%02%0d%37%0e%33%71" +
+ "%2c%58%65%c4%2f%b9%53%6c%5d%f7" +
+ "%c4%53%07%d7%eb%5d%79%df%d8%fc" +
+ "%43%c3%c0%6b%f3%89%ef%47%96%3e" +
+ "%72%7e%9b%fc%f6%4c%83%77%bf%ce" +
+ "%5d%7b%35%cc%c4%cb%aa%40%74%e2" +
+ "%fd%7d%75%09%57%fb%01%4f%cd%ab" +
+ "%4b%b3%58%5b%f7%9f%bf%a7%be%4a" +
+ "%2c%85%82%c4%eb%ce%60%e0%c2%a4" +
+ "%10%1f%7c%75%eb%26%9f%83%2d%8f" +
+ "%f5%3a%76%b5%f2%d4%cf%3b%de%b7" +
+ "%bb%e9%56%8a%ef%f4%af%3c%31%3c" +
+ "%76%77%b9%1a%98%14%32%3e%09%cd" +
+ "%fc%c8%f9%f3%c9%b2%45%21%f3%b6" +
+ "%2c%56%0c%39%fb%2d%e5%7f%da%de" +
+ "%fd%ce%33%17%d4%c8%af%15%c8%dd" +
+ "%99%6d%0a%4a%2a%01%8b%88%49%bb" +
+ "%94%86%5f%b6%09%d0%78%81%85%9b" +
+ "%f0%a6%5d%63%70%da%9d%0c%4b%bb" +
+ "%32%38%d3%ae%02%58%29%96%b2%d7" +
+ "%84%be%c9%d7%d8%d0%c8%c8%00%98" +
+ "%50%4d%8c%c1%65%af%85%a1%11%28" +
+ "%09%83%b9%d4%4d%be%49%31%e1%27" +
+ "%cf%4e%93%9b%7a%35%6d%1b%db%e1" +
+ "%10%3b%ee%c5%1e%b6%1f%23%ee%7c" +
+ "%9c%b7%6e%ee%aa%57%a2%7f%95%fb" +
+ "%fd%3a%3b%ab%de%46%cb%ff%62%9e" +
+ "%ac%90%66%b3%f0%58%b3%dd%ed%38" +
+ "%e1%16%9f%a4%56%8d%fb%6b%db%96" +
+ "%ba%ef%aa%a4%28%f9%66%b5%2f%9d" +
+ "%36%cd%7b%52%6b%4b%68%e5%8d%57" +
+ "%92%92%5f%78%36%7e%31%a4%b4%ec" +
+ "%55%a8%95%da%7c%76%42%8a%19%a3" +
+ "%d9%f1%03%27%af%cb%14%fb%3b%44" +
+ "%cf%dc%b1%fc%a1%dc%8f%95%31%b9" +
+ "%5f%ff%2e%aa%b8%00%2c%9d%f7%b9" +
+ "%1e%bd%c5%2e%78%b4%48%4e%aa%7b" +
+ "%92%e1%16%5d%af%cd%1f%94%93%96" +
+ "%3b%27%c5%ed%ab%f6%0c%dd%cb%73" +
+ "%fd%7a%b6%39%38%fd%2e%26%26%fd" +
+ "%52%1a%80%d9%66%e0%f4%bb%19%5f" +
+ "%fa%05%00%21%15%7f%b0";
+
+ System.out.println("Test PKCS11 Blob data: " + compressedTokenData);
+ System.out.println("Test Data: Len: " + compressedTokenData.length());
+
+ // Test getting integer values from a TPSBuffer
+
+ byte[] value = { (byte) 99, (byte) 49, (byte) 0, (byte) 0 };
+
+ TPSBuffer valBuf = new TPSBuffer(value);
+
+ long l1 = valBuf.getLongFrom4Bytes(0);
+
+ int i1 = valBuf.getIntFrom2Bytes(0);
+
+ int i2 = valBuf.getIntFrom1Byte(0);
+
+ System.out.println("4 bytes long: " + l1 + " 2 bytes int: " + i1 + " 1 byte int: " + i2);
+
+ // Now test the parsing and un-parsing of the data, the result at the end should be
+ // the same as the original data.
+ // The data above is an exact copy of a blob taken off of a real token in the
+ // old TPS.
+
+ byte[] decoded = Util.uriDecodeFromHex(compressedTokenData);
+
+ System.out.println("decoded compressed datat size: " + decoded.length);
+
+ // This is buffer containing sample copressed pkcs#11 blob.
+ TPSBuffer tokenData = new TPSBuffer(decoded);
+
+ // Parse the given token data into PKCS#11 objects and attributes
+
+ PKCS11Obj object = PKCS11Obj.parse(tokenData, 0);
+
+ String certId = "C1";
+ boolean exists = object.doesCertIdExist(certId);
+
+ System.out.println("CertID " + certId + " exists: " + exists);
+
+ // This gets the compressed blob that will go out to token of the parsed data.
+ TPSBuffer implodedData = object.getCompressedData();
+
+ System.out.println("imploded token data size: " + implodedData.size());
+
+ String encodedImplodedData = implodedData.toHexString();
+
+ System.out.println("encodedImplodedData: " + encodedImplodedData);
+
+ // Now test to see if both blobs are identical
+
+ boolean identical = implodedData.equals(tokenData);
+
+ System.out.println("Before and after comparison result: Are the blobs identical?: " + identical);
+
+ }
+
+ public int getOldFormatVersion() {
+ return oldFormatVersion;
+ }
+
+ public void setOldFormatVersion(int oldFormatVersion) {
+ this.oldFormatVersion = oldFormatVersion;
+ }
+
+ public int getOldObjectVersion() {
+ return oldObjectVersion;
+ }
+
+ public void setOldObjectVersion(int oldObjectVersion) {
+ this.oldObjectVersion = oldObjectVersion;
+ }
+
+ public int getNextFreeCertIdNumber() {
+
+ int highest_cert_id = 0;
+
+ int numObjs = getObjectSpecCount();
+
+ for (int i = 0; i < numObjs; i++) {
+ ObjectSpec os = getObjectSpec(i);
+ if (os == null)
+ continue;
+
+ long objid = os.getObjectID();
+
+ char[] b1 = new char[2];
+
+ b1[0] = (char) ((objid >> 24) & 0xff);
+ b1[1] = (char) ((objid >> 16) & 0xff);
+
+ if (b1[0] == 'C') { //found a certificate
+
+ int id_int = b1[1] - '0';
+
+ if (id_int > highest_cert_id) {
+ highest_cert_id = id_int;
+ }
+ }
+
+ }
+
+ highest_cert_id++;
+ CMS.debug("TPSEnrollProcessor.getNextFreeCertIdNumber: returning: " + highest_cert_id);
+
+ return highest_cert_id;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/AppletInfo.java b/base/tps/src/org/dogtagpki/server/tps/processor/AppletInfo.java
new file mode 100644
index 000000000..bc46eaba8
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/AppletInfo.java
@@ -0,0 +1,115 @@
+package org.dogtagpki.server.tps.processor;
+
+import org.dogtagpki.tps.main.TPSBuffer;
+
+
+public class AppletInfo {
+
+ private byte majorVersion;
+ private byte minorVersion;
+ private byte appMajorVersion;
+ private byte appMinorVersion;
+
+ private TPSBuffer aid;
+ private TPSBuffer cuid;
+ private TPSBuffer msn;
+ private int totalMem;
+ private int freeMem;
+
+ public AppletInfo(byte appletMajorVer,byte appletMinorVer,byte appMajorVer,byte appMinorVer) {
+
+ majorVersion = appletMajorVer;
+ minorVersion = appletMinorVer;
+ appMajorVersion = appMajorVer;
+ appMinorVersion = appMinorVer;
+
+ }
+
+ public void setCUID(TPSBuffer theCuid) {
+ cuid = new TPSBuffer(theCuid);
+ }
+
+ public TPSBuffer getCUID() {
+ return cuid;
+ }
+
+ public void setMSN(TPSBuffer theMsn) {
+ msn = new TPSBuffer(theMsn);
+ }
+
+ public TPSBuffer getMSN() {
+ return msn;
+ }
+
+ public String getCUIDhexString(){
+ if(cuid != null) {
+ return cuid.toHexString();
+ }
+
+ return null;
+ }
+
+ /*
+ * getCUIDhexString2 returns hex string without the '%'
+ */
+ public String getCUIDhexStringPlain() {
+ if(cuid != null) {
+ return cuid.toHexStringPlain();
+ }
+
+ return null;
+ }
+
+ public String getMSNString() {
+ if(msn != null) {
+ return msn.toHexString();
+ }
+ return null;
+ }
+
+ public byte getMajorVersion() {
+ return majorVersion;
+ }
+
+ public byte getMinorVersion() {
+ return minorVersion;
+ }
+
+ public byte getAppMinorVersion() {
+ return appMinorVersion;
+ }
+
+ public byte getAppMajorVersion() {
+ return appMajorVersion;
+ }
+
+ public static void main(String[] args) {
+
+ }
+
+ public void setTotalMem(int total_mem) {
+ totalMem = total_mem;
+
+ }
+
+ public int getTotalMem() {
+ return totalMem;
+ }
+
+ public void setFreeMem(int free_mem) {
+ freeMem = free_mem;
+ }
+
+ public int getFreeMem() {
+ return freeMem;
+ }
+
+ public TPSBuffer getAid() {
+ return aid;
+ }
+
+ public void setAid(TPSBuffer aid) {
+ this.aid = aid;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java b/base/tps/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java
new file mode 100644
index 000000000..9dfb3f114
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java
@@ -0,0 +1,270 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.processor;
+
+import org.dogtagpki.server.tps.channel.SecureChannel.TokenKeyType;
+import org.dogtagpki.server.tps.cms.CARenewCertResponse;
+import org.dogtagpki.server.tps.cms.CARetrieveCertResponse;
+import org.dogtagpki.server.tps.cms.KRARecoverKeyResponse;
+import org.dogtagpki.server.tps.dbs.TokenRecord;
+import org.dogtagpki.server.tps.engine.TPSEngine;
+
+public class CertEnrollInfo {
+
+ private TokenKeyType keyTypeEnum;
+ private String profileId;
+ private String certId;
+ private String certAttrId;
+ private String privateKeyAttrId;
+ private String publicKeyAttrId;
+ private String publisherId;
+ private String keyType;
+ private String keyTypePrefix;
+
+ private CARetrieveCertResponse recoveredCertData;
+ private KRARecoverKeyResponse recoveredKeyData;
+ private TokenRecord toBeRecoveredRecord;
+
+ private CARenewCertResponse renewedCertData;
+
+ private int keySize;
+ private int algorithm;
+ private int keyUsage;
+ private int keyUser;
+ private int privateKeyNumber;
+ private int publicKeyNumber;
+ private int startProgress;
+ private int endProgress;
+
+ private TPSEngine.ENROLL_MODES enrollmentMode = TPSEngine.ENROLL_MODES.MODE_ENROLL;
+
+ public void setEnrollmentMode(TPSEngine.ENROLL_MODES mode) {
+ enrollmentMode = mode;
+ }
+
+ public TPSEngine.ENROLL_MODES getEnrollmentMode() {
+ return enrollmentMode;
+ }
+
+ public void setRecoveredCertData(CARetrieveCertResponse cData) {
+ recoveredCertData = cData;
+ }
+
+ public CARetrieveCertResponse getRecoveredCertData() {
+ return recoveredCertData;
+ }
+
+ public void setRecoveredKeyData(KRARecoverKeyResponse kData) {
+ recoveredKeyData = kData;
+ }
+
+ public KRARecoverKeyResponse getRecoveredKeyData() {
+ return recoveredKeyData;
+ }
+
+
+ public void setStartProgressValue(int progress) {
+ startProgress = progress;
+ }
+
+ public int getStartProgressValue() {
+ return startProgress;
+ }
+
+ public void setEndProgressValue(int progress) {
+ endProgress = progress;
+ }
+
+ public int getEndProgressValue() {
+ return endProgress;
+ }
+
+ public void setKeyTypeEnum(TokenKeyType keyTypeEnum) {
+ this.keyTypeEnum = keyTypeEnum;
+ }
+
+ public TokenKeyType getKeyTypeEnum() {
+ return keyTypeEnum;
+ }
+
+ public void setProfileId(String profileId) {
+ this.profileId = profileId;
+ }
+
+ public String getProfileId() {
+ return profileId;
+ }
+
+ public void setCertId(String certId) {
+ this.certId = certId;
+ }
+
+ public String getCertId() {
+ return certId;
+ }
+
+ public void setCertAttrId(String certAttrId) {
+ this.certAttrId = certAttrId;
+ }
+
+ public String getCertAttrId() {
+ return certAttrId;
+ }
+
+ public void setPrivateKeyAttrId(String priKeyAttrId) {
+ privateKeyAttrId = priKeyAttrId;
+ }
+
+ public String getPrivateKeyAttrId() {
+ return privateKeyAttrId;
+ }
+
+ public void setPublicKeyAttrId(String publicKeyAttrId) {
+ this.publicKeyAttrId = publicKeyAttrId;
+ }
+
+ public String getPublicKeyAttrId() {
+ return publicKeyAttrId;
+ }
+
+ public void setKeySize(int keySize) {
+ this.keySize = keySize;
+ }
+
+ public int getKeySize() {
+ return keySize;
+ }
+
+ public void setPublisherId(String publisherId) {
+ this.publisherId = publisherId;
+ }
+
+ public String getPublisherId() {
+ return publisherId;
+ }
+
+ public void setAlgorithm(int algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public int getAlgorithm() {
+ return algorithm;
+ }
+
+ public void setKeyUsage(int keyUsage) {
+ this.keyUsage = keyUsage;
+ }
+
+ public int getKeyUsage() {
+ return keyUsage;
+ }
+
+ public void setKeyUser(int keyUser) {
+ this.keyUser = keyUser;
+ }
+
+ public int getKeyUser() {
+ return keyUser;
+ }
+
+ public void setPrivateKeyNumber(int priKeyNumber) {
+ privateKeyNumber = priKeyNumber;
+ }
+
+ public int getPrivateKeyNumber() {
+ return privateKeyNumber;
+ }
+
+ public void setPublicKeyNumber(int pubKeyNumber) {
+ publicKeyNumber = pubKeyNumber;
+ }
+
+ public int getPublicKeyNumber() {
+ return publicKeyNumber;
+ }
+
+ public void setKeyType(String keyType) {
+ this.keyType = keyType;
+ }
+
+ public String getKeyType() {
+ return keyType;
+ }
+
+ public void setKeyTypePrefix(String keyTypePrefix) {
+ this.keyTypePrefix = keyTypePrefix;
+ }
+
+ public String getKeyTypePrefix() {
+ return keyTypePrefix;
+ }
+
+ public boolean getIsRecoveryMode() {
+ if (enrollmentMode == TPSEngine.ENROLL_MODES.MODE_RECOVERY) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean getIsRenewalMode() {
+ if (enrollmentMode == TPSEngine.ENROLL_MODES.MODE_RENEWAL) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean getIsEnrollmentMode() {
+ if (enrollmentMode == TPSEngine.ENROLL_MODES.MODE_ENROLL) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void setTokenToBeRecovered(TokenRecord toBeRecovered) {
+ toBeRecoveredRecord = toBeRecovered;
+
+ }
+
+ public TokenRecord getTokenToBeRecovered() {
+ return toBeRecoveredRecord;
+ }
+
+ public void setRenewedCertData(CARenewCertResponse certResponse) {
+ renewedCertData = certResponse;
+ }
+
+ public CARenewCertResponse getRenewedCertData() {
+ return renewedCertData;
+ }
+
+ public int getCertIdIndex() {
+ int result = 0;
+
+ if(certId != null && certId.length() == 2) {
+ result = certId.charAt(1) - '0';
+ }
+
+ return result;
+ }
+
+
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/EnrolledCertsInfo.java b/base/tps/src/org/dogtagpki/server/tps/processor/EnrolledCertsInfo.java
new file mode 100644
index 000000000..87b86f7d7
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/EnrolledCertsInfo.java
@@ -0,0 +1,262 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.processor;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+
+import netscape.security.x509.X509CertImpl;
+
+import org.dogtagpki.server.tps.dbs.TPSCertRecord;
+import org.dogtagpki.server.tps.main.PKCS11Obj;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.Util;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+
+public class EnrolledCertsInfo {
+
+ EnrolledCertsInfo() {
+ certificates = new ArrayList<X509CertImpl>();
+ ktypes = new ArrayList<String>();
+ origins = new ArrayList<String>();
+ tokenTypes = new ArrayList<String>();
+ }
+
+ EnrolledCertsInfo(PKCS11Obj obj, TPSBuffer wrappedChallenge, TPSBuffer plainChallenge, int keyTypeNum,
+ int startProgress, int endProgress) {
+ this();
+ this.wrappedChallenge = wrappedChallenge;
+ plaintextChallenge = plainChallenge;
+ pkcs11objx = obj;
+ numCertsToEnroll = keyTypeNum;
+ this.startProgress = startProgress;
+ this.endProgress = endProgress;
+ }
+
+ //Tables that will get set during processing
+ private ArrayList<String> origins;
+ private ArrayList<String> ktypes;
+ private ArrayList<String> tokenTypes;
+ private ArrayList<X509CertImpl> certificates;
+
+ //Input challenge data
+ private TPSBuffer wrappedChallenge;
+ private TPSBuffer plaintextChallenge;
+ private TPSBuffer keyCheck;
+
+ private int numCertsToEnroll;
+ private int currentCertIndex;
+
+ private int startProgress;
+ private int endProgress;
+
+ public int getCurrentCertIndex() {
+ return currentCertIndex;
+ }
+
+ public void setCurrentCertIndex(int index) {
+ currentCertIndex = index;
+ }
+
+ public void setNumCertsToEnroll(int num) {
+ numCertsToEnroll = num;
+ }
+
+ public int getNumCertsToEnroll() {
+ return numCertsToEnroll;
+ }
+
+ int getStartProgressValue() {
+ return startProgress;
+ }
+
+ int getEndProgressValue() {
+ return endProgress;
+ }
+
+ public void setKeyCheck(TPSBuffer keyCheck) {
+ this.keyCheck = keyCheck;
+ }
+
+ public TPSBuffer getKeyCheck() {
+ return keyCheck;
+ }
+
+ //PKCS11Object that will have values added to it during processing
+ private PKCS11Obj pkcs11objx;
+
+ public void setWrappedChallenge(TPSBuffer wrappedChallenge) {
+ this.wrappedChallenge = wrappedChallenge;
+ }
+
+ public TPSBuffer getWrappedChallenge() {
+ return wrappedChallenge;
+ }
+
+ public void setPlaintextChallenge(TPSBuffer plaintextChallenge) {
+ this.plaintextChallenge = plaintextChallenge;
+ }
+
+ public TPSBuffer getPlaintextChallenge() {
+ return plaintextChallenge;
+ }
+
+ public void setPKCS11Obj(PKCS11Obj pkcs11obj) {
+ pkcs11objx = pkcs11obj;
+ }
+
+ public PKCS11Obj getPKCS11Obj() {
+ return pkcs11objx;
+ }
+
+ public void addOrigin(String origin) {
+
+ CMS.debug("EnrolledCertsInfo.addOrigin: " + origin);
+ origins.add(origin);
+ }
+
+ public void addKType(String ktype) {
+ ktypes.add(ktype);
+ }
+
+ public void addTokenType(String tokenType) {
+ tokenTypes.add(tokenType);
+ }
+
+ public void addCertificate(X509CertImpl x509Cert) {
+ certificates.add(x509Cert);
+ }
+
+ public void setStartProgress(int startP) {
+ startProgress = startP;
+
+ }
+
+ public void setEndProgress(int endP) {
+ endProgress = endP;
+
+ }
+
+ public ArrayList<TPSCertRecord> toTPSCertRecords(String cuid, String uid) {
+ ArrayList<TPSCertRecord> certs = new ArrayList<TPSCertRecord>();
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: starts");
+ int index = 0;
+ for (X509CertImpl cert: certificates) {
+ TPSCertRecord certRecord = new TPSCertRecord();
+
+ //serial number
+ BigInteger serial_BigInt = cert.getSerialNumber();
+
+ String hexSerial = serial_BigInt.toString(16);
+ String serialNumber = "0x" + hexSerial;
+ certRecord.setSerialNumber(serialNumber);
+
+ String uniqueString = Util.getTimeStampString(false);
+ String id = hexSerial + "." + uniqueString;
+
+ certRecord.setId(id);
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: converting cert:"+ certRecord.getId());
+
+ //token id
+ certRecord.setTokenID(cuid);
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: cuid =" + cuid);
+
+ //origin
+ if ((!origins.isEmpty()) && index <origins.size() && origins.get(index)!= null) {
+ certRecord.setOrigin(origins.get(index));
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: origin =" + origins.get(index));
+ } else {
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: origin not found for index:"+ index);
+ }
+
+ //user id
+ certRecord.setUserID(uid);
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: uid =" + uid);
+
+ //KeyType
+ if ((!ktypes.isEmpty()) && index <ktypes.size() && ktypes.get(index)!= null) {
+ certRecord.setKeyType(ktypes.get(index));
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: keyType =" + ktypes.get(index));
+ } else {
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: keyType not found for index:"+ index);
+ }
+
+ //token type
+ if ((!tokenTypes.isEmpty()) && index <tokenTypes.size() && tokenTypes.get(index)!= null) {
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: tokenType=" + tokenTypes.get(index));
+ certRecord.setType(tokenTypes.get(index));
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: tokenType set");
+ } else {
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: tokenType not found for index:"+ index);
+ //certRecord.setType("");
+ }
+
+ //Issuer
+ String issuedBy = cert.getIssuerDN().toString();
+ certRecord.setIssuedBy(issuedBy);
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: issuer ="+ issuedBy);
+
+ //Subject
+ String subject = cert.getSubjectDN().toString();
+ certRecord.setSubject(subject);
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: subject ="+ subject);
+
+ //NotBefore
+ certRecord.setValidNotBefore(cert.getNotBefore());
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: notBefore ="+ cert.getNotBefore().toString());
+
+ //NotAfter
+ certRecord.setValidNotAfter(cert.getNotAfter());
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: notAfter ="+ cert.getNotAfter().toString());
+
+ //status
+ certRecord.setStatus("active");
+
+ /* certificate
+ byte[] certBytes = null;
+ try {
+ certBytes = cert.getEncoded();
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: certBytes ="+ CMS.BtoA(certBytes));
+ } catch (CertificateEncodingException e) {
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecord: "+ e);
+ //TODO: throw
+
+ }
+ certRecord.setCertificate(CMS.BtoA(certBytes));
+ */
+ // Alternative to the actual certificate -- certificate AKI
+ try {
+ String aki = Util.getCertAkiString(cert);
+ certRecord.setCertificate(aki);
+ } catch (EBaseException | IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ certs.add(certRecord);
+
+ index++;
+ }
+ CMS.debug("EnrolledCertsInfo.toTPSCertRecords: ends");
+ return certs;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
new file mode 100644
index 000000000..cff615752
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java
@@ -0,0 +1,2789 @@
+package org.dogtagpki.server.tps.processor;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.zip.DataFormatException;
+
+import netscape.security.provider.RSAPublicKey;
+//import org.mozilla.jss.pkcs11.PK11ECPublicKey;
+import netscape.security.util.BigInt;
+import netscape.security.x509.X509CertImpl;
+
+import org.dogtagpki.server.tps.TPSSession;
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.TPSTokenPolicy;
+import org.dogtagpki.server.tps.authentication.TPSAuthenticator;
+import org.dogtagpki.server.tps.channel.SecureChannel;
+import org.dogtagpki.server.tps.channel.SecureChannel.TokenKeyType;
+import org.dogtagpki.server.tps.cms.CAEnrollCertResponse;
+import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
+import org.dogtagpki.server.tps.cms.CARenewCertResponse;
+import org.dogtagpki.server.tps.cms.CARetrieveCertResponse;
+import org.dogtagpki.server.tps.cms.CARevokeCertResponse;
+import org.dogtagpki.server.tps.cms.KRARecoverKeyResponse;
+import org.dogtagpki.server.tps.cms.KRAServerSideKeyGenResponse;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
+import org.dogtagpki.server.tps.dbs.TPSCertRecord;
+import org.dogtagpki.server.tps.dbs.TokenRecord;
+import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.server.tps.engine.TPSEngine.ENROLL_MODES;
+import org.dogtagpki.server.tps.main.ObjectSpec;
+import org.dogtagpki.server.tps.main.PKCS11Obj;
+import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.main.Util;
+import org.dogtagpki.tps.msg.BeginOpMsg;
+import org.dogtagpki.tps.msg.EndOpMsg;
+import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+import org.mozilla.jss.asn1.InvalidBERException;
+import org.mozilla.jss.crypto.InvalidKeyFormatException;
+import org.mozilla.jss.pkcs11.PK11PubKey;
+import org.mozilla.jss.pkcs11.PK11RSAPublicKey;
+import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.tps.token.TokenStatus;
+import com.netscape.cmsutil.util.Utils;
+
+public class TPSEnrollProcessor extends TPSProcessor {
+
+ public TPSEnrollProcessor(TPSSession session) {
+ super(session);
+ }
+
+ @Override
+ public void process(BeginOpMsg beginMsg) throws TPSException, IOException {
+ if (beginMsg == null) {
+ throw new TPSException("TPSEnrollrocessor.process: invalid input data, not beginMsg provided.",
+ TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+ }
+ setBeginMessage(beginMsg);
+ setCurrentTokenOperation("enroll");
+ checkIsExternalReg();
+
+ enroll();
+
+ }
+
+ private void enroll() throws TPSException, IOException {
+ CMS.debug("TPSEnrollProcessor enroll: entering...");
+ String auditMsg = null;
+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ TPSTokenPolicy tokenPolicy = new TPSTokenPolicy(tps);
+
+ AppletInfo appletInfo = null;
+ TokenRecord tokenRecord = null;
+ try {
+ appletInfo = getAppletInfo();
+ } catch (TPSException e) {
+ auditMsg = e.toString();
+ tps.tdb.tdbActivity(ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw e;
+ }
+ appletInfo.setAid(getCardManagerAID());
+
+ CMS.debug("TPSEnrollProcessor.enroll: token cuid: " + appletInfo.getCUIDhexStringPlain());
+ boolean isTokenPresent = false;
+
+ tokenRecord = isTokenRecordPresent(appletInfo);
+
+ if (tokenRecord != null) {
+ CMS.debug("TPSEnrollProcessor.enroll: found token...");
+ isTokenPresent = true;
+ } else {
+ CMS.debug("TPSEnrollProcessor.enroll: token does not exist in tokendb... create one in memory");
+ tokenRecord = new TokenRecord();
+ tokenRecord.setId(appletInfo.getCUIDhexStringPlain());
+ }
+
+ fillTokenRecord(tokenRecord, appletInfo);
+ session.setTokenRecord(tokenRecord);
+
+ String resolverInstName = getResolverInstanceName();
+
+ String tokenType = null;
+
+ tokenType = resolveTokenProfile(resolverInstName, appletInfo.getCUIDhexString(), appletInfo.getMSNString(),
+ appletInfo.getMajorVersion(), appletInfo.getMinorVersion());
+ CMS.debug("TPSEnrollProcessor.enroll: resolved tokenType: " + tokenType);
+
+ checkProfileStateOK();
+ String cuid = appletInfo.getCUIDhexStringPlain();
+
+ boolean do_force_format = false;
+ if (isTokenPresent) {
+ CMS.debug("TPSEnrollProcessor.enroll: token exists in tokendb");
+
+ TokenStatus newState = TokenStatus.ACTIVE;
+ // Check for transition to ACTIVE status.
+
+ if (!tps.engine.isOperationTransitionAllowed(tokenRecord.getTokenStatus(), newState)) {
+ CMS.debug("TPSEnrollProcessor.enroll: token transition disallowed " +
+ tokenRecord.getTokenStatus() +
+ " to " + newState);
+ auditMsg = "Operation for CUID " + cuid +
+ " Disabled, illegal transition attempted " + tokenRecord.getTokenStatus() +
+ " to " + newState;
+ tps.tdb.tdbActivity(ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw new TPSException(auditMsg,
+ TPSStatus.STATUS_ERROR_DISABLED_TOKEN);
+ } else {
+ CMS.debug("TPSPEnrollrocessor.enroll: token transition allowed " +
+ tokenRecord.getTokenStatus() +
+ " to " + newState);
+ }
+
+ do_force_format = tokenPolicy.isForceTokenFormat(cuid);
+
+ if (!tokenPolicy.isAllowdTokenReenroll(cuid) &&
+ !tokenPolicy.isAllowdTokenRenew(cuid)) {
+ CMS.debug("TPSEnrollProcessor.enroll: token renewal or reEnroll disallowed ");
+ auditMsg = "Operation renewal or reEnroll for CUID " + cuid +
+ " Disabled";
+ tps.tdb.tdbActivity(ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw new TPSException(auditMsg,
+ TPSStatus.STATUS_ERROR_DISABLED_TOKEN);
+ }
+ } else {
+ CMS.debug("TPSEnrollProcessor.enroll: token does not exist");
+ tokenRecord.setStatus("uninitialized");
+
+ checkAllowUnknownToken(TPSEngine.OP_FORMAT_PREFIX);
+ }
+ checkAndAuthenticateUser(appletInfo, tokenType);
+
+ if (do_force_format) {
+ CMS.debug("TPSEnrollProcessor.enroll: About to force format first due to policy.");
+ //We will skip the auth step inside of format
+ format(true);
+ } else {
+ checkAndUpgradeApplet(appletInfo);
+ //Get new applet info
+ appletInfo = getAppletInfo();
+ }
+
+ CMS.debug("TPSEnrollProcessor.enroll: Finished updating applet if needed.");
+
+ //Check and upgrade keys if called for
+
+ SecureChannel channel = checkAndUpgradeSymKeys();
+ channel.externalAuthenticate();
+
+ //Reset the token's pin, create one if we don't have one already
+
+ checkAndHandlePinReset(channel);
+ tokenRecord.setKeyInfo(channel.getKeyInfoData().toHexStringPlain());
+ String tksConnId = getTKSConnectorID();
+ TPSBuffer plaintextChallenge = computeRandomData(16, tksConnId);
+
+ //These will be used shortly
+ TPSBuffer wrappedChallenge = encryptData(appletInfo, channel.getKeyInfoData(), plaintextChallenge, tksConnId);
+ PKCS11Obj pkcs11objx = null;
+
+ try {
+ pkcs11objx = getCurrentObjectsOnToken(channel);
+ } catch (DataFormatException e) {
+ auditMsg = "TPSEnrollProcessor.enroll: Failed to parse original token data: " + e.toString();
+ tps.tdb.tdbActivity(ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw new TPSException(auditMsg);
+ }
+
+ pkcs11objx.setCUID(appletInfo.getCUID());
+
+ if (!isTokenPresent) {
+ try {
+ tps.tdb.tdbAddTokenEntry(tokenRecord, "uninitialized");
+ } catch (Exception e) {
+ String failMsg = "add token failure";
+ auditMsg = failMsg + ":" + e.toString();
+ throw new TPSException(auditMsg);
+ }
+ }
+
+ statusUpdate(10, "PROGRESS_PROCESS_PROFILE");
+
+ EnrolledCertsInfo certsInfo = new EnrolledCertsInfo();
+ certsInfo.setWrappedChallenge(wrappedChallenge);
+ certsInfo.setPlaintextChallenge(plaintextChallenge);
+ certsInfo.setPKCS11Obj(pkcs11objx);
+ certsInfo.setStartProgress(15);
+ certsInfo.setEndProgress(90);
+
+ boolean renewed = false;
+ TPSStatus status = generateCertsAfterRenewalRecoveryPolicy(certsInfo, channel, appletInfo);
+ //most failed would have thrown an exception
+ String statusString = "Unknown"; // gives some meaningful debug message
+ if (status == TPSStatus.STATUS_NO_ERROR)
+ statusString = "Enrollment to follow";
+ else if (status == TPSStatus.STATUS_ERROR_RECOVERY_IS_PROCESSED)
+ statusString = "Recovery processed";
+ else if (status == TPSStatus.STATUS_ERROR_RENEWAL_IS_PROCESSED)
+ statusString = "Renewal processed";
+ else {
+ auditMsg = " generateCertsAfterRenewalRecoveryPolicy returned status=" + status;
+ CMS.debug("TPSEnrollProcessor.enroll:" + auditMsg);
+ throw new TPSException(auditMsg);
+ }
+ auditMsg = "generateCertsAfterRenewalRecoveryPolicy returns status:"
+ + EndOpMsg.statusToInt(status) + " : " + statusString;
+ CMS.debug("TPSEnrollProcessor.enroll: " + auditMsg);
+ if (status == TPSStatus.STATUS_NO_ERROR) {
+ if (!generateCertificates(certsInfo, channel, appletInfo)) {
+ CMS.debug("TPSEnrollProcessor.enroll:generateCertificates returned false means some certs failed enrollment; clean up (format) the token");
+ format(true /*skipAuth*/);
+ throw new TPSException("generateCertificates failed");
+ } else {
+ CMS.debug("TPSEnrollProcessor.enroll:generateCertificates returned true means cert enrollment successful");
+ }
+ }
+ // at this point, enrollment, renewal, or recovery have been processed accordingly;
+ if (status == TPSStatus.STATUS_ERROR_RENEWAL_IS_PROCESSED &&
+ tokenPolicy.isAllowdTokenRenew(cuid)) {
+ renewed = true;
+ CMS.debug("TPSEnrollProcessor.enroll: renewal happened.. ");
+ }
+ /*
+ * TODO:
+ * find the point to do the following...
+ * when total available memory is exceeded on the token ...
+ * if(!renewed) //Renewal should leave what they have on the token.
+ * format(true);
+ */
+ String tokenLabel = buildTokenLabel(certsInfo, appletInfo);
+
+ pkcs11objx.setTokenName(new TPSBuffer(tokenLabel.getBytes()));
+
+ int lastObjVer = pkcs11objx.getOldObjectVersion();
+
+ CMS.debug("TPSEnrollProcessor.enroll: getOldObjectVersion: returning: " + lastObjVer);
+
+ if (lastObjVer != 0) {
+ while (lastObjVer == 0xff) {
+ Random randomGenerator = new Random();
+ lastObjVer = randomGenerator.nextInt(1000);
+ }
+
+ lastObjVer = lastObjVer + 1;
+ CMS.debug("TPSEnrollProcessor.enroll: Setting objectVersion to: " + lastObjVer);
+ pkcs11objx.setObjectVersion(lastObjVer);
+
+ }
+
+ pkcs11objx.setFormatVersion(pkcs11objx.getOldFormatVersion());
+
+ // Make sure we have a good secure channel before writing out the final objects
+ channel = setupSecureChannel();
+
+ statusUpdate(92, "PROGRESS_WRITE_OBJECTS");
+
+ writeFinalPKCS11ObjectToToken(pkcs11objx, appletInfo, channel);
+ statusUpdate(98, "PROGRESS_ISSUER_INFO");
+ writeIssuerInfoToToken(channel);
+
+ statusUpdate(99, "PROGRESS_SET_LIFECYCLE");
+ channel.setLifeycleState((byte) 0x0f);
+
+ try {
+ tokenRecord.setStatus("active");
+ tps.tdb.tdbUpdateTokenEntry(tokenRecord);
+ } catch (Exception e) {
+ String failMsg = "update token failure";
+ auditMsg = failMsg + ":" + e.toString();
+ tps.tdb.tdbActivity(ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), failMsg,
+ "failure");
+ throw new TPSException(auditMsg);
+ }
+ //update the tokendb with new certs
+ CMS.debug("TPSEnrollProcessor.enroll: updating tokendb with certs.");
+ ArrayList<TPSCertRecord> certRecords = certsInfo.toTPSCertRecords(tokenRecord.getId(), tokenRecord.getUserID());
+ tps.tdb.tdbAddCertificatesForCUID(tokenRecord.getId(), certRecords);
+
+ auditMsg = "appletVersion=" + lastObjVer + "; tokenType =" + selectedTokenType + "; userid =" + userid;
+ if (renewed) {
+ tps.tdb.tdbActivity(ActivityDatabase.OP_RENEWAL, tokenRecord, session.getIpAddress(), auditMsg, "success");
+ } else {
+ tps.tdb.tdbActivity(ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), auditMsg,
+ "success");
+ }
+
+ CMS.debug("TPSEnrollProcessor.enroll: leaving ...");
+
+ statusUpdate(100, "PROGRESS_DONE_ENROLLMENT");
+ }
+
+ private void writeFinalPKCS11ObjectToToken(PKCS11Obj pkcs11objx, AppletInfo ainfo, SecureChannel channel)
+ throws TPSException, IOException {
+ if (pkcs11objx == null || ainfo == null || channel == null) {
+ throw new TPSException("TPSErollProcessor.writeFinalPKCS11ObjectToToken: invalid input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("TPSEnrollProcessor.writeFinalPKCS11ObjectToToken: entering...");
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String compressConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+ + "pkcs11obj.compress.enable";
+
+ CMS.debug("TPSEnrollProcessor.writeFinalPKCS11ObjectToToken: config to check: " + compressConfig);
+
+ boolean doCompress = false;
+
+ try {
+ doCompress = configStore.getBoolean(compressConfig, true);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.writeFinalPKCS11ObjectToToken: internal error obtaining config value " + e);
+ }
+
+ CMS.debug("TPSEnrollProcessor.writeFinalPKCS11ObjectToToken: doCompress: " + doCompress);
+
+ TPSBuffer tokenData = null;
+
+ if (doCompress) {
+ tokenData = pkcs11objx.getCompressedData();
+
+ } else {
+ tokenData = pkcs11objx.getData();
+ }
+
+ if (tokenData.size() > ainfo.getTotalMem()) {
+
+ throw new TPSException(
+ "TPSEnrollProcessor.writeFinalPKCS11ObjectToToken: NOt enough memory to write certificates!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+ }
+
+ byte[] zobjectid = { (byte) 'z', (byte) '0', 0, 0 };
+ byte[] perms = { (byte) 0xff, (byte) 0xff, 0x40, 0x00, 0x40, 0x00 };
+ TPSBuffer zobjidBuf = new TPSBuffer(zobjectid);
+
+ channel.createObject(zobjidBuf, new TPSBuffer(perms), tokenData.size());
+
+ channel.writeObject(zobjidBuf, tokenData);
+
+ CMS.debug("TPSEnrollProcessor.writeFinalPKCS11ObjectToToken: leaving successfully ...");
+
+ }
+
+ private void checkAndAuthenticateUser(AppletInfo appletInfo, String tokenType) throws TPSException {
+ IAuthCredentials userCred;
+ IAuthToken authToken;
+ TokenRecord tokenRecord = getTokenRecord();
+ if (!isExternalReg) {
+ // authenticate per profile/tokenType configuration
+ String configName = TPSEngine.OP_ENROLL_PREFIX + "." + tokenType + ".auth.enable";
+ IConfigStore configStore = CMS.getConfigStore();
+
+ TPSSubsystem tps =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ //TPSSession session = getSession();
+ boolean isAuthRequired;
+ try {
+ CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: getting config: " + configName);
+ isAuthRequired = configStore.getBoolean(configName, true);
+ } catch (EBaseException e) {
+ CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: Internal Error obtaining mandatory config values. Error: "
+ + e);
+ throw new TPSException("TPS error getting config values from config store.",
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+ if (isAuthRequired) {
+ try {
+ TPSAuthenticator userAuth =
+ getAuthentication(TPSEngine.OP_ENROLL_PREFIX, tokenType);
+ userCred = requestUserId(TPSEngine.ENROLL_OP, appletInfo.getCUIDhexString(), userAuth,
+ beginMsg.getExtensions());
+ userid = (String) userCred.get(userAuth.getAuthCredName());
+ CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: userCred (attempted) userid=" + userid);
+ // initialize userid first for logging purposes in case authentication fails
+ tokenRecord.setUserID(userid);
+ authToken = authenticateUser(TPSEngine.ENROLL_OP, userAuth, userCred);
+ userid = authToken.getInString("userid");
+ tokenRecord.setUserID(userid);
+ CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser: auth passed: userid: "
+ + authToken.get("userid"));
+
+ } catch (Exception e) {
+ // all exceptions are considered login failure
+ CMS.debug("TPSEnrollProcessor.checkAndAuthenticateUser:: authentication exception thrown: " + e);
+ String msg = "TPS error user authentication failed:" + e;
+ tps.tdb.tdbActivity(ActivityDatabase.OP_ENROLLMENT, tokenRecord, session.getIpAddress(), msg,
+ "failure");
+
+ throw new TPSException(msg,
+ TPSStatus.STATUS_ERROR_LOGIN);
+ }
+ } else {
+ throw new TPSException(
+ "TPSEnrollProcessor.checkAndAuthenticateUser: TPS enrollment must have authentication enabled.",
+ TPSStatus.STATUS_ERROR_LOGIN);
+
+ }
+
+ }
+ }
+
+ private void checkAndHandlePinReset(SecureChannel channel) throws TPSException, IOException {
+
+ CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset entering...");
+
+ if (channel == null) {
+ throw new TPSException("TPSEnrollProcessor.checkAndHandlePinReset: invalid input data!",
+ TPSStatus.STATUS_ERROR_TOKEN_RESET_PIN_FAILED);
+ }
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String pinResetEnableConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_PIN_RESET_ENABLE;
+
+ CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + pinResetEnableConfig);
+
+ String minLenConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_PIN_RESET_MIN_LEN;
+
+ CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + minLenConfig);
+
+ String maxLenConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_PIN_RESET_MAX_LEN;
+
+ CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + maxLenConfig);
+
+ String maxRetriesConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_PIN_RESET_MAX_RETRIES;
+
+ CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + maxRetriesConfig);
+
+ String pinStringConfig = TPSEngine.CFG_PIN_RESET_STRING;
+
+ CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset config to check: " + pinStringConfig);
+
+ boolean enabled = false;
+ int minLen;
+ int maxLen;
+ int maxRetries;
+ String stringName;
+
+ try {
+
+ enabled = configStore.getBoolean(pinResetEnableConfig, true);
+
+ if (enabled == false) {
+ CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset: Pin Reset not allowed by configuration, exiting...");
+ return;
+
+ }
+
+ minLen = configStore.getInteger(minLenConfig, 4);
+ maxLen = configStore.getInteger(maxLenConfig, 10);
+ maxRetries = configStore.getInteger(maxRetriesConfig, 0x7f);
+ stringName = configStore.getString(pinStringConfig, "password");
+
+ CMS.debug("TPSEnrollProcessor.checkAndHandlePinReset: config vals: enabled: " + enabled + " minLen: "
+ + minLen + " maxLen: " + maxLen);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.checkAndHandlePinReset: internal error in getting value from config.");
+ }
+
+ String new_pin = requestNewPin(minLen, maxLen);
+
+ channel.createPin(0x0, maxRetries, stringName);
+
+ channel.resetPin(0x0, new_pin);
+
+ }
+
+ private void checkAndUpgradeApplet(AppletInfo appletInfo) throws TPSException, IOException {
+ // TODO Auto-generated method stub
+
+ CMS.debug("checkAndUpgradeApplet: entering..");
+
+ SecurityLevel securityLevel = SecurityLevel.SECURE_MSG_MAC;
+
+ boolean useEncryption = checkUpdateAppletEncryption();
+
+ String tksConnId = getTKSConnectorID();
+ if (useEncryption)
+ securityLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
+
+ if (checkForAppletUpdateEnabled()) {
+
+ String targetAppletVersion = checkForAppletUpgrade("op." + currentTokenOperation);
+ targetAppletVersion = targetAppletVersion.toLowerCase();
+
+ String currentAppletVersion = formatCurrentAppletVersion(appletInfo);
+
+ CMS.debug("TPSEnrollProcessor.checkAndUpgradeApplet: currentAppletVersion: " + currentAppletVersion
+ + " targetAppletVersion: " + targetAppletVersion);
+
+ if (targetAppletVersion.compareTo(currentAppletVersion) != 0) {
+
+ CMS.debug("TPSEnrollProessor.checkAndUpgradeApplet: Upgrading applet to : " + targetAppletVersion);
+ upgradeApplet("op." + currentTokenOperation, targetAppletVersion, securityLevel, getBeginMessage()
+ .getExtensions(),
+ tksConnId, 5, 12);
+ } else {
+ CMS.debug("TPSEnrollProcessor.checkAndUpgradeApplet: applet already at correct version.");
+ }
+ }
+
+ }
+
+ protected boolean checkUpdateAppletEncryption() throws TPSException {
+
+ CMS.debug("TPSEnrollProcessor.checkUpdateAppletEncryption entering...");
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String appletEncryptionConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_UPDATE_APPLET_ENCRYPTION;
+
+ CMS.debug("TPSEnrollProcessor.checkUpdateAppletEncryption config to check: " + appletEncryptionConfig);
+
+ boolean appletEncryption = false;
+
+ try {
+ appletEncryption = configStore.getBoolean(appletEncryptionConfig, false);
+ } catch (EBaseException e) {
+ //Default TPSException will return a "contact admin" error code.
+ throw new TPSException(
+ "TPSEnrollProcessor.checkUpdateAppletEncryption: internal error in getting value from config.");
+ }
+
+ CMS.debug("TPSEnrollProcessor.checkUpdateAppletEncryption returning: " + appletEncryption);
+ return appletEncryption;
+
+ }
+
+ private PKCS11Obj getCurrentObjectsOnToken(SecureChannel channel) throws TPSException, IOException,
+ DataFormatException {
+
+ byte seq = 0;
+
+ TPSBuffer objects = null;
+
+ int lastFormatVersion = 0x0100;
+ int lastObjectVersion;
+ Random randomGenerator = new Random();
+
+ lastObjectVersion = randomGenerator.nextInt(1000);
+
+ CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: Random lastObjectVersion: " + lastObjectVersion);
+
+ PKCS11Obj pkcs11objx = new PKCS11Obj();
+ pkcs11objx.setOldFormatVersion(lastFormatVersion);
+ pkcs11objx.setOldObjectVersion(lastObjectVersion);
+
+ do {
+
+ objects = listObjects(seq);
+
+ if (objects != null) {
+ CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: objects: " + objects.toHexString());
+ }
+
+ if (objects == null) {
+ pkcs11objx.setOldObjectVersion(lastObjectVersion);
+ seq = 0;
+ } else {
+ seq = 1; // get next entry
+
+ TPSBuffer objectID = objects.substr(0, 4);
+ TPSBuffer objectLen = objects.substr(4, 4);
+
+ long objectIDVal = objectID.getLongFrom4Bytes(0);
+
+ long objectLenVal = objectLen.getLongFrom4Bytes(0);
+
+ TPSBuffer obj = channel.readObject(objectID, 0, (int) objectLenVal);
+
+ if (obj != null) {
+ CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: obj: " + obj.toHexString());
+ }
+
+ if ((char) objectID.at(0) == (byte) 'z' && objectID.at(1) == (byte) '0') {
+ lastFormatVersion = obj.getIntFrom2Bytes(0);
+ lastObjectVersion = obj.getIntFrom2Bytes(2);
+
+ CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: Versions read from token: lastFormatVersion : "
+ + lastFormatVersion
+ + " lastObjectVersion: " + lastObjectVersion);
+
+ pkcs11objx = PKCS11Obj.parse(obj, 0);
+
+ pkcs11objx.setOldFormatVersion(lastFormatVersion);
+ pkcs11objx.setOldObjectVersion(lastObjectVersion);
+ seq = 0;
+
+ } else {
+ ObjectSpec objSpec = ObjectSpec.parseFromTokenData(objectIDVal, obj);
+ pkcs11objx.addObjectSpec(objSpec);
+ }
+
+ CMS.debug("TPSEnrollProcessor.getCurrentObjectsOnToken. just read object from token: "
+ + obj.toHexString());
+ }
+
+ } while (seq != 0);
+
+ return pkcs11objx;
+ }
+
+ /*
+ * generateCertsAfterRenewalRecoveryPolicy determines whether a renewal or recovery is needed;
+ * if recovery is needed, it determines which certificates (from which old token)
+ * to recover onto the new token.
+ *
+ * Note: renewal and recovery are invoked in this method; However, if a new enrollment is determined
+ * to be the proper course of action, it is done after this method.
+ */
+ private TPSStatus generateCertsAfterRenewalRecoveryPolicy(EnrolledCertsInfo certsInfo, SecureChannel channel,
+ AppletInfo aInfo)
+ throws TPSException, IOException {
+ TPSStatus status = TPSStatus.STATUS_NO_ERROR;
+ String auditMsg;
+ final String method = "TPSEnrollProcessor.generateCertsAfterRenewalRecoveryPolicy";
+ CMS.debug(method + ": begins");
+ TPSSubsystem tps =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ TPSTokenPolicy tokenPolicy = new TPSTokenPolicy(tps);
+
+ ArrayList<TokenRecord> tokenRecords = null;
+ try {
+ tokenRecords = tps.tdb.tdbFindTokenRecordsByUID(userid);
+ } catch (Exception e) {
+ // no existing record, means no "renewal" or "recovery" actions needed
+ auditMsg = "no token associated with user: " + userid;
+ CMS.debug(method + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_INACTIVE_TOKEN_NOT_FOUND);
+ }
+ CMS.debug(method + " found " + tokenRecords.size() + " tokens for user:" + userid);
+ boolean isRecover = false;
+
+ TokenRecord lostToken = null;
+ for (TokenRecord tokenRecord : tokenRecords) {
+ CMS.debug(method + " token id:"
+ + tokenRecord.getId() + "; status="
+ + tokenRecord.getStatus());
+
+ //Is this the same token (current token)?
+ if (tokenRecord.getId().equals(aInfo.getCUIDhexStringPlain())) {
+ //same token
+ auditMsg = "found current token entry";
+ CMS.debug(method + ":" + auditMsg);
+ if (tokenRecord.getStatus().equals("uninitialized")) {
+ // this is the current token
+ if (tokenRecords.size() == 1) {
+ // the current token is the only token owned by the user
+ CMS.debug(method + ": need to do enrollment");
+ // need to do enrollment outside
+ break;
+ } else {
+ CMS.debug(method + ": There are multiple token entries for user "
+ + userid);
+ try {
+ // this is assuming that the user can only have one single active token
+ // TODO: for future, maybe should allow multiple active tokens
+ tps.tdb.tdbHasActiveToken(userid);
+
+ } catch (Exception e1) {
+ /*
+ * user has no active token, need to find a token to recover from
+ * there are no other active tokens for this user
+ */
+ isRecover = true;
+ continue; // TODO: or break?
+ }
+ auditMsg = method + ": user already has an active token";
+ CMS.debug(auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_HAS_AT_LEAST_ONE_ACTIVE_TOKEN);
+ }
+ } else if (tokenRecord.getStatus().equals("active")) {
+ // current token is already active; renew if allowed
+ if (tokenPolicy.isAllowdTokenRenew(aInfo.getCUIDhexStringPlain())) {
+ return processRenewal(certsInfo, channel, aInfo, tokenRecord);
+ } else {
+ auditMsg = "token is already active; can't renew because renewal is not allowed; will re-enroll if allowed";
+ CMS.debug(method + ":" + auditMsg);
+ }
+ break;
+ } else if (tokenRecord.getStatus().equals("terminated")) {
+ auditMsg = "terminated token cuid="
+ + aInfo.getCUIDhexStringPlain() + " cannot be reused";
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+ } else if (tokenRecord.getStatus().equals("lost")) {
+ String reasonStr = tokenRecord.getReason();
+ if (reasonStr.equals("keyCompromise")) {
+ auditMsg = "This token cannot be reused because it has been reported lost";
+ CMS.debug(method + ": "
+ + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_UNUSABLE_TOKEN_KEYCOMPROMISE);
+ } else if (reasonStr.equals("onHold")) {
+ try {
+ tps.tdb.tdbHasActiveToken(userid);
+ auditMsg = "user already has an active token";
+ CMS.debug(method + ": "
+ + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_HAS_AT_LEAST_ONE_ACTIVE_TOKEN);
+ } catch (Exception e2) {
+ auditMsg = "User needs to contact administrator to report lost token (it should be put on Hold).";
+ CMS.debug(method + ": "
+ + auditMsg);
+ break;
+ }
+ } else if (reasonStr.equals("destroyed")) {
+ auditMsg = "This destroyed lost case should not be executed because the token is so damaged. It should not get here";
+ CMS.debug(method + ": "
+ + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_TOKEN_DISABLED);
+ } else {
+ auditMsg = "No such lost reason: " + reasonStr + " for this cuid: "
+ + aInfo.getCUIDhexStringPlain();
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_NO_SUCH_LOST_REASON);
+ }
+
+ } else {
+ auditMsg = "No such token status for this cuid=" + aInfo.getCUIDhexStringPlain();
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_NO_SUCH_TOKEN_STATE);
+ }
+ } else { //cuid != current token
+ auditMsg = "found token entry different from current token";
+ CMS.debug(method + ":" + auditMsg);
+ if (tokenRecord.getStatus().equals("lost")) {
+ //lostostToken keeps track of the latest token that's lost
+ //last one in the look should be the latest
+ lostToken = tokenRecord;
+ auditMsg = "found a lost token: cuid = " + tokenRecord.getId();
+ CMS.debug(method + ":" + auditMsg);
+ }
+ continue;
+ }
+ }
+
+ if (isRecover == true) { // this could be set in previous iteration
+ if (lostToken == null) {
+ auditMsg = "No lost token to be recovered; do enrollment";
+ CMS.debug(method + ":" + auditMsg);
+ //shouldn't even get here; But if we do, just enroll
+ } else {
+ String reasonStr = lostToken.getReason();
+ //RevocationReason reason = RevocationReason.valueOf(reasonStr);
+ auditMsg = "isRecover true; reasonStr =" + reasonStr;
+ CMS.debug(method + ":" + auditMsg);
+
+ if (reasonStr.equals("keyCompromise")) {
+ return processRecovery(lostToken, certsInfo, channel, aInfo);
+ } else if (reasonStr.equals("onHold")) {
+ /*
+ * the inactive one becomes the temp token
+ * No recovery scheme, basically we are going to
+ * do the brand new enrollment
+ *
+ *
+ */
+
+ // ToDo: This section has not been tested to work.. Make sure this works.
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String configName = TPSEngine.OP_ENROLL_PREFIX + "." + getSelectedTokenType()
+ + ".temporaryToken.tokenType";
+ try {
+ String tmpTokenType = configStore.getString(configName);
+ setSelectedTokenType(tmpTokenType);
+ } catch (EPropertyNotFound e) {
+ auditMsg = " configuration " + configName + " not found";
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(method + ":" + auditMsg);
+ } catch (EBaseException e) {
+ auditMsg = " configuration " + configName + " not found";
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(method + ":" + auditMsg);
+ }
+ return processRecovery(lostToken, certsInfo, channel, aInfo);
+
+ } else if (reasonStr.equals("destroyed")) {
+ return processRecovery(lostToken, certsInfo, channel, aInfo);
+ } else {
+ auditMsg = "No such lost reason: " + reasonStr + " for this cuid: " + aInfo.getCUIDhexStringPlain();
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_NO_SUCH_LOST_REASON);
+ }
+ }
+ }
+
+ CMS.debug(method + ": ends");
+ return status;
+ }
+
+ /*
+ * Renewal logic
+ * 1. Create Optional local TPS grace period per token profile,
+ * per token type, such as signing or encryption.
+ * This grace period must match how the CA is configured. Ex:
+ * op.enroll.userKey.renewal.encryption.enable=true
+ * op.enroll.userKey.renewal.encryption.gracePeriod.enable=true
+ * op.enroll.userKey.renewal.encryption.gracePeriod.before=30
+ * op.enroll.userKey.renewal.encryption.gracePeriod.after=30
+ * 2. In case of a grace period failure the code will go on
+ * and attempt to renew the next certificate in the list.
+ * 3. In case of any other code failure, the code will abort
+ * and leave the token untouched, while informing the user
+ * with an error message.
+ *
+ */
+ private TPSStatus processRenewal(EnrolledCertsInfo certsInfo, SecureChannel channel, AppletInfo aInfo,
+ TokenRecord tokenRecord)
+ throws TPSException, IOException {
+ TPSStatus status = TPSStatus.STATUS_ERROR_RENEWAL_FAILED;
+ String method = "TPSEnrollProcess.processRenewal";
+ String auditMsg;
+ CMS.debug(method + ": begins");
+
+ boolean noFailedCerts = true;
+
+ if (certsInfo == null || aInfo == null || channel == null) {
+ throw new TPSException(method + ": Bad Input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ TPSSubsystem tps =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ int keyTypeNum = getNumberCertsToRenew();
+ /*
+ * Get certs from the tokendb for this token to find out about
+ * renewal possibility
+ */
+ ArrayList<TPSCertRecord> allCerts = tps.tdb.tdbGetCertificatesByCUID(tokenRecord.getId());
+
+ certsInfo.setNumCertsToEnroll(keyTypeNum);
+
+ CMS.debug(method + ": Number of certs to renew: " + keyTypeNum);
+
+ for (int i = 0; i < keyTypeNum; i++) {
+ /*
+ * e.g. op.enroll.userKey.renewal.keyType.value.0=signing
+ * e.g. op.enroll.userKey.renewal.keyType.value.1=encryption
+ */
+ String keyType = getRenewConfigKeyType(i);
+ boolean renewEnabled = getRenewEnabled(keyType);
+ CMS.debug(method + ": key type " + keyType);
+ if (!renewEnabled) {
+ CMS.debug(method + ": renew not enabled");
+ continue;
+ }
+
+ CMS.debug(method + ": renew enabled");
+
+ certsInfo.setCurrentCertIndex(i);
+
+ CertEnrollInfo cEnrollInfo = new CertEnrollInfo();
+ IConfigStore configStore = CMS.getConfigStore();
+
+ // find all config
+ String configName = null;
+ boolean graceEnabled = false;
+ String graceBeforeS = null;
+ String graceAfterS = null;
+ try {
+ String keyTypePrefix = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + ".renewal." + keyType;
+
+ //TODO: profileId is actually gotten in the CARemoteRequestHandler.
+ configName = keyTypePrefix + ".ca.profileId";
+ String profileId;
+ profileId = configStore.getString(configName);
+ CMS.debug(method + ": profileId: " + profileId);
+
+ configName = keyTypePrefix + ".gracePeriod.enable";
+ graceEnabled = configStore.getBoolean(configName, false);
+ if (graceEnabled) {
+ CMS.debug(method + ": grace period check is enabled");
+ configName = keyTypePrefix + ".gracePeriod.before";
+ graceBeforeS = configStore.getString(configName, "");
+ configName = keyTypePrefix + ".gracePeriod.after";
+ graceAfterS = configStore.getString(configName, "");
+ } else {
+ CMS.debug(method + ": grace period check is not enabled");
+ }
+
+ configName = keyTypePrefix + ".certId";
+ String certId = configStore.getString(configName, "C0");
+ CMS.debug(method + ": certId: " + certId);
+
+ configName = keyTypePrefix + ".certAttrId";
+ String certAttrId = configStore.getString(configName, "c0");
+ CMS.debug(method + ": certAttrId: " + certAttrId);
+
+ configName = keyTypePrefix + ".privateKeyAttrId";
+ String priKeyAttrId = configStore.getString(configName, "k0");
+ CMS.debug(method + ": privateKeyAttrId: " + priKeyAttrId);
+
+ configName = keyTypePrefix + ".publicKeyAttrId";
+ String publicKeyAttrId = configStore.getString(configName, "k1");
+ CMS.debug(method + ": publicKeyAttrId: " + publicKeyAttrId);
+
+ } catch (EBaseException e) {
+ throw new TPSException(method + ": Internal error finding config value: " + configName + ":"
+ + e,
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+
+ // find the certs that match the keyType to renew
+ for (TPSCertRecord cert : allCerts) {
+ if (keyType.equals(cert.getKeyType())) {
+ try {
+ CMS.debug(method + ": cert " + cert.getId() + " with status:" + cert.getStatus());
+ if (cert.getStatus().equals("revoked") ||
+ cert.getStatus().equals("renewed")) {
+ CMS.debug(method + ": cert status is not to be renewed");
+ continue;
+ }
+
+ // check if within grace period to save us a trip (note: CA makes the final decision)
+ if (graceEnabled) {
+ try {
+ if (!isCertWithinRenewalGracePeriod(cert, graceBeforeS, graceAfterS))
+ continue;
+ } catch (TPSException ge) {
+ // error in this will just log and keep going
+ CMS.debug(method + ":" + ge + "; continue to try renewal");
+ }
+ }
+
+ //Renew and fetch the renewed cert blob.
+
+ CARenewCertResponse certResponse = tps.getEngine().renewCertificate(cert,
+ cert.getSerialNumber(), selectedTokenType, keyType, getCAConnectorID());
+ cEnrollInfo.setRenewedCertData(certResponse);
+
+ generateCertificate(certsInfo, channel, aInfo, keyType, TPSEngine.ENROLL_MODES.MODE_RENEWAL,
+ 0, cEnrollInfo);
+
+ //renewCertificate(cert, certsInfo, channel, aInfo, keyType);
+ status = TPSStatus.STATUS_ERROR_RENEWAL_IS_PROCESSED;
+ } catch (TPSException e) {
+ CMS.debug(method + "renewCertificate: exception:" + e);
+ noFailedCerts = false;
+ break; //need to clean up half-done token later
+ }
+ }
+ }
+ }
+
+ if (!noFailedCerts) {
+ // TODO: handle cleanup
+ auditMsg = "There has been failed cert renewal";
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(auditMsg + TPSStatus.STATUS_ERROR_RENEWAL_FAILED);
+ }
+ return status;
+ }
+
+ /*
+ * isCertWithinRenewalGracePeriod - check if a cert is within the renewal grace period
+ * @param cert the cert to be renewed
+ * @param renewGraceBeforeS string representation of the # of days "before" cert expiration date
+ * @param renewGraceAfterS string representation of the # of days "after" cert expiration date
+ */
+ private boolean isCertWithinRenewalGracePeriod(TPSCertRecord cert, String renewGraceBeforeS, String renewGraceAfterS)
+ throws TPSException {
+ String method = "TPSEnrollProcessor.isCertWithinRenewalGracePeriod";
+ int renewGraceBefore = 0;
+ int renewGraceAfter = 0;
+
+ if (cert == null || renewGraceBeforeS == null || renewGraceAfterS == null) {
+ CMS.debug(method + ": missing some input");
+ throw new TPSException(method + ": Bad Input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ BigInteger renewGraceBeforeBI = new BigInteger(renewGraceBeforeS);
+ BigInteger renewGraceAfterBI = new BigInteger(renewGraceAfterS);
+
+ // -1 means no limit
+ if (renewGraceBeforeS == "")
+ renewGraceBefore = -1;
+ else
+ renewGraceBefore = Integer.parseInt(renewGraceBeforeS);
+
+ if (renewGraceAfterS == "")
+ renewGraceAfter = -1;
+ else
+ renewGraceAfter = Integer.parseInt(renewGraceAfterS);
+
+ if (renewGraceBefore > 0)
+ renewGraceBeforeBI = renewGraceBeforeBI.multiply(BigInteger.valueOf(1000 * 86400));
+ if (renewGraceAfter > 0)
+ renewGraceAfterBI = renewGraceAfterBI.multiply(BigInteger.valueOf(1000 * 86400));
+
+ Date origExpDate = cert.getValidNotAfter();
+ Date current = CMS.getCurrentDate();
+ long millisDiff = origExpDate.getTime() - current.getTime();
+ CMS.debug(method + ": millisDiff="
+ + millisDiff + " origExpDate=" + origExpDate.getTime() + " current=" + current.getTime());
+
+ /*
+ * "days", if positive, has to be less than renew_grace_before
+ * "days", if negative, means already past expiration date,
+ * (abs value) has to be less than renew_grace_after
+ * if renew_grace_before or renew_grace_after are negative
+ * the one with negative value is ignored
+ */
+ if (millisDiff >= 0) {
+ if ((renewGraceBefore > 0) && (millisDiff > renewGraceBeforeBI.longValue())) {
+ CMS.debug(method + ": renewal attempted outside of grace period;" +
+ renewGraceBefore + " days before and " +
+ renewGraceAfter + " days after original cert expiration date");
+ return false;
+ }
+ } else {
+ if ((renewGraceAfter > 0) && ((0 - millisDiff) > renewGraceAfterBI.longValue())) {
+ CMS.debug(method + ": renewal attempted outside of grace period;" +
+ renewGraceBefore + " days before and " +
+ renewGraceAfter + " days after original cert expiration date");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean getRenewEnabled(String keyType) {
+ String method = "TPSEnrollProcessor.getRenewEnabled";
+ IConfigStore configStore = CMS.getConfigStore();
+ boolean enabled = false;
+
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + ".renewal."
+ + keyType + "." + "enable";
+ enabled = configStore.getBoolean(
+ configValue, false);
+
+ } catch (EBaseException e) {
+ //default to false
+ }
+
+ CMS.debug(method + ": returning " + enabled);
+ return enabled;
+ }
+
+ private String getRenewConfigKeyType(int keyTypeIndex) throws TPSException {
+ String method = "TPSEnrollProcessor.getRenewConfigKeyType";
+ IConfigStore configStore = CMS.getConfigStore();
+ String keyType = null;
+
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "."
+ + TPSEngine.CFG_RENEW_KEYTYPE_VALUE + "." + keyTypeIndex;
+ keyType = configStore.getString(
+ configValue, null);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ method + ": Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ //We would really like one of these to exist
+ if (keyType == null) {
+ throw new TPSException(
+ method + ": Internal error finding config value: ",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug(method + ": returning: " + keyType);
+
+ return keyType;
+
+ }
+
+ private int getNumberCertsToRenew() throws TPSException {
+ String method = "TPSEnrollProcessor.getNumberCertsToRenew";
+
+ IConfigStore configStore = CMS.getConfigStore();
+ int keyTypeNum = 0;
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "."
+ + TPSEngine.CFG_RENEW_KEYTYPE_NUM;
+ keyTypeNum = configStore.getInteger(
+ configValue, 0);
+
+ } catch (EBaseException e) {
+ throw new TPSException(method + ": Internal error finding config value: "
+ + e,
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+
+ if (keyTypeNum == 0) {
+ throw new TPSException(
+ method + ": invalid number of certificates to renew configured!",
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+ CMS.debug(method + ": returning: " + keyTypeNum);
+
+ return keyTypeNum;
+ }
+
+ private TPSStatus processRecovery(TokenRecord toBeRecovered, EnrolledCertsInfo certsInfo, SecureChannel channel,
+ AppletInfo aInfo) throws TPSException, IOException {
+ String method = "TPSEnrollProcessor.processRecover";
+ String auditMsg;
+ TPSStatus status = TPSStatus.STATUS_ERROR_RECOVERY_IS_PROCESSED;
+
+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ IConfigStore configStore = CMS.getConfigStore();
+
+ CMS.debug("TPSEnrollProcessor.processRecovery: entering:");
+
+ if (toBeRecovered == null || certsInfo == null || channel == null || aInfo == null) {
+ throw new TPSException("TPSEnrollProcessor.processRecovery: Invalid reason!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ String reason = toBeRecovered.getReason();
+
+ int num = getNumberCertsForRecovery(reason);
+
+ int totalNumCerts = 0;
+
+ //We will have to rifle through the configuration to see if there any recovery operations with
+ //scheme "GenerateNewKeyandRecoverLast" which allows for recovering the old key AND generating a new
+ // one for the encryption type only. If this scheme is present, the number of certs for bump by
+ // 1 for each occurrence.
+
+ String keyTypeValue = null;
+ String scheme = null;
+ CMS.debug("TPSEnrollProcessor.processRecovery: About to find if we have any GenerateNewAndRecoverLast schemes.");
+ for (int i = 0; i < num; i++) {
+ keyTypeValue = getRecoveryKeyTypeValue(reason, i);
+ scheme = getRecoveryScheme(reason, keyTypeValue);
+
+ if (scheme.equals(TPSEngine.RECOVERY_SCHEME_GENERATE_NEW_KEY_AND_RECOVER_LAST)) {
+
+ //Make sure we are not signing:
+ if (keyTypeValue.equals(TPSEngine.CFG_SIGNING)) {
+ throw new TPSException(
+ "TPSEnrollProcessor.processRecovery: Can't have GenerateNewAndRecoverLast scheme with a signing key!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+ totalNumCerts++;
+ }
+ totalNumCerts++;
+ }
+
+ CMS.debug("TPSEnrollProcessor.processRecovery: About to perform actual recoveries: totalNumCerts: "
+ + totalNumCerts);
+
+ if (!(totalNumCerts > num)) {
+ totalNumCerts = num;
+ }
+
+ boolean isGenerateAndRecover = false;
+ int actualCertIndex = 0;
+ boolean legalScheme = false;
+
+ //Go through again and do the recoveries/enrollments
+
+ certsInfo.setNumCertsToEnroll(totalNumCerts);
+ for (int i = 0; i < num; i++) {
+
+ keyTypeValue = getRecoveryKeyTypeValue(reason, i);
+ scheme = getRecoveryScheme(reason, keyTypeValue);
+
+ if (scheme.equals(TPSEngine.RECOVERY_SCHEME_GENERATE_NEW_KEY_AND_RECOVER_LAST)) {
+ CMS.debug("TPSEnrollProcessor.processRecovery: scheme GenerateNewKeyAndRecoverLast found.");
+ isGenerateAndRecover = true;
+
+ } else {
+ isGenerateAndRecover = false;
+ }
+
+ if (scheme.equals(TPSEngine.RECOVERY_GENERATE_NEW_KEY) || isGenerateAndRecover) {
+ legalScheme = true;
+ CertEnrollInfo cEnrollInfo = new CertEnrollInfo();
+ generateCertificate(certsInfo, channel, aInfo, keyTypeValue, TPSEngine.ENROLL_MODES.MODE_ENROLL,
+ actualCertIndex, cEnrollInfo);
+
+ actualCertIndex = cEnrollInfo.getCertIdIndex();
+ CMS.debug("TPSEnrollProcessor.processRecovery: scheme GenerateNewKey found, or isGenerateAndRecove is true: actualCertIndex, after enrollment: "
+ + actualCertIndex);
+
+ }
+
+ if (scheme.equals(TPSEngine.RECOVERY_RECOVER_LAST) || isGenerateAndRecover) {
+ legalScheme = true;
+ CMS.debug("TPSEnrollProcessor.processRecovery: scheme RecoverLast found, or isGenerateAndRecove is true");
+ if (isGenerateAndRecover) {
+ CMS.debug("TPSEnrollProcessor.processRecovery: isGenerateAndRecover is true.");
+ actualCertIndex++;
+ }
+
+ ArrayList<TPSCertRecord> certs = tps.tdb.tdbGetCertificatesByCUID(toBeRecovered.getId());
+
+ String serialToRecover = null;
+ TPSCertRecord certToRecover = null;
+ for (TPSCertRecord rec : certs) {
+
+ //Just take the end of the list most recent cert of given type.
+ CMS.debug("TPSEnrollProcessor.processRecovery: Looking for keyType record: " + keyTypeValue
+ + " curSererial: " + rec.getSerialNumber());
+
+ if (rec.getKeyType().equals(keyTypeValue)) {
+ serialToRecover = rec.getSerialNumber();
+ certToRecover = rec;
+ CMS.debug("TPSCertRecord: serial number: " + serialToRecover);
+ }
+
+ }
+ String b64cert = null;
+ if (serialToRecover != null) {
+ // get recovery conn id
+ String caConnId;
+ String config = "op.enroll." + certToRecover.getType() + ".keyGen." + certToRecover.getKeyType() + ".ca.conn";
+ try {
+ caConnId = configStore.getString(config);
+ } catch (Exception e) {
+ auditMsg = "cannot find config:" + config;
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(
+ method + ":" + auditMsg,
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+ CMS.debug("TPSEnrollProcessor.processRecovery: Selecting cert to recover: " + serialToRecover);
+
+ CARetrieveCertResponse certResponse = tps.getEngine().recoverCertificate(certToRecover,
+ serialToRecover, keyTypeValue, caConnId);
+
+ b64cert = certResponse.getCertB64();
+ CMS.debug("TPSEnrollProcessor.processRecovery: recoverd cert blob: " + b64cert);
+
+ KRARecoverKeyResponse keyResponse = tps.getEngine().recoverKey(toBeRecovered.getId(),
+ toBeRecovered.getUserID(),
+ channel.getDRMWrappedDesKey(), b64cert, getDRMConnectorID());
+
+ CertEnrollInfo cEnrollInfo = new CertEnrollInfo();
+
+ cEnrollInfo.setTokenToBeRecovered(toBeRecovered);
+ cEnrollInfo.setRecoveredCertData(certResponse);
+ cEnrollInfo.setRecoveredKeyData(keyResponse);
+
+ generateCertificate(certsInfo, channel, aInfo, keyTypeValue, TPSEngine.ENROLL_MODES.MODE_RECOVERY,
+ actualCertIndex, cEnrollInfo);
+
+ // unrevoke cert if needed
+ if (certToRecover.getStatus().equalsIgnoreCase("revoked_on_hold")) {
+ auditMsg = "unrevoking cert...";
+ CMS.debug(method + ":" + auditMsg);
+
+ CARemoteRequestHandler caRH = null;
+ try {
+ caRH = new CARemoteRequestHandler(caConnId);
+
+ CARevokeCertResponse response =
+ caRH.revokeCertificate(false /*unrevoke*/, serialToRecover,
+ certToRecover.getCertificate(),
+ null);
+ CMS.debug(method + ": response status =" + response.getStatus());
+
+ } catch (EBaseException e) {
+ auditMsg = "failed getting CARemoteRequestHandler";
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(method + ":" + auditMsg, TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+ }
+
+ // set cert status to active
+ certToRecover.setStatus("active");
+ try {
+ tps.tdb.tdbUpdateCertEntry(certToRecover);
+ } catch (Exception e) {
+ auditMsg = "failed tdbUpdateCertEntry";
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(method + ":" + auditMsg, TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+ } else {
+
+ }
+
+ }
+
+ if (!legalScheme) {
+ throw new TPSException("TPSEnrollProcessor.processRecovery: Invalid recovery configuration!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+ actualCertIndex++;
+
+ }
+
+ return status;
+ }
+
+ //Stub to generate a certificate, more to come
+ private boolean generateCertificates(EnrolledCertsInfo certsInfo, SecureChannel channel, AppletInfo aInfo)
+ throws TPSException, IOException {
+
+ CMS.debug("TPSEnrollProcess.generateCertificates: begins ");
+ boolean noFailedCerts = true;
+
+ if (certsInfo == null || aInfo == null || channel == null) {
+ throw new TPSException("TPSEnrollProcessor.generateCertificates: Bad Input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ int keyTypeNum = getNumberCertsToEnroll();
+
+ certsInfo.setNumCertsToEnroll(keyTypeNum);
+
+ CMS.debug("TPSEnrollProcessor.generateCertificate: Number of certs to enroll: " + keyTypeNum);
+
+ for (int i = 0; i < keyTypeNum; i++) {
+ String keyType = getConfiguredKeyType(i);
+ certsInfo.setCurrentCertIndex(i);
+ try {
+ generateCertificate(certsInfo, channel, aInfo, keyType, TPSEngine.ENROLL_MODES.MODE_ENROLL, 0, null);
+ } catch (TPSException e) {
+ CMS.debug("TPSEnrollProcessor.generateCertificate: exception:" + e);
+ noFailedCerts = false;
+ break; //need to clean up half-done token later
+ }
+ }
+
+ /*
+ * In this special case of RE_ENROLL, Revoke current certs for this token
+ * if so configured
+ */
+ /*TODO: format that follows should do this already based on the returned noFailedCerts value
+ if (noFailedCerts == true) {
+ revokeCertificates(aInfo.getCUIDhexStringPlain());
+ }
+ */
+
+ CMS.debug("TPSEnrollProcessor.generateCertificates: ends ");
+ return noFailedCerts;
+ }
+
+ private String buildTokenLabel(EnrolledCertsInfo certsInfo, AppletInfo ainfo) throws TPSException {
+ String label = null;
+
+ if (certsInfo == null || ainfo == null) {
+ throw new TPSException("TPSEnrollProcessor.buildTokenLabel: invalide input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("TPSEnrollProcessor.buildTokenLabel: entering...");
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String configName = TPSEngine.OP_ENROLL_PREFIX + "." + getSelectedTokenType() + ".keyGen.tokenName";
+ String pattern = null;
+
+ try {
+ pattern = configStore.getString(configName, "$cuid$");
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.buildTokenLabel: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+ }
+
+ CMS.debug("TPSEnrollProcessor.buildTokenLabel: pattern: " + pattern);
+
+ Map<String, String> nv = new LinkedHashMap<String, String>();
+
+ nv.put("cuid", ainfo.getCUIDhexString());
+ nv.put("msn", ainfo.getMSNString());
+ nv.put("userid", userid);
+ nv.put("auth.cn", userid);
+ nv.put("profileId", getSelectedTokenType());
+
+ label = mapPattern((LinkedHashMap<String, String>) nv, pattern);
+
+ CMS.debug("TPSEnrollProcessor.buildTokenLabel: returning: " + label);
+
+ return label;
+
+ }
+
+ /* This routine will be able to handle:
+ * regular enrollment
+ * recovery enrollment
+ * renewal enrollment
+ */
+ private void generateCertificate(EnrolledCertsInfo certsInfo, SecureChannel channel, AppletInfo aInfo,
+ String keyType, TPSEngine.ENROLL_MODES mode, int certIdNumOverride, CertEnrollInfo cEnrollInfo)
+ throws TPSException, IOException {
+
+ CMS.debug("TPSEnrollProcessor.generateCertificate: entering ... certIdNumOverride: " + certIdNumOverride
+ + " mode: " + mode);
+
+ if (certsInfo == null || aInfo == null || channel == null || aInfo == null) {
+ throw new TPSException("TPSEnrollProcessor.generateCertificate: Bad Input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ //get the params needed all at once
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ boolean isRenewal = false;
+
+ // This operation modifier allows us to get config entries for either
+ // regular enrollment and renewal. Allows the re-use of repetitive config processing code below.
+ String operationModifier = "keyGen";
+ if (mode == ENROLL_MODES.MODE_RENEWAL) {
+ isRenewal = true;
+ operationModifier = "renewal";
+ }
+
+ if (cEnrollInfo == null)
+ cEnrollInfo = new CertEnrollInfo();
+
+ try {
+
+ String keyTypePrefix = TPSEngine.OP_ENROLL_PREFIX + "." + getSelectedTokenType() + "." + operationModifier
+ + "." + keyType;
+ CMS.debug("TPSEnrollProcessor.generateCertificate: keyTypePrefix: " + keyTypePrefix);
+
+ String configName = keyTypePrefix + ".ca.profileId";
+ String profileId = configStore.getString(configName);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: profileId: " + profileId);
+
+ configName = keyTypePrefix + ".certId";
+ String certId = configStore.getString(configName, "C0");
+ CMS.debug("TPSEnrollProcessor.generateCertificate: certId: " + certId);
+
+ configName = keyTypePrefix + ".certAttrId";
+ String certAttrId = configStore.getString(configName, "c0");
+ CMS.debug("TPSEnrollProcessor.generateCertificate: certAttrId: " + certAttrId);
+
+ configName = keyTypePrefix + ".privateKeyAttrId";
+ String priKeyAttrId = configStore.getString(configName, "k0");
+ CMS.debug("TPSEnrollProcessor.generateCertificate: priKeyAttrId: " + priKeyAttrId);
+
+ configName = keyTypePrefix + ".publicKeyAttrId";
+ String publicKeyAttrId = configStore.getString(configName, "k1");
+ CMS.debug("TPSEnrollProcessor.generateCertificate: publicKeyAttrId: " + publicKeyAttrId);
+
+ configName = keyTypePrefix + ".keySize";
+ int keySize = configStore.getInteger(configName, 1024);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: keySize: " + keySize);
+
+ //Default RSA_CRT=2
+ configName = keyTypePrefix + ".alg";
+ int algorithm = configStore.getInteger(configName, 2);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: algorithm: " + algorithm);
+
+ configName = keyTypePrefix + ".publisherId";
+ String publisherId = configStore.getString(configName, "");
+ CMS.debug("TPSEnrollProcessor.generateCertificate: publisherId: " + publisherId);
+
+ configName = keyTypePrefix + ".keyUsage";
+ int keyUsage = configStore.getInteger(configName, 0);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: keyUsage: " + keyUsage);
+
+ configName = keyTypePrefix + ".keyUser";
+ int keyUser = configStore.getInteger(configName, 0);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: keyUser: " + keyUser);
+
+ configName = keyTypePrefix + ".privateKeyNumber";
+ int priKeyNumber = configStore.getInteger(configName, 0);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: privateKeyNumber: " + priKeyNumber);
+
+ configName = keyTypePrefix + ".publicKeyNumber";
+ int pubKeyNumber = configStore.getInteger(configName, 0);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: pubKeyNumber: " + pubKeyNumber);
+
+ // get key capabilites to determine if the key type is SIGNING,
+ // ENCRYPTION, or SIGNING_AND_ENCRYPTION
+
+ configName = keyTypePrefix + ".private.keyCapabilities.sign";
+ boolean isSigning = configStore.getBoolean(configName, false);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: isSigning: " + isSigning);
+
+ configName = keyTypePrefix + ".public.keyCapabilities.encrypt";
+ CMS.debug("TPSEnrollProcessor.generateCertificate: encrypt config name: " + configName);
+ boolean isEncrypt = configStore.getBoolean(configName, true);
+ CMS.debug("TPSEnrollProcessor.generateCertificate: isEncrypt: " + isEncrypt);
+
+ TokenKeyType keyTypeEnum;
+
+ if (isSigning && isEncrypt) {
+ keyTypeEnum = TokenKeyType.KEY_TYPE_SIGNING_AND_ENCRYPTION;
+ } else if (isSigning) {
+ keyTypeEnum = TokenKeyType.KEY_TYPE_SIGNING;
+ } else if (isEncrypt) {
+ keyTypeEnum = TokenKeyType.KEY_TYPE_ENCRYPTION;
+ } else {
+ CMS.debug("TPSEnrollProcessor.generateCertificate: Illegal toke key type!");
+ throw new TPSException("TPSEnrollProcessor.generateCertificate: Illegal toke key type!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("TPSEnrollProcessor.generateCertificate: keyTypeEnum value: " + keyTypeEnum);
+
+ // The certIdNumOverride allows us to place the certs and keys into a different slot.
+ // Thus overriding what is found in the config.
+ // Used in recovery mostly up to this point.
+
+ if (certIdNumOverride > 0) {
+ CMS.debug("TPSEnrollProcessor.generateCertificate: called with overridden cert id number: "
+ + certIdNumOverride);
+
+ pubKeyNumber = 2 * certIdNumOverride + 1;
+ priKeyNumber = 2 * certIdNumOverride;
+
+ certId = "C" + certIdNumOverride;
+ certAttrId = "c" + certIdNumOverride;
+ priKeyAttrId = "k" + priKeyNumber;
+ publicKeyAttrId = "k" + pubKeyNumber;
+
+ CMS.debug("TPSEnrollProcessor.generateCertificate: called with overridden cert no: certId: " + certId
+ + " certAttrId: " + certAttrId + " priKeyAttrId: " + priKeyAttrId + " publicKeyAttrId: "
+ + publicKeyAttrId);
+
+ }
+
+ cEnrollInfo.setKeyTypeEnum(keyTypeEnum);
+ cEnrollInfo.setProfileId(profileId);
+ cEnrollInfo.setCertId(certId);
+ cEnrollInfo.setCertAttrId(certAttrId);
+
+ // These setting are key related and have no meaning in renewal.
+ if (isRenewal == false) {
+ cEnrollInfo.setPrivateKeyAttrId(priKeyAttrId);
+ cEnrollInfo.setPublicKeyAttrId(publicKeyAttrId);
+ cEnrollInfo.setKeySize(keySize);
+ cEnrollInfo.setAlgorithm(algorithm);
+ cEnrollInfo.setPublisherId(publisherId);
+ cEnrollInfo.setKeyUsage(keyUsage);
+ cEnrollInfo.setKeyUser(keyUser);
+ cEnrollInfo.setPrivateKeyNumber(priKeyNumber);
+ cEnrollInfo.setPublicKeyNumber(pubKeyNumber);
+ cEnrollInfo.setKeyType(keyType);
+ cEnrollInfo.setKeyTypePrefix(keyTypePrefix);
+ }
+
+ int certsStartProgress = certsInfo.getStartProgressValue();
+ int certsEndProgress = certsInfo.getEndProgressValue();
+ int currentCertIndex = certsInfo.getCurrentCertIndex();
+ int totalNumCerts = certsInfo.getNumCertsToEnroll();
+
+ int progressBlock = (certsEndProgress - certsStartProgress) / totalNumCerts;
+
+ int startCertProgValue = certsStartProgress + currentCertIndex * progressBlock;
+
+ int endCertProgValue = startCertProgValue + progressBlock;
+
+ cEnrollInfo.setStartProgressValue(startCertProgValue);
+ cEnrollInfo.setEndProgressValue(endCertProgValue);
+
+ } catch (EBaseException e) {
+
+ throw new TPSException(
+ "TPSEnrollProcessor.generateCertificate: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ enrollOneCertificate(certsInfo, cEnrollInfo, aInfo, channel, mode);
+
+ }
+
+ /* Core method handles the following modes:
+ * Regular enrollment
+ * Recovery enrollment
+ * Renewal enrollment
+ */
+ private void enrollOneCertificate(EnrolledCertsInfo certsInfo, CertEnrollInfo cEnrollInfo, AppletInfo aInfo,
+ SecureChannel channel, TPSEngine.ENROLL_MODES mode)
+ throws TPSException, IOException {
+
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: entering ... mode: " + mode);
+
+ if (certsInfo == null || aInfo == null || cEnrollInfo == null || channel == null) {
+ throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: Bad Input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ statusUpdate(cEnrollInfo.getStartProgressValue(), "PROGRESS_KEY_GENERATION");
+ boolean serverSideKeyGen = checkForServerSideKeyGen(cEnrollInfo);
+ boolean objectOverwrite = checkForObjectOverwrite(cEnrollInfo);
+
+ PKCS11Obj pkcs11obj = certsInfo.getPKCS11Obj();
+
+ int keyAlg = cEnrollInfo.getAlgorithm();
+
+ boolean isECC = getTPSEngine().isAlgorithmECC(keyAlg);
+
+ if (objectOverwrite) {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: We are configured to overwrite existing cert objects.");
+
+ } else {
+
+ boolean certIdExists = pkcs11obj.doesCertIdExist(cEnrollInfo.getCertId());
+
+ //Bomb out if cert exists, we ca't overwrite
+
+ if (certIdExists) {
+ throw new TPSException(
+ "TPSEnrollProcessor.enrollOneCertificate: Overwrite of certificates not allowed!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ }
+
+ TPSBuffer public_key_blob = null;
+ KRAServerSideKeyGenResponse ssKeyGenResponse = null;
+ KRARecoverKeyResponse keyResp = null;
+ RSAPublicKey parsedPubKey = null;
+ PK11PubKey parsedPK11PubKey = null;
+ byte[] parsedPubKey_ba = null;
+
+ boolean isRecovery = false;
+ boolean isRenewal = false;
+
+ if (mode == ENROLL_MODES.MODE_RECOVERY) {
+ isRecovery = true;
+
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: detecting recovery mode!");
+ if (isRecovery && !serverSideKeyGen) {
+ throw new TPSException(
+ "TPSEnrollProcessor.enrollOneCertificate: Attempting illegal recovery when archival is not enabled!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+ }
+
+ if (mode == ENROLL_MODES.MODE_RENEWAL) {
+ isRenewal = true;
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: detecting renewal mode!");
+ }
+
+ if (serverSideKeyGen || isRecovery) {
+ //Handle server side keyGen/recovery
+ // The main difference is where the key and cert data is obtained.
+ // In recovery the cert and key are recovered.
+ // In server side key gen, cert is enrolled and key is generated and recovered.
+
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: either generate private key on the server, or preform recovery or perform renewal.");
+ boolean archive = checkForServerKeyArchival(cEnrollInfo);
+ String drmConnId = getDRMConnectorID();
+
+ String publicKeyStr = null;
+ //Do this for JUST server side keygen
+ if (isRecovery == false) {
+ ssKeyGenResponse = getTPSEngine()
+ .serverSideKeyGen(cEnrollInfo.getKeySize(),
+ aInfo.getCUIDhexStringPlain(), userid, drmConnId, channel.getDRMWrappedDesKey(),
+ archive, isECC);
+
+ publicKeyStr = ssKeyGenResponse.getPublicKey();
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: public key string from server: " + publicKeyStr);
+ public_key_blob = new TPSBuffer(Utils.base64decode(publicKeyStr));
+
+ } else {
+ //Here we have a recovery, get the key data from the CertInfo object
+
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: Attempt to get key data in recovery mode!");
+ keyResp = cEnrollInfo.getRecoveredKeyData();
+
+ publicKeyStr = keyResp.getPublicKey();
+ public_key_blob = new TPSBuffer(Utils.base64decode(publicKeyStr));
+
+ }
+
+ try {
+ parsedPK11PubKey = PK11RSAPublicKey.fromSPKI(public_key_blob.toBytesArray());
+
+ } catch (InvalidKeyFormatException e) {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate, can't create public key object from server side key generated public key blob!");
+ throw new TPSException(
+ "TPSEnrollProcessor.enrollOneCertificate, can't create public key object from server side key generated public key blob!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ parsedPubKey_ba = parsedPK11PubKey.getEncoded();
+
+ } else if (isRenewal) {
+
+ CMS.debug("TPSEnrollProcessor: We are in renewal mode, no work to do with the keys, in renewal the keys remain on the token.");
+
+ } else {
+ //Handle token side keyGen
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: about to generate the private key on the token.");
+
+ int algorithm = 0x80;
+
+ if (certsInfo.getKeyCheck() != null) {
+ algorithm = 0x81;
+ }
+
+ if (isECC) {
+ algorithm = keyAlg;
+ }
+
+ int pe1 = (cEnrollInfo.getKeyUser() << 4) + cEnrollInfo.getPrivateKeyNumber();
+ int pe2 = (cEnrollInfo.getKeyUsage() << 4) + cEnrollInfo.getPublicKeyNumber();
+
+ int size = channel.startEnrollment(pe1, pe2, certsInfo.getWrappedChallenge(), certsInfo.getKeyCheck(),
+ algorithm, cEnrollInfo.getKeySize(), 0x0);
+
+ byte[] iobytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
+ TPSBuffer iobuf = new TPSBuffer(iobytes);
+
+ public_key_blob = channel.readObject(iobuf, 0, size);
+
+ parsedPubKey = parsePublicKeyBlob(public_key_blob, isECC);
+
+ parsedPubKey_ba = parsedPubKey.getEncoded();
+ }
+
+ // enrollment/recovery begins
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: enrollment begins");
+ X509CertImpl x509Cert = null;
+ byte[] cert_bytes = null;
+ try {
+
+ if (isRecovery == false && isRenewal == false) {
+ String caConnID = getCAConnectorID();
+ CARemoteRequestHandler caRH = new CARemoteRequestHandler(caConnID);
+ TPSBuffer encodedParsedPubKey = new TPSBuffer(parsedPubKey_ba);
+
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: userid =" + userid + ", cuid="
+ + aInfo.getCUIDhexString());
+ CAEnrollCertResponse caEnrollResp = caRH.enrollCertificate(encodedParsedPubKey, userid,
+ aInfo.getCUIDhexString(), getSelectedTokenType(),
+ cEnrollInfo.getKeyType());
+ String retCertB64 = caEnrollResp.getCertB64();
+
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: retCertB64: " + retCertB64);
+
+ cert_bytes = Utils.base64decode(retCertB64);
+
+ TPSBuffer cert_bytes_buf = new TPSBuffer(cert_bytes);
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: retCertB64: " + cert_bytes_buf.toHexString());
+
+ if (retCertB64 != null)
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert b64 =" + retCertB64);
+ else {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert b64 not found");
+ throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: new cert b64 not found",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ x509Cert = caEnrollResp.getCert();
+ if (x509Cert != null)
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert retrieved");
+ else {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: new cert not found");
+ throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: new cert not found",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ } else {
+ //Import the cert data from the CertEnrollObject or from Renewal object
+
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: Attempt to import cert data in recovery mode or renew mode!");
+
+ if (isRecovery) {
+ CARetrieveCertResponse certResp = cEnrollInfo.getRecoveredCertData();
+
+ if (certResp == null) {
+ throw new TPSException(
+ "TPSEnrollProcessor.enrollOneCertificate: In recovery mode, CARetieveCertResponse object not found!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ String retCertB64 = certResp.getCertB64();
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: recovering: retCertB64: " + retCertB64);
+ cert_bytes = Utils.base64decode(retCertB64);
+
+ TPSBuffer cert_bytes_buf = new TPSBuffer(cert_bytes);
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: recovering: retCertB64: "
+ + cert_bytes_buf.toHexString());
+
+ if (retCertB64 != null)
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: recovering: new cert b64 =" + retCertB64);
+ else {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: recovering new cert b64 not found");
+ throw new TPSException(
+ "TPSEnrollProcessor.enrollOneCertificate: recovering: new cert b64 not found",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+ x509Cert = certResp.getCert();
+ if (x509Cert != null)
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: recovering new cert retrieved");
+ else {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: recovering new cert not found");
+ throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: new cert not found",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ }
+
+ // If we are here, it has to be one or the other.
+
+ if (isRenewal) {
+
+ CARenewCertResponse certResp = cEnrollInfo.getRenewedCertData();
+ if (certResp == null) {
+ throw new TPSException(
+ "TPSEnrollProcessor.enrollOneCertificate: In renewal mode, CARemewCertResponse object not found!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ String retCertB64 = certResp.getRenewedCertB64();
+ cert_bytes = Utils.base64decode(retCertB64);
+
+ if (retCertB64 != null)
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: renewing: new cert b64 =" + retCertB64);
+ else {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: renewing new cert b64 not found");
+ throw new TPSException(
+ "TPSEnrollProcessor.enrollOneCertificate: remewomg: new cert b64 not found",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ x509Cert = certResp.getRenewedCert();
+
+ if (x509Cert != null)
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: renewing new cert retrieved");
+ else {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: renewing new cert not found");
+ throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: new cert not found",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+
+ TPSBuffer cert_bytes_buf = new TPSBuffer(cert_bytes);
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: renewing: retCertB64: "
+ + cert_bytes_buf.toHexString());
+
+ }
+
+ }
+
+ certsInfo.addCertificate(x509Cert);
+ // In renewal case, we don't need to save this info.
+ if (!isRenewal) {
+ certsInfo.addKType(cEnrollInfo.getKeyType());
+ }
+
+ //Add origin, special handling for recovery case.
+ if (isRecovery == true) {
+ TokenRecord recordToRecover = cEnrollInfo.getTokenToBeRecovered();
+ //We need to have this token record otherwise bomb out.
+
+ if (recordToRecover == null) {
+ throw new TPSException(
+ "TPSEnrollProcessor.enrollOneCertificate: TokenRecord of token to be recovered not found.",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ certsInfo.addOrigin(recordToRecover.getId());
+
+ } else {
+ certsInfo.addOrigin(aInfo.getCUIDhexStringPlain());
+ }
+
+ certsInfo.addTokenType(selectedTokenType);
+
+ SubjectPublicKeyInfo publicKeyInfo = null;
+
+ String label = null;
+ TPSBuffer keyid = null;
+ TPSBuffer modulus = null;
+ TPSBuffer exponent = null;
+
+ if (!isRenewal) {
+
+ try {
+ if (serverSideKeyGen) {
+ publicKeyInfo = new SubjectPublicKeyInfo(parsedPK11PubKey);
+ } else {
+ publicKeyInfo = new SubjectPublicKeyInfo(parsedPubKey);
+ }
+ } catch (InvalidBERException e) {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: cant get publicKeyInfo object.");
+ throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: can't get publcKeyInfo object.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ //Create label ToDo: Do this the correct way later
+
+ label = buildCertificateLabel(cEnrollInfo, aInfo);
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: cert label: " + label);
+
+ keyid = new TPSBuffer(makeKeyIDFromPublicKeyInfo(publicKeyInfo.getEncoded()));
+
+ modulus = null;
+ exponent = null;
+
+ if (serverSideKeyGen) {
+ modulus = new TPSBuffer(((PK11RSAPublicKey) parsedPK11PubKey).getModulus().toByteArray());
+ exponent = new TPSBuffer(((PK11RSAPublicKey) parsedPK11PubKey).getPublicExponent().toByteArray());
+
+ } else {
+ modulus = new TPSBuffer(parsedPubKey.getModulus().toByteArray());
+ exponent = new TPSBuffer(parsedPubKey.getPublicExponent().toByteArray());
+ }
+
+ }
+
+ //Write cert to the token,do this in all modes
+
+ long l1, l2;
+ long objid;
+ PKCS11Obj pkcs11Obj = certsInfo.getPKCS11Obj();
+
+ String certId = cEnrollInfo.getCertId();
+
+ l1 = (certId.charAt(0) & 0xff) << 24;
+ l2 = (certId.charAt(1) & 0xff) << 16;
+ objid = l1 + l2;
+
+ CMS.debug("TPSEnrollProcess.enrollOneCertificate: cert objid long: " + objid);
+
+ ObjectSpec certObjSpec = ObjectSpec.parseFromTokenData(objid, new TPSBuffer(cert_bytes));
+ pkcs11Obj.addObjectSpec(certObjSpec);
+
+ //Do the rest of this stuff only in enrollment or recovery case, in renewal, we need not deal with the keys
+
+ if (isRenewal == false) {
+
+ String certAttrId = cEnrollInfo.getCertAttrId();
+
+ TPSBuffer certAttrsBuffer = channel.createPKCS11CertAttrsBuffer(cEnrollInfo.getKeyTypeEnum(),
+ certAttrId, label, keyid);
+
+ l1 = (certAttrId.charAt(0) & 0xff) << 24;
+ l2 = (certAttrId.charAt(1) & 0xff) << 16;
+ objid = l1 + l2;
+
+ CMS.debug("TPSEnrollProcess.enrollOneCertificate: cert attr objid long: " + objid);
+ ObjectSpec certAttrObjSpec = ObjectSpec.parseFromTokenData(objid, certAttrsBuffer);
+ pkcs11Obj.addObjectSpec(certAttrObjSpec);
+
+ //Add the pri key attrs object
+
+ String priKeyAttrId = cEnrollInfo.getPrivateKeyAttrId();
+
+ l1 = (priKeyAttrId.charAt(0) & 0xff) << 24;
+ l2 = (priKeyAttrId.charAt(1) & 0xff) << 16;
+
+ objid = l1 + l2;
+
+ CMS.debug("TPSEnrollProcess.enrollOneCertificate: pri key objid long: " + objid);
+
+ TPSBuffer privKeyAttrsBuffer = channel.createPKCS11PriKeyAttrsBuffer(priKeyAttrId, label, keyid,
+ modulus, cEnrollInfo.getKeyTypePrefix());
+
+ ObjectSpec priKeyObjSpec = ObjectSpec.parseFromTokenData(objid, privKeyAttrsBuffer);
+ pkcs11obj.addObjectSpec(priKeyObjSpec);
+
+ // Now add the public key object
+
+ String pubKeyAttrId = cEnrollInfo.getPublicKeyAttrId();
+
+ l1 = (pubKeyAttrId.charAt(0) & 0xff) << 24;
+ l2 = (pubKeyAttrId.charAt(1) & 0xff) << 16;
+
+ objid = l1 + l2;
+ CMS.debug("TPSEnrollProcess.enrollOneCertificate: pub key objid long: " + objid);
+
+ TPSBuffer pubKeyAttrsBuffer = channel.createPKCS11PublicKeyAttrsBuffer(pubKeyAttrId, label, keyid,
+ modulus, exponent, cEnrollInfo.getKeyTypePrefix());
+ ObjectSpec pubKeyObjSpec = ObjectSpec.parseFromTokenData(objid, pubKeyAttrsBuffer);
+ pkcs11obj.addObjectSpec(pubKeyObjSpec);
+
+ }
+ } catch (EBaseException e) {
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate::" + e);
+ throw new TPSException("TPSEnrollProcessor.enrollOneCertificate: Exception thrown: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ if (serverSideKeyGen || isRecovery) {
+ //Handle injection of private key onto token
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate: About to inject private key");
+
+ if (!isRecovery) {
+
+ // SecureChannel newChannel = setupSecureChannel();
+ importPrivateKeyPKCS8(ssKeyGenResponse, cEnrollInfo, channel, isECC);
+
+ } else {
+ importPrivateKeyPKCS8(keyResp, cEnrollInfo, channel, isECC);
+ }
+
+ }
+
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate:: enrollment ends");
+
+ statusUpdate(cEnrollInfo.getEndProgressValue(), "PROGRESS_ENROLL_CERT");
+ CMS.debug("TPSEnrollProcessor.enrollOneCertificate ends");
+
+ }
+
+ private void importPrivateKeyPKCS8(KRARecoverKeyResponse keyResp, CertEnrollInfo cEnrollInfo,
+ SecureChannel channel,
+ boolean isECC) throws TPSException, IOException {
+
+ if (keyResp == null || cEnrollInfo == null || channel == null) {
+ throw new TPSException("TPSEnrollProcessor.importPrivateKeyPKCS8: invalid input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ importPrivateKeyPKCS8(keyResp.getWrappedPrivKey(), keyResp.getIVParam(), cEnrollInfo, channel, isECC);
+
+ }
+
+ private void importPrivateKeyPKCS8(KRAServerSideKeyGenResponse ssKeyGenResponse, CertEnrollInfo cEnrollInfo,
+ SecureChannel channel,
+ boolean isECC) throws TPSException, IOException {
+
+ if (ssKeyGenResponse == null || cEnrollInfo == null || channel == null) {
+ throw new TPSException("TPSEnrollProcessor.importPrivateKeyPKCS8: invalid input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ importPrivateKeyPKCS8(ssKeyGenResponse.getWrappedPrivKey(), ssKeyGenResponse.getIVParam(), cEnrollInfo,
+ channel, isECC);
+
+ }
+
+ private void importPrivateKeyPKCS8(String wrappedPrivKeyStr, String ivParams, CertEnrollInfo cEnrollInfo,
+ SecureChannel channel,
+ boolean isECC) throws TPSException, IOException {
+
+ CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 entering..");
+ if (wrappedPrivKeyStr == null || ivParams == null || cEnrollInfo == null || channel == null) {
+ throw new TPSException("TPSEnrollProcessor.importPrivateKeyPKCS8: invalid input data!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ byte[] objid = {
+ (byte) 0xFF,
+ 0x00,
+ (byte) 0xFF,
+ (byte) 0xF3 };
+
+ byte keytype = 0x09; //RSAPKCS8Pair
+
+ // String wrappedPrivKeyStr = ssKeyGenResponse.getWrappedPrivKey();
+ int keysize = cEnrollInfo.getKeySize();
+
+ TPSBuffer privKeyBlob = new TPSBuffer();
+
+ privKeyBlob.add((byte) 0x1); // encryption
+ privKeyBlob.add(keytype);
+ privKeyBlob.add((byte) (keysize / 256));
+ privKeyBlob.add((byte) (keysize % 256));
+
+ TPSBuffer privKeyBuff = new TPSBuffer(Util.uriDecodeFromHex(wrappedPrivKeyStr));
+ privKeyBlob.add(privKeyBuff);
+
+ CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 privKeyBlob: " + privKeyBlob.toHexString());
+
+ byte[] perms = { 0x40,
+ 0x00,
+ 0x40,
+ 0x00,
+ 0x40,
+ 0x00 };
+
+ TPSBuffer objIdBuff = new TPSBuffer(objid);
+
+ channel.createObject(objIdBuff, new TPSBuffer(perms), privKeyBlob.size());
+
+ channel.writeObject(objIdBuff, privKeyBlob);
+
+ TPSBuffer keyCheck = channel.getKeyCheck();
+
+ CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 : keyCheck: " + keyCheck.toHexString());
+
+ // String ivParams = ssKeyGenResponse.getIVParam();
+ CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8: ivParams: " + ivParams);
+ TPSBuffer ivParamsBuff = new TPSBuffer(Util.uriDecodeFromHex(ivParams));
+
+ if (ivParamsBuff.size() == 0) {
+ throw new TPSException("TPSEnrollProcessor.importPrivateKeyPKCS8: invalid iv vector!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+
+ }
+
+ TPSBuffer kekWrappedDesKey = channel.getKekDesKey();
+
+ if (kekWrappedDesKey != null)
+ CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: keyWrappedDesKey: " + kekWrappedDesKey.toHexString());
+ else
+ CMS.debug("TPSEnrollProcessor.iportPrivateKeyPKC8: null kekWrappedDesKey!");
+
+ byte alg = (byte) 0x80;
+ if (kekWrappedDesKey == null || kekWrappedDesKey.size() > 0) {
+ alg = (byte) 0x81;
+ }
+
+ TPSBuffer data = new TPSBuffer();
+
+ data.add(objIdBuff);
+ data.add(alg);
+ data.add((byte) kekWrappedDesKey.size());
+ data.add(kekWrappedDesKey);
+ data.add((byte) keyCheck.size());
+ data.add(keyCheck);
+ data.add((byte) ivParamsBuff.size());
+ data.add(ivParamsBuff);
+
+ int pe1 = (cEnrollInfo.getKeyUser() << 4) + cEnrollInfo.getPrivateKeyNumber();
+ int pe2 = (cEnrollInfo.getKeyUsage() << 4) + cEnrollInfo.getPublicKeyNumber();
+
+ channel.importKeyEnc(pe1, pe2, data);
+
+ CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8 successful, leaving...");
+
+ }
+
+ private String buildCertificateLabel(CertEnrollInfo cEnrollInfo, AppletInfo ainfo) throws TPSException {
+
+ CMS.debug("TPSEnrollProcessor.buildCertificateLabel");
+
+ if (cEnrollInfo == null) {
+ throw new TPSException("TPSErollProcessor.buildCertificateLabel: Invalid input params!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ String label = null;
+ String pattern = null;
+
+ String defaultLabel = cEnrollInfo.getKeyType() + " key for $userid$";
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String configValue = "op." + currentTokenOperation + "." + selectedTokenType + ".keyGen."
+ + cEnrollInfo.getKeyType() + ".label";
+
+ CMS.debug("TPSEnrollProcessor.buildCertificateLabel: label config: " + configValue);
+
+ try {
+ pattern = configStore.getString(
+ configValue, defaultLabel);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.buildCertificateLabel: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ Map<String, String> nv = new LinkedHashMap<String, String>();
+
+ nv.put("cuid", ainfo.getCUIDhexString());
+ nv.put("msn", ainfo.getMSNString());
+ nv.put("userid", userid);
+ nv.put("auth.cn", userid);
+ nv.put("profileId", getSelectedTokenType());
+
+ label = mapPattern((LinkedHashMap<String, String>) nv, pattern);
+
+ CMS.debug("TPSEnrollProcessor.buildCertificateLabel: returning: " + label);
+
+ return label;
+ }
+
+ /**
+ * Extracts information from the public key blob and verify proof.
+ *
+ * Muscle Key Blob Format (RSA Public Key)
+ * ---------------------------------------
+ *
+ * The key generation operation places the newly generated key into
+ * the output buffer encoding in the standard Muscle key blob format.
+ * For an RSA key the data is as follows:
+ *
+ * Byte Encoding (0 for plaintext)
+ *
+ * Byte Key Type (1 for RSA public)
+ *
+ * Short Key Length (1024 û high byte first)
+ *
+ * Short Modulus Length
+ *
+ * Byte[] Modulus
+ *
+ * Short Exponent Length
+ *
+ * Byte[] Exponent
+ *
+ *
+ * ECC KeyBlob Format (ECC Public Key)
+ * ----------------------------------
+ *
+ * Byte Encoding (0 for plaintext)
+ *
+ * Byte Key Type (10 for ECC public)
+ *
+ * Short Key Length (256, 384, 521 high byte first)
+ *
+ * Byte[] Key (W)
+ *
+ *
+ * Signature Format (Proof)
+ * ---------------------------------------
+ *
+ * The key generation operation creates a proof-of-location for the
+ * newly generated key. This proof is a signature computed with the
+ * new private key using the RSA-with-MD5 signature algorithm. The
+ * signature is computed over the Muscle Key Blob representation of
+ * the new public key and the challenge sent in the key generation
+ * request. These two data fields are concatenated together to form
+ * the input to the signature, without any other data or length fields.
+ *
+ * Byte[] Key Blob Data
+ *
+ * Byte[] Challenge
+ *
+ *
+ * Key Generation Result
+ * ---------------------------------------
+ *
+ * The key generation command puts the key blob and the signature (proof)
+ * into the output buffer using the following format:
+ *
+ * Short Length of the Key Blob
+ *
+ * Byte[] Key Blob Data
+ *
+ * Short Length of the Proof
+ *
+ * Byte[] Proof (Signature) Data
+ *
+ * @param blob the publickey blob to be parsed
+ * @param challenge the challenge generated by TPS
+ *
+ ******/
+ private RSAPublicKey parsePublicKeyBlob(
+ TPSBuffer public_key_blob,
+ /* TPSBuffer challenge,*/
+ boolean isECC)
+ throws TPSException {
+ RSAPublicKey parsedPubKey = null;
+
+ if (public_key_blob == null /*|| challenge == null*/) {
+ throw new TPSException(
+ "TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! Missing public_key_blob or challenge",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: public key blob from token to parse: "
+ + public_key_blob.toHexString());
+ /*
+ * decode blob into structures
+ */
+
+ // offset to the beginning of the public key length. should be 0
+ int pkeyb_len_offset = 0;
+
+ /*
+ * now, convert lengths
+ */
+ // 1st, keyblob length
+ /*
+ byte len0 = public_key_blob.at(pkeyb_len_offset);
+ byte len1 = public_key_blob.at(pkeyb_len_offset + 1);
+ int pkeyb_len = (len0 << 8) | (len1 & 0xFF);
+ */
+ int pkeyb_len = public_key_blob.getIntFrom2Bytes(pkeyb_len_offset);
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: pkeyb_len = " +
+ pkeyb_len + ", isECC: " + isECC);
+ // public key blob
+ TPSBuffer pkeyb = public_key_blob.substr(pkeyb_len_offset + 2, pkeyb_len);
+ if (pkeyb == null) {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: pkeyb null ");
+ throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! pkeyb null",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: pkeyb = "
+ + pkeyb.toHexString());
+
+ // 2nd, proof blob length
+ int proofb_len_offset = pkeyb_len_offset + 2 + pkeyb_len;
+ /*
+ len0 = public_key_blob.at(proofb_len_offset);
+ len1 = public_key_blob.at(proofb_len_offset + 1);
+ int proofb_len = (len0 << 8 | len1 & 0xFF);
+ */
+ int proofb_len = public_key_blob.getIntFrom2Bytes(proofb_len_offset);
+ // proof blob
+ TPSBuffer proofb = public_key_blob.substr(proofb_len_offset + 2, proofb_len);
+ if (proofb == null) {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: proofb null ");
+ throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! proofb null",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: proofb = "
+ + proofb.toHexString());
+
+ // convert pkeyb to pkey
+ // 1 byte encoding, 1 byte key type, 2 bytes key length, then the key
+ int pkey_offset = 4;
+ /*
+ len0 = pkeyb.at(pkey_offset);
+ len1 = pkeyb.at(pkey_offset + 1);
+ */
+ if (!isECC) {
+ // int mod_len = len0 << 8 | len1 & 0xFF;
+ int mod_len = pkeyb.getIntFrom2Bytes(pkey_offset);
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: mod_len= " + mod_len);
+ /*
+ len0 = pkeyb.at(pkey_offset + 2 + mod_len);
+ len1 = pkeyb.at(pkey_offset + 2 + mod_len + 1);
+ int exp_len = len0 << 8 | len1 & 0xFF;
+ */
+ int exp_len = pkeyb.getIntFrom2Bytes(pkey_offset + 2 + mod_len);
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: exp_len= " + exp_len);
+
+ TPSBuffer modb = pkeyb.substr(pkey_offset + 2, mod_len);
+ if (modb == null) {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: modb null ");
+ throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! modb null",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: modb= "
+ + modb.toHexString());
+ TPSBuffer expb = pkeyb.substr(pkey_offset + 2 + mod_len + 2, exp_len);
+
+ if (expb == null) {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: expb null ");
+ throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Bad input data! expb null",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: expb= "
+ + expb.toHexString());
+ BigInt modb_bi = new BigInt(modb.toBytesArray());
+ BigInt expb_bi = new BigInt(expb.toBytesArray());
+ try {
+ RSAPublicKey rsa_pub_key = new RSAPublicKey(modb_bi, expb_bi);
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: public key blob converted to RSAPublicKey");
+ if (rsa_pub_key != null) {
+ parsedPubKey = rsa_pub_key;
+ }
+ } catch (InvalidKeyException e) {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob:InvalidKeyException thrown");
+ throw new TPSException("TPSEnrollProcessor.parsePublicKeyBlob: Exception thrown: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ } else {
+ // TODO: handle ECC
+ }
+
+ // TODO: challenge verification
+
+ // sanity-check parsedPubKey before return
+ if (parsedPubKey == null) {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey null");
+ throw new TPSException(
+ "TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey null.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ } else {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey not null");
+ }
+ byte[] parsedPubKey_ba = parsedPubKey.getEncoded();
+ if (parsedPubKey_ba == null) {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey_ba null");
+ throw new TPSException(
+ "TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey encoding failure.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ } else {
+ CMS.debug("TPSEnrollProcessor.parsePublicKeyBlob: parsedPubKey getEncoded not null");
+ }
+
+ return parsedPubKey;
+ }
+
+ private boolean checkForServerSideKeyGen(CertEnrollInfo cInfo) throws TPSException {
+
+ if (cInfo == null) {
+ throw new TPSException("TPSEnrollProcessor.checkForServerSideKeyGen: invalid cert info.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ IConfigStore configStore = CMS.getConfigStore();
+ boolean serverSideKeygen = false;
+
+ try {
+ String configValue = cInfo.getKeyTypePrefix() + "." + TPSEngine.CFG_SERVER_KEYGEN_ENABLE;
+ CMS.debug("TPSEnrollProcessor.checkForServerSideKeyGen: config: " + configValue);
+ serverSideKeygen = configStore.getBoolean(
+ configValue, false);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.checkForServerSideKeyGen: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("TPSProcess.checkForServerSideKeyGen: returning: " + serverSideKeygen);
+
+ return serverSideKeygen;
+
+ }
+
+ private boolean checkForServerKeyArchival(CertEnrollInfo cInfo) throws TPSException {
+
+ if (cInfo == null) {
+ throw new TPSException("TPSEnrollProcessor.checkForServerKeyArchival: invalid cert info.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ IConfigStore configStore = CMS.getConfigStore();
+ boolean serverKeyArchival = false;
+
+ try {
+ String configValue = cInfo.getKeyTypePrefix() + "." + TPSEngine.CFG_SERVER_KEY_ARCHIVAL;
+ CMS.debug("TPSEnrollProcessor.checkForServerKeyArchival: config: " + configValue);
+ serverKeyArchival = configStore.getBoolean(
+ configValue, false);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.checkForServerKeyArchival: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("TPSProcess.checkForServerKeyArchival: returning: " + serverKeyArchival);
+
+ return serverKeyArchival;
+
+ }
+
+ private boolean checkForObjectOverwrite(CertEnrollInfo cInfo) throws TPSException {
+
+ if (cInfo == null) {
+ throw new TPSException("TPSEnrollProcessor.checkForObjectOverwrite: invalid cert info.",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+ IConfigStore configStore = CMS.getConfigStore();
+ boolean objectOverwrite = false;
+
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + getSelectedTokenType() + ".keyGen."
+ + cInfo.getKeyType() + "." + TPSEngine.CFG_OVERWRITE;
+
+ CMS.debug("TPSProcess.checkForObjectOverwrite: config: " + configValue);
+ objectOverwrite = configStore.getBoolean(
+ configValue, true);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.checkForServerSideKeyGen: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("TPSProcess.checkForObjectOverwrite: returning: " + objectOverwrite);
+
+ return objectOverwrite;
+
+ }
+
+ private String getConfiguredKeyType(int keyTypeIndex) throws TPSException {
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String keyType = null;
+
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "."
+ + TPSEngine.CFG_KEYGEN_KEYTYPE_VALUE + "." + keyTypeIndex;
+ keyType = configStore.getString(
+ configValue, null);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.getConfiguredKeyType: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ //We would really like one of these to exist
+
+ if (keyType == null) {
+ throw new TPSException(
+ "TPSEnrollProcessor.getConfiguredKeyType: Internal error finding config value: ",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ CMS.debug("TPSProcess.getConfiguredKeyType: returning: " + keyType);
+
+ return keyType;
+
+ }
+
+ private String getDRMConnectorID() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ String id = null;
+
+ String config = "op." + currentTokenOperation + "." + selectedTokenType + "." + TPSEngine.CFG_KEYGEN_ENCRYPTION
+ + "." + TPSEngine.CFG_DRM_CONNECTOR;
+
+ CMS.debug("TPSEnrollProcessor.getDRMConnectorID: config value: " + config);
+ try {
+ id = configStore.getString(config, "kra1");
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEnrollProcessor.getDRMConnectorID: Internal error finding config value.");
+
+ }
+
+ CMS.debug("TPSEnrollProcessor.getDRMConectorID: returning: " + id);
+
+ return id;
+ }
+
+ protected int getNumberCertsToEnroll() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ int keyTypeNum = 0;
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "."
+ + TPSEngine.CFG_KEYGEN_KEYTYPE_NUM;
+ keyTypeNum = configStore.getInteger(
+ configValue, 0);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEnrollProcessor.getNumberCertsToEnroll: Internal error finding config value: "
+ + e,
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+ }
+
+ if (keyTypeNum == 0) {
+ throw new TPSException(
+ "TPSEnrollProcessor.getNumberCertsToEnroll: invalid number of certificates configured!",
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+ CMS.debug("TPSProcess.getNumberCertsToEnroll: returning: " + keyTypeNum);
+
+ return keyTypeNum;
+ }
+
+ protected int getEnrollmentAlg() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ int enrollmentAlg;
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "."
+ + TPSEngine.CFG_KEYGEN_ENCRYPTION + "." + TPSEngine.CFG_ALG;
+
+ CMS.debug("TPSProcess.getEnrollmentAlg: configValue: " + configValue);
+
+ enrollmentAlg = configStore.getInteger(
+ configValue, 2);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEnrollProcessor.getEnrollmentAlg: Internal error finding config value: "
+ + e,
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+
+ }
+
+ CMS.debug("TPSProcess.getEnrollmentAlg: returning: " + enrollmentAlg);
+
+ return enrollmentAlg;
+ }
+
+ protected String getRecoveryKeyTypeValue(String reason, int index) throws TPSException {
+
+ if (reason == null || index < 0) {
+ throw new TPSException("TPSEnrollProcessor.getRecoveryKeyTypeValue: invalide input data!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String keyTypeValue;
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "." + TPSEngine.CFG_KEYGEN
+ + "."
+ + TPSEngine.RECOVERY_OP + "." + reason + "." + TPSEngine.CFG_KEYTYPE_VALUE + "." + index;
+ ;
+
+ CMS.debug("TPSProcess.getRecoveryKeyTypeValue: configValue: " + configValue);
+
+ keyTypeValue = configStore.getString(
+ configValue, null);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEnrollProcessor.getRecoveryKeyTypeValue: Internal error finding config value: "
+ + e,
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+
+ }
+
+ if (keyTypeValue == null) {
+ throw new TPSException("TPSEnrollProcessor.getRecoveryKeyTypeValue: Invalid keyTypeValue found! ",
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+
+ CMS.debug("TPSProcess.getRecoveryKeyTypeValue: returning: " + keyTypeValue);
+
+ return keyTypeValue;
+ }
+
+ protected String getRecoveryScheme(String reason, String keyTypeValue) throws TPSException {
+
+ if (reason == null || keyTypeValue == null) {
+ throw new TPSException("TPSEnrollProcessor.getRecoveryScheme: invalid input data!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String scheme = null;
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "." + TPSEngine.CFG_KEYGEN
+ + "." + keyTypeValue + "."
+ + TPSEngine.RECOVERY_OP + "." + reason + "." + TPSEngine.CFG_SCHEME;
+ ;
+
+ CMS.debug("TPSProcess.getRecoveryScheme: configValue: " + configValue);
+
+ scheme = configStore.getString(
+ configValue, null);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEnrollProcessor.getRecoveryScheme: Internal error finding config value: "
+ + e,
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+
+ }
+
+ if (scheme == null) {
+ throw new TPSException("TPSEnrollProcessor.getRecoverScheme: Invalid scheme found! ",
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+
+ CMS.debug("TPSProcess.getRecoveryScheme: returning: " + scheme);
+
+ return scheme;
+ }
+
+ protected int getNumberCertsForRecovery(String reason) throws TPSException {
+ if (reason == null) {
+ throw new TPSException("TPSEnrollProcessor.getNumberCertsForRecovery: invlalid input data!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+
+ IConfigStore configStore = CMS.getConfigStore();
+ int keyTypeNum = 0;
+ try {
+ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "." + TPSEngine.CFG_KEYGEN
+ + "." + TPSEngine.RECOVERY_OP
+ + "." + reason + "." + TPSEngine.CFG_KEYTYPE_NUM;
+
+ CMS.debug("TPSEnrollProcessor.getNumberCertsForRecovery: configValue: " + configValue);
+ keyTypeNum = configStore.getInteger(
+ configValue, 0);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSEnrollProcessor.getNumberCertsForRecovery: Internal error finding config value: "
+ + e,
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+
+ }
+
+ if (keyTypeNum == 0) {
+ throw new TPSException(
+ "TPSEnrollProcessor.getNumberCertsForRecovery: invalid number of certificates configured!",
+ TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
+ }
+ CMS.debug("TPSProcess.getNumberCertsForRecovery: returning: " + keyTypeNum);
+
+ return keyTypeNum;
+ }
+
+ protected String getCAConnectorID() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ String id = null;
+
+ String config = "op." + currentTokenOperation + "." + selectedTokenType + ".ca.conn";
+
+ try {
+ id = configStore.getString(config, "ca1");
+ } catch (EBaseException e) {
+ throw new TPSException("TPSEnrollProcessor.getCAConnectorID: Internal error finding config value.");
+
+ }
+
+ CMS.debug("TPSEnrollProcessor.getCAConectorID: returning: " + id);
+
+ return id;
+ }
+
+ private TPSBuffer makeKeyIDFromPublicKeyInfo(byte[] publicKeyInfo) throws TPSException {
+
+ final String alg = "SHA1";
+
+ if (publicKeyInfo == null) {
+ throw new TPSException("TPSEnrollProcessor.makeKeyIDFromPublicKeyInfo: invalid input data",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ TPSBuffer keyID = null;
+
+ byte[] mozillaDigestOut;
+
+ java.security.MessageDigest mozillaDigest;
+ try {
+ mozillaDigest = java.security.MessageDigest.getInstance(alg);
+ } catch (NoSuchAlgorithmException e) {
+ throw new TPSException("TPSEnrollProcessor.makeKeyIDFromPublicKeyInfo: " + e,
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ mozillaDigestOut = mozillaDigest.digest(publicKeyInfo);
+
+ if (mozillaDigestOut.length == mozillaDigest.getDigestLength()) {
+ System.out.println(mozillaDigest.getAlgorithm() + " " +
+ " digest output size is " + mozillaDigestOut.length);
+ } else {
+ throw new TPSException("ERROR: digest output size is " +
+ mozillaDigestOut.length + ", should be " +
+ mozillaDigest.getDigestLength(), TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ keyID = new TPSBuffer(mozillaDigestOut);
+
+ CMS.debug("TPSEnrollProcessor.makeKeyIDFromPublicKeyInfo: " + keyID.toHexString());
+
+ return keyID;
+ }
+
+ public BigInteger serialNoToBigInt(String serialS) {
+ if (serialS == null)
+ return new BigInteger("0", 16);
+
+ CMS.debug("TPSEnrollProcessor.seralNoToBigInt: serial # =" + serialS);
+ String serialhex = serialS.substring(2); // strip off the "0x"
+ BigInteger serialBI = new BigInteger(serialhex, 16);
+
+ return serialBI;
+ }
+
+ public static void main(String[] args) {
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
new file mode 100644
index 000000000..b92cd8b91
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java
@@ -0,0 +1,66 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.processor;
+
+import java.io.IOException;
+
+import org.dogtagpki.server.tps.TPSSession;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.BeginOpMsg;
+import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+
+import com.netscape.certsrv.apps.CMS;
+
+public class TPSPinResetProcessor extends TPSProcessor {
+
+ public TPSPinResetProcessor(TPSSession session) {
+ super(session);
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public void process(BeginOpMsg beginMsg) throws TPSException, IOException {
+ if (beginMsg == null) {
+ throw new TPSException("TPSPinResetProcessor.process: invalid input data, not beginMsg provided.",
+ TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+ }
+ setBeginMessage(beginMsg);
+ setCurrentTokenOperation("pinReset");
+
+ resetPin();
+
+ }
+
+ private void resetPin() throws TPSException {
+
+ //ToDo: Implement full pin reset processor, the pin reset portion
+ // of an enrollment works fine. We just need to finish this to perform
+ // a completely stand alone pin reset of an already enrolled token.
+ CMS.debug("TPSPinResetProcessor.resetPin: entering...");
+
+ throw new TPSException("TPSPinResetProcessor.resetPin: Pin Reset standalone operation not yet supported!",
+ TPSStatus.STATUS_ERROR_MAC_RESET_PIN_PDU);
+
+ }
+
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
new file mode 100644
index 000000000..e23cea0ad
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java
@@ -0,0 +1,2404 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.processor;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import netscape.security.x509.RevocationReason;
+
+import org.dogtagpki.server.tps.TPSSession;
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.authentication.AuthUIParameter;
+import org.dogtagpki.server.tps.authentication.TPSAuthenticator;
+import org.dogtagpki.server.tps.channel.SecureChannel;
+import org.dogtagpki.server.tps.cms.CARemoteRequestHandler;
+import org.dogtagpki.server.tps.cms.CARevokeCertResponse;
+import org.dogtagpki.server.tps.cms.TKSComputeRandomDataResponse;
+import org.dogtagpki.server.tps.cms.TKSComputeSessionKeyResponse;
+import org.dogtagpki.server.tps.cms.TKSEncryptDataResponse;
+import org.dogtagpki.server.tps.cms.TKSRemoteRequestHandler;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
+import org.dogtagpki.server.tps.dbs.TPSCertRecord;
+import org.dogtagpki.server.tps.dbs.TokenRecord;
+import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.server.tps.profile.BaseTokenProfileResolver;
+import org.dogtagpki.server.tps.profile.TokenProfileParams;
+import org.dogtagpki.tps.apdu.APDU;
+import org.dogtagpki.tps.apdu.APDUResponse;
+import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel;
+import org.dogtagpki.tps.apdu.GetDataAPDU;
+import org.dogtagpki.tps.apdu.GetStatusAPDU;
+import org.dogtagpki.tps.apdu.GetVersionAPDU;
+import org.dogtagpki.tps.apdu.InitializeUpdateAPDU;
+import org.dogtagpki.tps.apdu.ListObjectsAPDU;
+import org.dogtagpki.tps.apdu.SelectAPDU;
+import org.dogtagpki.tps.main.TPSBuffer;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.BeginOpMsg;
+import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+import org.dogtagpki.tps.msg.ExtendedLoginRequestMsg;
+import org.dogtagpki.tps.msg.ExtendedLoginResponseMsg;
+import org.dogtagpki.tps.msg.LoginRequestMsg;
+import org.dogtagpki.tps.msg.LoginResponseMsg;
+import org.dogtagpki.tps.msg.NewPinRequestMsg;
+import org.dogtagpki.tps.msg.NewPinResponseMsg;
+import org.dogtagpki.tps.msg.StatusUpdateRequestMsg;
+import org.dogtagpki.tps.msg.TPSMessage;
+import org.dogtagpki.tps.msg.TokenPDURequestMsg;
+import org.dogtagpki.tps.msg.TokenPDUResponseMsg;
+import org.mozilla.jss.CryptoManager.NotInitializedException;
+import org.mozilla.jss.pkcs11.PK11SymKey;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.authentication.IAuthCredentials;
+import com.netscape.certsrv.authentication.IAuthManager;
+import com.netscape.certsrv.authentication.IAuthToken;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.tps.token.TokenStatus;
+import com.netscape.symkey.SessionKey;
+
+public class TPSProcessor {
+
+ public static final int RESULT_NO_ERROR = 0;
+ public static final int RESULT_ERROR = -1;
+
+ public static final int CPLC_DATA_SIZE = 47;
+ public static final int CPLC_MSN_INDEX = 41;
+ public static final int CPLC_MSN_SIZE = 4;
+
+ public static final int INIT_UPDATE_DATA_SIZE = 28;
+ public static final int DIVERSIFICATION_DATA_SIZE = 10;
+ public static final int CARD_CRYPTOGRAM_OFFSET = 20;
+ public static final int CARD_CRYPTOGRAM_SIZE = 8;
+ public static final int CARD_CHALLENGE_OFFSET = 12;
+ public static final int CARD_CHALLENGE_SIZE = 8;
+
+ protected boolean isExternalReg;
+
+ protected TPSSession session;
+ //protected TokenRecord tokenRecord;
+ protected String selectedTokenType;
+
+ protected String userid = null;
+ protected String currentTokenOperation;
+
+ protected BeginOpMsg beginMsg;
+
+ public TPSProcessor(TPSSession session) {
+ setSession(session);
+ }
+
+ protected void setCurrentTokenOperation(String op) {
+ currentTokenOperation = op;
+ }
+
+ protected void setSession(TPSSession session) {
+ if (session == null) {
+ throw new NullPointerException("TPS session is null");
+ }
+ this.session = session;
+ }
+
+ protected TPSSession getSession() {
+ return session;
+ }
+
+ protected TokenRecord getTokenRecord() {
+ TPSSession session = getSession();
+ return session.getTokenRecord();
+ }
+
+ protected void setBeginMessage(BeginOpMsg msg) {
+ beginMsg = msg;
+ }
+
+ public BeginOpMsg getBeginMessage() {
+ return beginMsg;
+ }
+
+ protected void setSelectedTokenType(String theTokenType) {
+
+ if (theTokenType == null) {
+ throw new NullPointerException("TPSProcessor.setSelectedTokenType: Attempt to set invalid null token type!");
+ }
+ CMS.debug("TPS_Processor.setSelectedTokenType: tokenType=" +
+ theTokenType);
+ selectedTokenType = theTokenType;
+
+ TokenRecord tokenRecord = getTokenRecord();
+ tokenRecord.setType(selectedTokenType);
+ }
+
+ public String getSelectedTokenType() {
+ return selectedTokenType;
+ }
+
+ protected TPSBuffer extractTokenMSN(TPSBuffer cplc_data) throws TPSException {
+ //Just make sure no one is inputing bogus cplc_data
+ if (cplc_data == null || cplc_data.size() < CPLC_DATA_SIZE) {
+ throw new TPSException("TPSProcessor.extractTokenMSN: Can't extract token msn from cplc data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ TPSBuffer token_msn = cplc_data.substr(CPLC_MSN_INDEX, CPLC_MSN_SIZE);
+ return token_msn;
+
+ }
+
+ protected TPSBuffer extractTokenCUID(TPSBuffer cplc_data) throws TPSException {
+ //Just make sure no one is inputing bogus cplc_data
+ if (cplc_data == null || cplc_data.size() < CPLC_DATA_SIZE) {
+ CMS.debug("TPS_Processor.extractTokenCUID: cplc_data: invalid length.");
+ throw new TPSException("TPSProcessor.extractTokenCUID: Can't extract cuid from cplc data!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ TPSBuffer token1 = cplc_data.substr(3, 4);
+ TPSBuffer token2 = cplc_data.substr(19, 2);
+ TPSBuffer token3 = cplc_data.substr(15, 4);
+
+ TPSBuffer token_cuid = new TPSBuffer();
+
+ token_cuid.add(token1);
+ token_cuid.add(token2);
+ token_cuid.add(token3);
+
+ return token_cuid;
+
+ }
+
+ /**
+ * Select applet.
+ *
+ * Global Platform Open Platform Card Specification
+ * Version 2.0.1 Page 9-22
+ *
+ * Sample Data:
+ *
+ * _____________ CLA
+ * | __________ INS
+ * | | _______ P1
+ * | | | ____ P2
+ * | | | | _ Len
+ * | | | | |
+ * 00 A4 04 00 07
+ * 53 4C 42 47 49 4E 41
+ *
+ * @throws IOException
+ * @throws TPSException
+ *
+ */
+
+ protected APDUResponse selectApplet(byte p1, byte p2, TPSBuffer aid) throws IOException, TPSException {
+
+ CMS.debug("In TPS_Processor.SelectApplet.");
+
+ if (aid == null || aid.size() == 0) {
+ throw new TPSException("TPSProcessor.selectApplet: Invalid aid value!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ SelectAPDU select_apdu = new SelectAPDU(p1, p2, aid);
+
+ //return the Response because the caller can
+ //decide what to do, not every failure is fatal.
+ //For instance the coolkey applet may not yet exist.
+ return handleAPDURequest(select_apdu);
+
+ }
+
+ protected TPSBuffer getStatus() throws IOException, TPSException {
+
+ CMS.debug("In TPS_Processor.GetStatus.");
+
+ GetStatusAPDU get_status_apdu = new GetStatusAPDU();
+
+ return handleAPDURequest(get_status_apdu).getData();
+ }
+
+ public APDUResponse handleAPDURequest(APDU apdu) throws IOException, TPSException {
+
+ if (apdu == null) {
+ throw new TPSException("TPSProcessor.handleAPDURequest: invalid incoming apdu!");
+ }
+
+ TokenPDURequestMsg request_msg = new TokenPDURequestMsg(apdu);
+
+ try {
+ session.write(request_msg);
+ } catch (IOException e) {
+ CMS.debug("TPS_Processor.HandleAPDURequest failed WriteMsg: " + e.toString());
+ throw e;
+
+ }
+
+ TokenPDUResponseMsg response_msg = null;
+
+ try {
+ response_msg = (TokenPDUResponseMsg) session.read();
+ } catch (IOException e) {
+ CMS.debug("TPS_Processor.HandleAPDURequest failed ReadMsg: " + e.toString());
+ throw e;
+
+ }
+
+ return response_msg.getResponseAPDU();
+ }
+
+ protected TPSBuffer getCplcData() throws IOException, TPSException {
+ CMS.debug("In TPS_Processor.GetData");
+
+ GetDataAPDU get_data_apdu = new GetDataAPDU();
+
+ APDUResponse respApdu = handleAPDURequest(get_data_apdu);
+
+ if (!respApdu.checkResult()) {
+ throw new TPSException("TPSProcessor.getCplcData: Can't get data!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+ TPSBuffer cplcData = respApdu.getData();
+
+ if (cplcData.size() != CPLC_DATA_SIZE) {
+ throw new TPSException("TPSProcessor.cplcData: Data invalid size!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ return respApdu.getData();
+ }
+
+ protected TPSBuffer getAppletVersion() throws IOException, TPSException {
+ //We return null if no applet present
+ // This is not an error, the token can be blank.
+
+ CMS.debug("In TPSProcessor.getAppletVersion");
+
+ GetVersionAPDU get_version_apdu = new GetVersionAPDU();
+
+ APDUResponse respApdu = handleAPDURequest(get_version_apdu);
+
+ if (!respApdu.checkResult()) {
+ CMS.debug("TPSProcessor.getAppletVersion: No applet version found on card!");
+ return null;
+ }
+
+ TPSBuffer apdu_data = respApdu.getData();
+
+ if (apdu_data.size() != 6) {
+ CMS.debug("TPSProcessor.getAppletVersion: incorrect return data size!");
+ throw new TPSException("TPSProcessor.getAppletVersion: invalid applet version string returned!");
+ }
+
+ TPSBuffer build_id = apdu_data.substr(0, 4);
+
+ CMS.debug("TPSProcessor.getAppletVersion: returning: " + build_id.toHexString());
+
+ return build_id;
+
+ }
+
+ protected TPSBuffer encryptData(AppletInfo appletInfo, TPSBuffer keyInfo, TPSBuffer plaintextChallenge,
+ String connId) throws TPSException {
+
+ TKSRemoteRequestHandler tks = null;
+
+ TKSEncryptDataResponse data = null;
+
+ try {
+ tks = new TKSRemoteRequestHandler(connId);
+ data = tks.encryptData(appletInfo.getCUID(), keyInfo, plaintextChallenge);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.encryptData: Erorr getting wrapped data from TKS!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ int status = data.getStatus();
+
+ if (status != 0) {
+ throw new TPSException("TPSProcessor.computeRandomData: Erorr getting wrapped data from TKS!",
+ TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU);
+ }
+
+ return data.getEncryptedData();
+ }
+
+ TPSBuffer computeRandomData(int dataSize, String connId) throws TPSException {
+
+ TKSRemoteRequestHandler tks = null;
+
+ TKSComputeRandomDataResponse data = null;
+
+ try {
+ tks = new TKSRemoteRequestHandler(connId);
+ data = tks.computeRandomData(dataSize);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.computeRandomData: Erorr getting random data from TKS!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ int status = data.getStatus();
+
+ if (status != 0) {
+ throw new TPSException("TPSProcessor.computeRandomData: Erorr getting random data from TKS!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ return data.getRandomData();
+ }
+
+ protected TPSBuffer initializeUpdate(byte keyVersion, byte keyIndex, TPSBuffer randomData) throws IOException,
+ TPSException {
+
+ CMS.debug("In TPS_Processor.initializeUpdate.");
+ InitializeUpdateAPDU initUpdate = new InitializeUpdateAPDU(keyVersion, keyIndex, randomData);
+
+ APDUResponse resp = handleAPDURequest(initUpdate);
+
+ if (!resp.checkResult()) {
+ CMS.debug("TPSProcessor.initializeUpdate: Failed intializeUpdate!");
+ throw new TPSException("TPSBuffer.initializeUpdate: Failed initializeUpdate!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+ }
+
+ TPSBuffer data = resp.getResultDataNoCode();
+
+ if (data.size() != INIT_UPDATE_DATA_SIZE) {
+ throw new TPSException("TPSBuffer.initializeUpdate: Invalid response from token!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ return data;
+
+ }
+
+ protected SecureChannel setupSecureChannel() throws TPSException, IOException {
+ SecureChannel channel = null;
+
+ //Create a standard secure channel with current key set.
+ CMS.debug("TPSProcessor.setupSecureChannel: No arguments entering...");
+
+ int defKeyVersion = getChannelDefKeyVersion();
+ int defKeyIndex = getChannelDefKeyIndex();
+
+ channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, SecurityLevel.SECURE_MSG_MAC_ENC,
+ getTKSConnectorID());
+
+ channel.externalAuthenticate();
+
+ return channel;
+ }
+
+ protected SecureChannel setupSecureChannel(byte keyVersion, byte keyIndex, SecurityLevel securityLevel,
+ String connId)
+ throws IOException, TPSException {
+
+ //Assume generating host challenge on TKS, we no longer support not involving the TKS.
+
+ TPSBuffer randomData = computeRandomData(8, connId);
+ CMS.debug("TPSProcessor.setupSecureChannel: obtained randomData: " + randomData.toHexString());
+
+ TPSBuffer initUpdateResp = initializeUpdate(keyVersion, keyIndex, randomData);
+
+ TPSBuffer key_diversification_data = initUpdateResp.substr(0, DIVERSIFICATION_DATA_SIZE);
+ CMS.debug("TPSProcessor.setupSecureChannel: diversification data: " + key_diversification_data.toHexString());
+
+ TPSBuffer key_info_data = initUpdateResp.substr(DIVERSIFICATION_DATA_SIZE, 2);
+ CMS.debug("TPSProcessor.setupSecureChannel: key info data: " + key_info_data.toHexString());
+
+ TokenRecord tokenRecord = getTokenRecord();
+ tokenRecord.setKeyInfo(key_info_data.toHexStringPlain());
+
+ TPSBuffer card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET, CARD_CRYPTOGRAM_SIZE);
+ CMS.debug("TPSProcessor.setupSecureChannel: card cryptogram: " + card_cryptogram.toHexString());
+
+ TPSBuffer card_challenge = initUpdateResp.substr(CARD_CHALLENGE_OFFSET, CARD_CHALLENGE_SIZE);
+ CMS.debug("TPSProcessor.setupSecureChannel: card challenge: " + card_challenge.toHexString());
+
+ SecureChannel channel = null;
+
+ try {
+ channel = generateSecureChannel(connId, key_diversification_data, key_info_data, card_challenge,
+ card_cryptogram,
+ randomData);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.setupSecureChannel: Can't set up secure channel: " + e,
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ return channel;
+
+ }
+
+ protected SecureChannel generateSecureChannel(String connId, TPSBuffer keyDiversificationData,
+ TPSBuffer keyInfoData, TPSBuffer cardChallenge, TPSBuffer cardCryptogram, TPSBuffer hostChallenge)
+ throws EBaseException, TPSException {
+
+ CMS.debug("TPSProcessor.generateSecureChannel: entering..");
+
+ TPSEngine engine = getTPSEngine();
+
+ SecureChannel channel = null;
+ TPSBuffer hostCryptogram = null;
+
+ TKSComputeSessionKeyResponse resp = engine.computeSessionKey(keyDiversificationData, keyInfoData,
+ cardChallenge, hostChallenge, cardCryptogram,
+ connId, getSelectedTokenType());
+
+ hostCryptogram = resp.getHostCryptogram();
+
+ if (hostCryptogram == null) {
+ new TPSException("TPSProcessor.generateSecureChannel: No host cryptogram returned from token!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+ }
+
+ PK11SymKey sharedSecret = null;
+
+ try {
+ sharedSecret = getSharedSecretTransportKey(connId);
+ } catch (Exception e) {
+ CMS.debug(e);
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't get shared secret key!: " + e,
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ PK11SymKey sessionKey = null;
+ PK11SymKey encSessionKey = null;
+ String tokenName = "Internal Key Storage Token";
+
+ try {
+ TPSBuffer sessionKeyWrapped = resp.getSessionKey();
+ TPSBuffer encSessionKeyWrapped = resp.getEncSessionKey();
+
+ sessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+ sessionKeyWrapped.toBytesArray());
+
+ if (sessionKey == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't extract session key!");
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract session key!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+ CMS.debug("TPSProcessor.generateSecureChannel: retrieved session key: " + sessionKey);
+
+ encSessionKey = SessionKey.UnwrapSessionKeyWithSharedSecret(tokenName, sharedSecret,
+ encSessionKeyWrapped.toBytesArray());
+
+ if (encSessionKey == null) {
+ CMS.debug("TPSProcessor.generateSecureChannel: Can't extract enc session key!");
+ throw new TPSException("TPSProcessor.generateSecureChannel: Can't extract enc session key!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ CMS.debug("TPSProcessor.generateSecureChannel: retrieved enc session key: " + encSessionKey);
+ } catch (Exception e) {
+ CMS.debug(e);
+ e.printStackTrace();
+ throw new TPSException("TPSProcessor.generateSecureChannel: Problem extracting session keys! " + e,
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ TPSBuffer drmDesKey = null;
+ TPSBuffer kekDesKey = null;
+ TPSBuffer keyCheck = null;
+
+ drmDesKey = resp.getDRM_Trans_DesKey();
+ keyCheck = resp.getKeyCheck();
+ kekDesKey = resp.getKekWrappedDesKey();
+
+ if (checkServerSideKeyGen(connId)) {
+
+ CMS.debug("TPSProcessor.generateSecureChannel: drmDesKey: " + drmDesKey + " kekDesKey : " + kekDesKey
+ + " keyCheck: " + keyCheck);
+ //ToDo handle server side keygen.
+
+ }
+ channel = new SecureChannel(this, sessionKey, encSessionKey, drmDesKey,
+ kekDesKey, keyCheck, keyDiversificationData, cardChallenge,
+ cardCryptogram, hostChallenge, hostCryptogram, keyInfoData);
+
+ return channel;
+ }
+
+ protected void upgradeApplet(String operation, String new_version, SecurityLevel securityLevel,
+ Map<String, String> extensions, String connId, int startProgress, int endProgress) throws IOException,
+ TPSException {
+
+ TPSBuffer netkeyAIDBuff = null;
+ TPSBuffer cardMgrAIDBuff = null;
+ TPSBuffer netkeyPAIDBuff = null;
+
+ netkeyAIDBuff = getNetkeyAID();
+ netkeyPAIDBuff = getNetkeyPAID();
+ cardMgrAIDBuff = getCardManagerAID();
+
+ int channelBlockSize = getChannelBlockSize();
+ int channelInstanceSize = getChannelInstanceSize();
+ int channelAppletMemSize = getAppletMemorySize();
+ int defKeyVersion = getChannelDefKeyVersion();
+ int defKeyIndex = getChannelDefKeyIndex();
+
+ byte[] appletData = null;
+
+ TokenRecord tokenRecord = getTokenRecord();
+
+ String directory = getAppletDirectory(operation);
+
+ CMS.debug("TPSProcessor.upgradeApplet: applet target directory: " + directory);
+
+ String appletFileExt = getAppletExtension();
+
+ String appletFilePath = directory + "/" + new_version + "." + appletFileExt;
+
+ CMS.debug("TPSProcessor.upgradeApplet: targe applet file name: " + appletFilePath);
+
+ appletData = getAppletFileData(appletFilePath);
+
+ APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, cardMgrAIDBuff);
+
+ if (!select.checkResult()) {
+ throw new TPSException("TPSProcessor.upgradeApplet: Can't selelect the card manager!");
+ }
+
+ SecureChannel channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, securityLevel, connId);
+
+ channel.externalAuthenticate();
+ channel.deleteFileX(netkeyAIDBuff);
+ channel.deleteFileX(netkeyPAIDBuff);
+
+ // Next step will be to load the applet file to token.
+
+ TPSBuffer empty = new TPSBuffer();
+
+ channel.installLoad(netkeyPAIDBuff, empty, appletData.length);
+
+ TPSBuffer appletDataBuff = new TPSBuffer(appletData);
+
+ channel.loadFile(appletDataBuff, channelBlockSize, startProgress, endProgress);
+
+ channel.installApplet(netkeyPAIDBuff, netkeyAIDBuff, (byte) 0, channelInstanceSize, channelAppletMemSize);
+
+ //Now select our new applet
+
+ select = selectApplet((byte) 0x04, (byte) 0x00, netkeyAIDBuff);
+
+ if (!select.checkResult()) {
+ throw new TPSException("TPSProcessor.upgradeApplet: Cannot select newly created applet!",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+ tokenRecord.setAppletID(new_version);
+
+ }
+
+ public void selectCoolKeyApplet() throws TPSException, IOException {
+
+ TPSBuffer netkeyAIDBuff = getNetkeyAID();
+
+ APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, netkeyAIDBuff);
+
+ if (!select.checkResult()) {
+ CMS.debug("TPSProcessor.selectCoolKeyApplet: Can't select coolkey, token may be blank.");
+ /* throw new TPSException("TPSProcessor.upgradeApplet: Cannot select newly created applet!",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ */
+ }
+ }
+
+ protected byte[] getAppletFileData(String appletFilePath) throws IOException, TPSException {
+
+ if (appletFilePath == null) {
+ throw new TPSException("TPSProcessor.getAppletFileData: Invalid applet file name.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ byte[] contents = null;
+ try {
+ Path path = Paths.get(appletFilePath);
+ contents = Files.readAllBytes(path);
+
+ } catch (IOException e) {
+ CMS.debug("TPSProcessor.getAppletFileData: IOException " + e);
+ throw e;
+ } catch (Exception e) {
+ CMS.debug("PSProcessor.getAppletFileData: Exception: " + e);
+ throw new TPSException("TPSProcessor.getAppletFileData: Exception: " + e,
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ CMS.debug("TPSProcessor.getAppletFileData: data: " + contents);
+
+ return contents;
+ }
+
+ /**
+ * getAuthentication gets Authentication per configuration
+ *
+ * @param prefix config prefix for tokenType
+ * @param tokenType the tokenType(profile)
+ * @return Authentication
+ */
+ public TPSAuthenticator getAuthentication(String prefix, String tokenType)
+ throws EBaseException {
+ CMS.debug("TPSProcessor.getAuthentication");
+ String auditMsg = null;
+
+ if (prefix.isEmpty() || tokenType.isEmpty()) {
+ auditMsg = "TPSProcessor.getAuthentication: missing parameters: prefix or tokenType";
+ CMS.debug(auditMsg);
+ throw new EBaseException(auditMsg);
+ }
+ IConfigStore configStore = CMS.getConfigStore();
+ String configName = prefix + "." + tokenType + ".auth.id";
+ String authId;
+
+ CMS.debug("TPSProcessor.getAuthentication: getting config: " +
+ configName);
+ authId = configStore.getString(configName);
+ if (authId == null) {
+ auditMsg = "TPSProcessor.getAuthentication: config param not found:" + configName;
+ CMS.debug(auditMsg);
+ throw new EBaseException(auditMsg);
+ }
+
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ TPSAuthenticator authInst =
+ subsystem.getAuthenticationManager().getAuthInstance(authId);
+ String authCredNameConf = "auths.instance." + authId + ".authCredName";
+ CMS.debug("TPSProcessor.getAuthentication: getting config: " +
+ authCredNameConf);
+ String authCredName = configStore.getString(authCredNameConf);
+ if (authCredName == null) {
+ auditMsg = "TPSProcessor.getAuthentication: config param not found:" + authCredNameConf;
+ CMS.debug(auditMsg);
+ throw new EBaseException(auditMsg);
+ }
+ authInst.setAuthCredName(authCredName);
+ return authInst;
+ }
+
+ /**
+ * authenticateUser authenticates a user using specified authentication
+ *
+ * @param op "enrollment", "format", or "pinReset" //TODO: for tokendb activity log
+ * @param userAuth the authenticator
+ * @param userCred IAuthCredentials obtained from a successful requestUserId call
+ * @return IAuthToken information relating to the performed authentication
+ * -- plugin-specific
+ */
+ public IAuthToken authenticateUser(
+ String op,
+ TPSAuthenticator userAuth,
+ IAuthCredentials userCred)
+ throws EBaseException, TPSException {
+ /**
+ * TODO: isExternalReg is not handled until decision made
+ */
+ String auditMsg = null;
+ CMS.debug("TPSProcessor.authenticateUser");
+ if (op.isEmpty() || userAuth == null || userCred == null) {
+ auditMsg = "TPSProcessor.authenticateUser: missing parameter(s): op, userAuth, or userCred";
+ CMS.debug(auditMsg);
+ throw new EBaseException(auditMsg);
+ }
+ IAuthManager auth = userAuth.getAuthManager();
+
+ try {
+ // Authenticate user
+ IAuthToken aToken = auth.authenticate(userCred);
+ if (aToken != null) {
+ CMS.debug("TPSProcessor.authenticateUser: authentication success");
+ return aToken;
+ } else {
+ CMS.debug("TPSProcessor.authenticateUser: authentication failure with aToken null");
+ throw new TPSException("TPS error user authentication failed.",
+ TPSStatus.STATUS_ERROR_LOGIN);
+ }
+ } catch (EBaseException e) {
+ CMS.debug("TPSProcessor.authenticateUser: authentication failure:" + e);
+ throw new TPSException("TPS error user authentication failed.",
+ TPSStatus.STATUS_ERROR_LOGIN);
+ }
+ }
+
+ /**
+ * requestUserId sends message to client to request for user credential
+ * per authentication plugin
+ *
+ * @param op "enrollment", "format", or "pinReset" //TODO: for tokendb activity log
+ * @param cuid token CUID //TODO: for tokendb activity log
+ * @param extensions message extensions
+ * @return IAuthCredentials containing user credential needed for authentication
+ */
+ IAuthCredentials requestUserId(String op, String cuid, TPSAuthenticator auth, Map<String, String> extensions)
+ throws IOException, TPSException, EBaseException {
+ CMS.debug("TPSProcessor.requestUserId");
+ if (op.isEmpty() ||
+ cuid.isEmpty() || auth == null) {
+ CMS.debug("TPSProcessor.requestUserId: missing parameter(s): op, cuid, or auth");
+ throw new EBaseException("TPSProcessor.requestUserId: missing parameter(s): op, cuid, or auth");
+ }
+
+ IAuthCredentials login;
+ if (extensions != null &&
+ extensions.get("extendedLoginRequest") != null) {
+ // default locale will be "en"
+ String locale = extensions.get("locale");
+ if (extensions.get("locale") == null) {
+ locale = "en";
+ }
+ // title
+ String title = auth.getUiTitle(locale);
+ if (title.isEmpty())
+ title = auth.getUiTitle("en");
+ // description
+ String description = auth.getUiDescription(locale);
+ if (description.isEmpty())
+ description = auth.getUiTitle("en");
+ // parameters
+ HashMap<String, AuthUIParameter> authParamSet = auth.getUiParamSet();
+ Set<String> params = new HashSet<String>();
+ for (Map.Entry<String, AuthUIParameter> entry : authParamSet.entrySet()) {
+ params.add(auth.getUiParam(entry.getKey()).toString(locale));
+ CMS.debug("TPSProcessor.requestUserId: for extendedLoginRequest, added param: " +
+ auth.getUiParam(entry.getKey()).toString(locale));
+ }
+
+ login = requestExtendedLogin(0 /* invalid_pw */, 0 /* blocked */,
+ params, title, description, auth);
+ } else {
+ login = requestLogin(0 /* invalid_pw */, 0 /* blocked */, auth);
+ }
+
+ return login;
+ }
+
+ /**
+ * mapCredFromMsgResponse fills up authManager required auth credentials
+ * with mapped values from client
+ * configuration example:
+ *
+ * auths.instance.ldap1.ui.id.UID.credMap.msgCred.extlogin=UID
+ * auths.instance.ldap1.ui.id.UID.credMap.msgCred.login=screen_name
+ * auths.instance.ldap1.ui.id.UID.credMap.authCred=uid
+ *
+ * auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred.extlogin=PASSWORD
+ * auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred.login=password
+ * auths.instance.ldap1.ui.id.PASSWORD.credMap.authCred=pwd
+ *
+ * @param response the message response to be mapped
+ * @param auth the authentication for mapping consultation
+ * @return IAuthCredentials auth credential for auth manager
+ */
+ public IAuthCredentials mapCredFromMsgResponse(TPSMessage response, TPSAuthenticator auth, boolean extendedLogin)
+ throws EBaseException {
+ CMS.debug("TPSProcessor.mapCredFromMsgResponse");
+ if (response == null || auth == null) {
+ CMS.debug("TPSProcessor.mapCredFromMsgResponse: missing parameter(s): response or auth");
+ throw new EBaseException("TPSProcessor.mapCredFromMsgResponse: missing parameter(s): response or auth");
+ }
+ IAuthCredentials login =
+ new com.netscape.certsrv.authentication.AuthCredentials();
+
+ String[] requiredCreds = auth.getAuthManager().getRequiredCreds();
+ for (String cred : requiredCreds) {
+ String name = auth.getCredMap(cred, extendedLogin);
+ CMS.debug("TPSProcessor.mapCredFromMsgResponse: cred=" + cred + " &name=" +
+ name);
+ login.set(cred, response.get(name));
+ }
+
+ return login;
+ }
+
+ /**
+ * Requests login ID and password from user.
+ */
+ public IAuthCredentials requestExtendedLogin(int invalidPW, int blocked,
+ Set<String> parameters,
+ String title,
+ String description,
+ TPSAuthenticator auth)
+ throws IOException, TPSException, EBaseException {
+
+ CMS.debug("TPSProcessor.requestExtendedLogin");
+ if (parameters == null || title.isEmpty() ||
+ description.isEmpty() || auth == null) {
+ CMS.debug("TPSProcessor.requestExtendedLogin: missing parameter(s): parameters, title, description, or auth");
+ throw new EBaseException(
+ "TPSProcessor.requestExtendedLogin: missing parameter(s): parameters, title, description, or auth");
+ }
+ ExtendedLoginRequestMsg loginReq =
+ new ExtendedLoginRequestMsg(invalidPW, blocked, parameters, title, description);
+
+ try {
+ session.write(loginReq);
+ } catch (IOException e) {
+ CMS.debug("TPSProcessor.requestExtendedLogin failed WriteMsg: " + e.toString());
+ throw e;
+ }
+ CMS.debug("TPSProcessor.requestExtendedLogin: extendedLoginRequest sent");
+
+ ExtendedLoginResponseMsg loginResp = null;
+ try {
+ loginResp = (ExtendedLoginResponseMsg) session.read();
+ } catch (IOException e) {
+ CMS.debug("TPSProcessor.requestExtendedLogin failed ReadMsg: " + e.toString());
+ throw e;
+ }
+
+ IAuthCredentials login = mapCredFromMsgResponse(loginResp, auth, true /*extendedLogin*/);
+
+ return login;
+ }
+
+ /**
+ * Requests login ID and password from user.
+ */
+ public IAuthCredentials requestLogin(int invalidPW, int blocked,
+ TPSAuthenticator auth)
+ throws IOException, TPSException, EBaseException {
+
+ CMS.debug("TPSProcessor.requestLogin");
+ if (auth == null) {
+ CMS.debug("TPSProcessor.requestLogin: missing parameter(s): parameters, title, description, or auth");
+ throw new EBaseException(
+ "TPSProcessor.requestLogin: missing parameter(s): parameters, title, description, or auth");
+ }
+ LoginRequestMsg loginReq = new LoginRequestMsg(invalidPW, blocked);
+
+ try {
+ session.write(loginReq);
+ } catch (IOException e) {
+ CMS.debug("TPSProcessor.requestLogin failed WriteMsg: " + e.toString());
+ throw e;
+ }
+ CMS.debug("TPSProcessor.requestLogin: loginRequest sent");
+
+ LoginResponseMsg loginResp = null;
+ try {
+ loginResp = (LoginResponseMsg) session.read();
+ } catch (IOException e) {
+ CMS.debug("TPSProcessor.requestLogin failed ReadMsg: " + e.toString());
+ throw e;
+ }
+
+ IAuthCredentials login = mapCredFromMsgResponse(loginResp, auth, false /*not extendedLogin*/);
+ return login;
+ }
+
+ /*
+ * fillTokenRecord -
+ * - retrieves token record from tokendb if it exists, or
+ * - creates a new token record
+ * this in-memory copy of tokenRecord is to be set in the TPSSession
+ */
+ protected void fillTokenRecord(TokenRecord tokenRecord, AppletInfo appletInfo)
+ throws TPSException {
+ String method = "TPSProcessor.fillTokenRecord";
+ CMS.debug(method + ": begins");
+ if (tokenRecord == null || appletInfo == null) {
+ CMS.debug(method + ": params tokenRecord and appletInfo cannot be null");
+ throw new TPSException(
+ method + ": missing parameter(s): parameter appletInfo");
+ }
+
+ byte app_major_version = appletInfo.getAppMajorVersion();
+ byte app_minor_version = appletInfo.getAppMinorVersion();
+ TPSBuffer build_id = null;
+ try {
+ build_id = getAppletVersion();
+ } catch (IOException e) {
+ CMS.debug(method + ": failed getting applet version:" + e + " ... continue");
+ }
+ if (build_id != null) {
+ tokenRecord.setAppletID(Integer.toHexString(app_major_version) + "."
+ + Integer.toHexString(app_minor_version) + "." +
+ build_id.toHexStringPlain());
+ }
+
+ CMS.debug(method + ": ends");
+
+ }
+
+ protected TokenRecord isTokenRecordPresent(AppletInfo appletInfo) throws TPSException {
+
+ if (appletInfo == null) {
+ throw new TPSException("TPSProcessor.isTokenRecordPresent: invalid input data.");
+ }
+
+ CMS.debug("TPSEnrollProcessor.isTokenRecordPresent: " + appletInfo.getCUIDhexString());
+
+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ TokenRecord tokenRecord = null;
+ try {
+ tokenRecord = tps.tdb.tdbGetTokenEntry(appletInfo.getCUIDhexStringPlain());
+ // now the in memory tokenRecord is replaced by the actual token data
+ CMS.debug("TPSEnrollProcessor.enroll: found token...");
+ } catch (Exception e) {
+ CMS.debug("TPSEnrollProcessor.enroll: token does not exist in tokendb... create one in memory");
+ }
+
+ return tokenRecord;
+ }
+
+ protected String getCAConnectorID() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ String id = null;
+
+ String config = "op." + currentTokenOperation + "." + selectedTokenType + ".ca.conn";
+
+ try {
+ id = configStore.getString(config, "ca1");
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getCAConnectorID: Internal error finding config value.");
+
+ }
+
+ CMS.debug("TPSProcessor.getCAConectorID: returning: " + id);
+
+ return id;
+ }
+
+ /*
+ * revokeCertsAtFormat returns a boolean that tells if config wants to revoke certs on the token during format
+ */
+ protected boolean revokeCertsAtFormat() {
+ String method = "revokeCertsAtFormat";
+ String auditMsg;
+ CMS.debug(method + ": begins");
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String configName = TPSEngine.OP_FORMAT_PREFIX + "." + selectedTokenType + ".revokeCert";
+ boolean revokeCert = false;
+ try {
+ revokeCert = configStore.getBoolean(configName, false);
+ } catch (EBaseException e) {
+ auditMsg = method + ": config not found: " + configName +
+ "; default to false";
+ CMS.debug(auditMsg);
+ }
+ if (!revokeCert) {
+ auditMsg = method + ": revokeCert = false";
+ CMS.debug(auditMsg);
+ }
+ return revokeCert;
+ }
+
+ protected RevocationReason getRevocationReasonAtFormat() {
+ String method = "getRevocationReasonAtFormat";
+ String auditMsg;
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String configName = TPSEngine.OP_FORMAT_PREFIX + "." + selectedTokenType + ".revokeCert.revokeReason";
+ RevocationReason revokeReason = RevocationReason.UNSPECIFIED;
+ try {
+ int revokeReasonInt = configStore.getInteger(configName);
+ revokeReason = RevocationReason.fromInt(revokeReasonInt);
+ } catch (EBaseException e) {
+ auditMsg = method + ": config not found: " + configName +
+ "; default to unspecified";
+ CMS.debug(auditMsg);
+ revokeReason = RevocationReason.UNSPECIFIED;
+ }
+
+ return revokeReason;
+ }
+
+ /*
+ * revokeCertificates revokes certificates on the token specified
+ * @param cuid the cuid of the token to revoke certificates
+ * @return auditMsg captures the audit message
+ * @throws TPSException in case of error
+ *
+ * TODO: maybe make this a callback function later
+ */
+ protected void revokeCertificates(String cuid, RevocationReason revokeReason, String caConnId) throws TPSException {
+ String auditMsg = "";
+ final String method = "TPSProcessor.revokeCertificates";
+
+ if (cuid == null) {
+ auditMsg = "cuid null";
+ CMS.debug(method + ":" + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
+ }
+ CMS.debug(method + ": begins for cuid:" + cuid);
+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ boolean isTokenPresent = tps.tdb.isTokenPresent(cuid);
+ if (!isTokenPresent) {
+ auditMsg = method + ": token not found: " + cuid;
+ CMS.debug(auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
+ }
+
+ CARemoteRequestHandler caRH = null;
+ try {
+ caRH = new CARemoteRequestHandler(caConnId);
+ } catch (EBaseException e) {
+ auditMsg = method + ": getting CARemoteRequestHandler failure";
+ CMS.debug(auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
+ }
+ //find all certs belonging to the token
+ ArrayList<TPSCertRecord> certRecords = tps.tdb.tdbGetCertificatesByCUID(cuid);
+
+ CMS.debug(method + ": found " + certRecords.size() + " certs");
+
+ for (TPSCertRecord cert : certRecords) {
+ if (cert.getStatus().equals("revoked")) {
+ // already revoked cert should not be on token any more
+ CMS.debug(method + ": cert " + cert.getSerialNumber()
+ + " already revoked; remove from tokendb and move on");
+ try {
+ tps.certDatabase.removeRecord(cert.getId());
+ } catch (Exception e) {
+ auditMsg = method + ": removeRecord failed";
+ CMS.debug(auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
+ }
+ continue;
+ }
+
+ String origin = cert.getOrigin();
+ if (origin != null && !origin.equals(cuid)) {
+ /*
+ * Raidzilla Bug #57803:
+ * If the certificate is not originally created for this
+ * token, we should not revoke the certificate here.
+ * To figure out if this certificate is originally created
+ * for this token, we check the tokenOrigin attribute.
+ */
+ CMS.debug(method + ": cert " + cert.getSerialNumber()
+ + " originally created for this token: " + origin +
+ " while current token: " + cuid
+ + "; Remove from tokendb and skip the revoke");
+ try {
+ tps.certDatabase.removeRecord(cert.getId());
+ } catch (Exception e) {
+ auditMsg = method + ": removeRecord failed";
+ CMS.debug(auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
+ }
+ continue;
+ }
+ if (origin == null) {
+ // no tokenOrigin, then don't care, keep going
+ CMS.debug(method + ": tokenOrigin is not present in tokendb cert record");
+ }
+
+ // revoke the cert
+ /*
+ * if the certificates are revoked_on_hold, don't do anything because the certificates may
+ * be referenced by more than one token.
+ */
+ if (cert.getStatus().equals("revoked_on_hold")) {
+ CMS.debug(method + ": cert " + cert.getSerialNumber()
+ + " has status revoked_on_hold; remove from tokendb and move on");
+ try {
+ tps.certDatabase.removeRecord(cert.getId());
+ } catch (Exception e) {
+ auditMsg = method + ": removeRecord failed";
+ CMS.debug(auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
+ }
+ continue;
+ }
+
+ String hexSerial = cert.getSerialNumber();
+ if (hexSerial.length() >= 3 && hexSerial.startsWith("0x")) {
+ String serial = hexSerial.substring(2); // skip over the '0x'
+ BigInteger bInt = new BigInteger(serial, 16);
+ String serialStr = bInt.toString();
+ CMS.debug(method + ": found cert hex serial: " + serial +
+ " dec serial:" + serialStr);
+ try {
+ CARevokeCertResponse response =
+ caRH.revokeCertificate(true, serialStr, cert.getCertificate(),
+ revokeReason);
+ CMS.debug(method + ": response status =" + response.getStatus());
+ } catch (EBaseException e) {
+ auditMsg = method + ": revokeCertificate from CA failed:" + e;
+ CMS.debug(auditMsg);
+
+ if (revokeReason == RevocationReason.CERTIFICATE_HOLD) {
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, session.getTokenRecord(),
+ session.getIpAddress(), auditMsg,
+ "failure");
+ } else {
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, session.getTokenRecord(),
+ session.getIpAddress(), auditMsg,
+ "failure");
+ }
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
+ }
+ } else {
+ auditMsg = "mulformed hex serial number :" + hexSerial;
+ CMS.debug(method + ": " + auditMsg);
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, session.getTokenRecord(), session.getIpAddress(),
+ auditMsg,
+ "failure");
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_REVOKE_CERTIFICATES_FAILED);
+ }
+ auditMsg = "Certificate " + hexSerial + " revoked";
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, session.getTokenRecord(), session.getIpAddress(), auditMsg,
+ "success");
+
+ // delete cert from tokendb
+ CMS.debug(method + ": cert " + cert.getSerialNumber()
+ + ": remove from tokendb");
+ try {
+ tps.certDatabase.removeRecord(cert.getId());
+ } catch (Exception e) {
+ auditMsg = "removeRecord failed:" + e;
+ CMS.debug(method + ": " + auditMsg);
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_UPDATE_TOKENDB_FAILED);
+ }
+ continue;
+ }
+ CMS.debug(method + ": done for cuid:" + cuid);
+ }
+
+ protected void format(boolean skipAuth) throws TPSException, IOException {
+
+ String auditMsg = null;
+ String appletVersion = null;
+
+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+
+ boolean isExternalReg = false;
+ AppletInfo appletInfo = null;
+ TokenRecord tokenRecord = null;
+ try {
+ appletInfo = getAppletInfo();
+ } catch (TPSException e) {
+ auditMsg = e.toString();
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw e;
+ }
+ appletInfo.setAid(getCardManagerAID());
+
+ CMS.debug("TPSProcessor.format: token cuid: " + appletInfo.getCUIDhexStringPlain());
+ boolean isTokenPresent = false;
+
+ tokenRecord = isTokenRecordPresent(appletInfo);
+
+ if (tokenRecord != null) {
+ CMS.debug("TPSProcessor.format: found token...");
+ isTokenPresent = true;
+ } else {
+ CMS.debug("TPSProcessor.format: token does not exist in tokendb... create one in memory");
+ tokenRecord = new TokenRecord();
+ tokenRecord.setId(appletInfo.getCUIDhexStringPlain());
+ }
+
+ fillTokenRecord(tokenRecord, appletInfo);
+ session.setTokenRecord(tokenRecord);
+
+ String cuid = appletInfo.getCUIDhexString();
+ CMS.debug("TPSProcessor.format: CUID hex string=" + appletInfo.getCUIDhexStringPlain());
+ //tokenRecord.setId(appletInfo.getCUIDhexString(true));
+ String msn = appletInfo.getMSNString();
+
+ byte major_version = appletInfo.getMajorVersion();
+ byte minor_version = appletInfo.getMinorVersion();
+ byte app_major_version = appletInfo.getAppMajorVersion();
+ byte app_minor_version = appletInfo.getAppMinorVersion();
+
+ CMS.debug("TPSProcessor.format: major_version " + major_version + " minor_version: " + minor_version
+ + " app_major_version: " + app_major_version + " app_minor_version: " + app_minor_version);
+
+ String tokenType = "tokenType";
+ String resolverInstName = getResolverInstanceName();
+
+ IAuthCredentials userCred =
+ new com.netscape.certsrv.authentication.AuthCredentials();
+ if (isExternalReg) {
+ //ToDo, do some external Reg stuff along with authentication
+ tokenType = "externalRegAddToToken";
+ } else {
+ CMS.debug("In TPSProcessor.format isExternalReg: OFF");
+ /*
+ * Note: op.format.tokenProfileResolver=none indicates no resolver
+ * plugin used (tokenType resolved perhaps via authentication)
+ */
+
+ try {
+ tokenType = resolveTokenProfile(resolverInstName, cuid, msn, major_version, minor_version);
+ } catch (TPSException e) {
+ auditMsg = e.toString();
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+ CMS.debug("TPSProcessor.format: calculated tokenType: " + tokenType);
+ }
+
+ // isExternalReg : user already authenticated earlier
+ if (!isExternalReg) {
+ // authenticate per profile/tokenType configuration
+ String configName = TPSEngine.OP_FORMAT_PREFIX + "." + tokenType + ".auth.enable";
+ IConfigStore configStore = CMS.getConfigStore();
+ boolean isAuthRequired;
+ try {
+ CMS.debug("TPSProcessor.format: getting config: " + configName);
+ isAuthRequired = configStore.getBoolean(configName, true);
+ } catch (EBaseException e) {
+ CMS.debug("TPSProcessor.format: Internal Error obtaining mandatory config values. Error: " + e);
+ auditMsg = "TPS error getting config values from config store." + e.toString();
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw new TPSException(auditMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+
+ if (isAuthRequired && !skipAuth) {
+ try {
+ TPSAuthenticator userAuth =
+ getAuthentication(TPSEngine.OP_FORMAT_PREFIX, tokenType);
+ userCred = requestUserId("format", cuid, userAuth, beginMsg.getExtensions());
+ userid = (String) userCred.get(userAuth.getAuthCredName());
+ CMS.debug("TPSProcessor.format: userCred (attempted) userid=" + userid);
+ // initialize userid first for logging purposes in case authentication fails
+ tokenRecord.setUserID(userid);
+ IAuthToken authToken = authenticateUser("format", userAuth, userCred);
+ userid = authToken.getInString("userid");
+ tokenRecord.setUserID(userid);
+ CMS.debug("TPSProcessor.format:: auth token userid=" + userid);
+ // TODO: should check if userid match?
+ } catch (Exception e) {
+ // all exceptions are considered login failure
+ CMS.debug("TPSProcessor.format:: authentication exception thrown: " + e);
+ auditMsg = "authentication failed, status = STATUS_ERROR_LOGIN";
+
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw new TPSException(auditMsg,
+ TPSStatus.STATUS_ERROR_LOGIN);
+ }
+ } // TODO: if no auth required, should wipe out existing tokenRecord entry data later?
+ }
+
+ /**
+ * TODO:
+ * isExternalReg is not handled beyond this point until decided
+ */
+
+ //Now check provided profile
+
+ checkProfileStateOK();
+
+ if (isTokenPresent) {
+ CMS.debug("TPSProcessor.format: token exists");
+ TokenStatus newState = TokenStatus.UNINITIALIZED;
+ // Check for transition to 0/UNINITIALIZED status.
+
+ if (!tps.engine.isOperationTransitionAllowed(tokenRecord.getTokenStatus(), newState)) {
+ CMS.debug("TPSProcessor.format: token transition disallowed " +
+ tokenRecord.getTokenStatus() +
+ " to " + newState);
+ auditMsg = "Operation for CUID " + appletInfo.getCUIDhexStringPlain() +
+ " Disabled, illegal transition attempted " + tokenRecord.getTokenStatus() +
+ " to " + newState;
+
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg,
+ "failure");
+
+ throw new TPSException(auditMsg,
+ TPSStatus.STATUS_ERROR_DISABLED_TOKEN);
+ } else {
+ CMS.debug("TPSProcessor.format: token transition allowed " +
+ tokenRecord.getTokenStatus() +
+ " to " + newState);
+ }
+ } else {
+ CMS.debug("TPSProcessor.format: token does not exist");
+
+ checkAllowUnknownToken(TPSEngine.OP_FORMAT_PREFIX);
+ }
+
+ TPSBuffer build_id = getAppletVersion();
+
+ if (build_id == null) {
+ checkAllowNoAppletToken(TPSEngine.OP_FORMAT_PREFIX);
+ } else {
+ appletVersion = Integer.toHexString(app_major_version) + "." + Integer.toHexString(app_minor_version) + "."
+ + build_id.toHexString();
+ }
+
+ String appletRequiredVersion = checkForAppletUpgrade(TPSEngine.OP_FORMAT_PREFIX);
+
+ CMS.debug("TPSProcessor.format: appletVersion found: " + appletVersion + " requiredVersion: "
+ + appletRequiredVersion);
+
+ SecurityLevel secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
+
+ String tksConnId = getTKSConnectorID();
+
+ upgradeApplet(TPSEngine.OP_FORMAT_PREFIX, appletRequiredVersion, secLevel,
+ beginMsg.getExtensions(), tksConnId,
+ 10, 90);
+ CMS.debug("TPSProcessor.format: Completed applet upgrade.");
+
+ // Add issuer info to the token
+
+ writeIssuerInfoToToken(null);
+
+ if (requiresStatusUpdate()) {
+ statusUpdate(100, "PROGRESS_DONE");
+ }
+
+ // Upgrade Symm Keys if needed
+
+ SecureChannel channel = checkAndUpgradeSymKeys();
+ channel.externalAuthenticate();
+ tokenRecord.setKeyInfo(channel.getKeyInfoData().toHexStringPlain());
+
+ if (isTokenPresent && revokeCertsAtFormat()) {
+ // Revoke certificates on token, if so configured
+ RevocationReason reason = getRevocationReasonAtFormat();
+ String caConnId = getCAConnectorID();
+
+ try {
+ revokeCertificates(tokenRecord.getId(), reason, caConnId);
+ } catch (TPSException te) {
+ // failed revocation; capture message and continue
+ auditMsg = te.getMessage();
+ }
+ }
+
+ // Update Token DB
+ tokenRecord.setStatus("uninitialized");
+ try {
+ tps.tdb.tdbUpdateTokenEntry(tokenRecord);
+ String successMsg = "update token success";
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), successMsg,
+ "success");
+ } catch (Exception e) {
+ String failMsg = "update token failure";
+ auditMsg = failMsg + ":" + e.toString();
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), failMsg,
+ "failure");
+
+ throw new TPSException(auditMsg);
+ }
+
+ auditMsg = "format operation succeeded";
+
+ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), auditMsg, "success");
+
+ CMS.debug("TPSProcessor.format:: ends");
+
+ }
+
+ protected void writeIssuerInfoToToken(SecureChannel origChannel) throws TPSException, IOException,
+ UnsupportedEncodingException {
+ if (checkIssuerInfoEnabled()) {
+
+ SecurityLevel secLevel = SecurityLevel.SECURE_MSG_MAC_ENC;
+
+ String tksConnId = getTKSConnectorID();
+
+ int defKeyIndex = getChannelDefKeyIndex();
+ int defKeyVersion = getChannelDefKeyVersion();
+
+ SecureChannel channel = null;
+
+ if (origChannel != null) {
+ channel = origChannel;
+ } else {
+
+ channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, secLevel, tksConnId);
+ channel.externalAuthenticate();
+
+ }
+
+ String issuer = getIssuerInfoValue();
+
+ // We know this better be ASCII value URL.
+ byte[] issuer_bytes = issuer.getBytes("US-ASCII");
+ TPSBuffer issuerInfoBuff = new TPSBuffer(issuer_bytes);
+
+ channel.setIssuerInfo(issuerInfoBuff);
+
+ }
+ }
+
+ protected String getResolverInstanceName() throws TPSException {
+
+ CMS.debug("TPSProcessor.getResolverInstanceName: entering for operaiton : " + currentTokenOperation);
+ IConfigStore configStore = CMS.getConfigStore();
+ String resolverInstName = null;
+
+ String opPrefix = null;
+ String opDefault = null;
+
+ if (currentTokenOperation.equals(TPSEngine.FORMAT_OP)) {
+ opPrefix = TPSEngine.OP_FORMAT_PREFIX;
+ opDefault = TPSEngine.CFG_DEF_FORMAT_PROFILE_RESOLVER;
+
+ } else if (currentTokenOperation.equals(TPSEngine.ENROLL_OP)) {
+ opDefault = TPSEngine.CFG_DEF_ENROLL_PROFILE_RESOLVER;
+ opPrefix = TPSEngine.OP_ENROLL_PREFIX;
+ } else if (currentTokenOperation.equals(TPSEngine.PIN_RESET_OP)) {
+
+ opDefault = TPSEngine.CFG_DEF_PIN_RESET_PROFILE_RESOLVER;
+ opPrefix = TPSEngine.OP_PIN_RESET_PREFIX;
+ }
+
+ String config = opPrefix +
+ "." + TPSEngine.CFG_PROFILE_RESOLVER;
+
+ CMS.debug("TPSProcessor.getResolverInstanceName: config: " + config);
+ try {
+ resolverInstName = configStore.getString(config, opDefault);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getResolverInstanceName: Internal error finding config value.");
+
+ }
+
+ CMS.debug("TPSProcessor.getResolverInstanceName: returning: " + resolverInstName);
+
+ return resolverInstName;
+ }
+
+ /**
+ * @param resolverInstName
+ * @param cuid
+ * @param msn
+ * @param major_version
+ * @param minor_version
+ * @return
+ */
+ protected String resolveTokenProfile(
+ String resolverInstName,
+ String cuid,
+ String msn,
+ byte major_version,
+ byte minor_version)
+ throws TPSException {
+ String tokenType;
+
+ if (!resolverInstName.equals("none") && (selectedTokenType == null)) {
+
+ try {
+ TokenProfileParams pParams = new TokenProfileParams();
+ CMS.debug("In TPSProcessor.resolveTokenProfile : after new TokenProfileParams");
+ pParams.set(TokenProfileParams.PROFILE_PARAM_MAJOR_VERSION,
+ String.valueOf(major_version));
+ pParams.set(TokenProfileParams.PROFILE_PARAM_MINOR_VERSION,
+ String.valueOf(minor_version));
+ pParams.set(TokenProfileParams.PROFILE_PARAM_CUID, cuid);
+ pParams.set(TokenProfileParams.PROFILE_PARAM_MSN, msn);
+ if (beginMsg.getExtensions() != null) {
+ pParams.set(TokenProfileParams.PROFILE_PARAM_EXT_TOKEN_TYPE,
+ beginMsg.getExtensions().get("tokenType"));
+ pParams.set(TokenProfileParams.PROFILE_PARAM_EXT_TOKEN_ATR,
+ beginMsg.getExtensions().get("tokenATR"));
+ }
+ CMS.debug("In TPSProcessor.resolveTokenProfile : after setting TokenProfileParams");
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+ BaseTokenProfileResolver resolverInst =
+ subsystem.getProfileResolverManager().getResolverInstance(resolverInstName);
+ tokenType = resolverInst.getTokenType(pParams);
+ CMS.debug("In TPSProcessor.resolveTokenProfile : profile resolver result: " + tokenType);
+ setSelectedTokenType(tokenType);
+ } catch (EBaseException et) {
+ CMS.debug("In TPSProcessor.resolveTokenProfile exception:" + et);
+ throw new TPSException("TPSProcessor.resolveTokenProfile failed.",
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+
+ } else {
+ //Already have a token type, return it
+ tokenType = getSelectedTokenType();
+ }
+
+ return tokenType;
+ }
+
+ protected String getIssuerInfoValue() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ String info = null;
+
+ String config = "op." + currentTokenOperation + "." + selectedTokenType + "." + TPSEngine.CFG_ISSUER_INFO_VALUE;
+
+ CMS.debug("TPSProcessor.getIssuerInfoValue: config: " + config);
+ try {
+ info = configStore.getString(config, null);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getIssuerInfoValue: Internal error finding config value.");
+
+ }
+
+ if (info == null) {
+ throw new TPSException("TPSProcessor.getIssuerInfoValue: Can't find issuer info value in the config.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ CMS.debug("TPSProcessor.getIssuerInfoValue: returning: " + info);
+
+ return info;
+ }
+
+ void checkProfileStateOK() throws TPSException {
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String profileConfig = "config.Profiles." + selectedTokenType + ".state";
+ String profileState = null;
+
+ try {
+ profileState = configStore.getString(profileConfig, TPSEngine.CFG_ENABLED);
+ } catch (EBaseException e) {
+ //Default TPSException will return a "contact admin" error code.
+ throw new TPSException(
+ "TPSProcessor.checkProfileStateOK: internal error in getting profile state from config.");
+ }
+
+ if (!profileState.equals(TPSEngine.CFG_ENABLED)) {
+ CMS.debug("TPSProcessor.checkProfileStateOK: profile specifically disabled.");
+ throw new TPSException("TPSProcessor.checkProfileStateOK: profile disabled!");
+ }
+
+ }
+
+ protected boolean checkIssuerInfoEnabled() throws TPSException {
+
+ CMS.debug("TPSProcessor.checkIssuerEnabled entering...");
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String issuerEnabledConfig = "op." + currentTokenOperation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_ISSUER_INFO_ENABLE;
+
+ CMS.debug("TPSProcessor.checkIssuerEnabled config to check: " + issuerEnabledConfig);
+
+ boolean issuerInfoEnabled = false;
+
+ try {
+ issuerInfoEnabled = configStore.getBoolean(issuerEnabledConfig, false);
+ } catch (EBaseException e) {
+ //Default TPSException will return a "contact admin" error code.
+ throw new TPSException(
+ "TPSProcessor.checkIssuerInfo: internal error in getting value from config.");
+ }
+
+ CMS.debug("TPSProcessor.checkIssuerEnabled returning: " + issuerInfoEnabled);
+ return issuerInfoEnabled;
+
+ }
+
+ //Obtain value and set class property.
+ protected void checkIsExternalReg() throws TPSException {
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String External_Reg_Cfg = TPSEngine.CFG_EXTERNAL_REG + "." + "enable";
+
+ try {
+ //These defaults are well known, it is safe to use them.
+
+ CMS.debug("In TPS_Processor.checkIsExternalReg.");
+
+ this.isExternalReg = configStore.getBoolean(External_Reg_Cfg, false);
+ CMS.debug("In TPS_Processor.checkIsExternalReg. isExternalReg: " + isExternalReg);
+ } catch (EBaseException e1) {
+ CMS.debug("TPS_Processor.checkIsExternalReg: Internal Error obtaining mandatory config values. Error: "
+ + e1);
+ throw new TPSException("TPS error getting config values from config store.");
+ }
+
+ }
+
+ boolean checkServerSideKeyGen(String connId) throws TPSException {
+
+ boolean result;
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String profileConfig = "conn." + connId + "." + ".serverKeygen";
+
+ try {
+ result = configStore.getBoolean(profileConfig, false);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor: checkServerSideKeyGen: Internal error obtaining config value!");
+ }
+
+ return result;
+ }
+
+ void checkAllowNoAppletToken(String operation) throws TPSException {
+ boolean allow = true;
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String noAppletConfig = operation + "." + selectedTokenType + "." + TPSEngine.CFG_ALLOW_NO_APPLET;
+
+ try {
+ allow = configStore.getBoolean(noAppletConfig, true);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.checkAllowNoAppletToken: Internal error getting config param.");
+ }
+
+ if (!allow) {
+ throw new TPSException("TPSProcessor.checkAllowNoAppletToken: token without applet not permitted!",
+ TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+ }
+
+ }
+
+ boolean checkForAppletUpdateEnabled() throws TPSException {
+ boolean enabled = false;
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String appletUpdate = "op." + currentTokenOperation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_UPDATE_APPLET_ENABLE;
+ CMS.debug("TPSProcessor.checkForAppletUpdateEnabled: getting config: " + appletUpdate);
+ try {
+ enabled = configStore.getBoolean(appletUpdate, false);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSProcessor.checkForAppleUpdateEnabled: Can't find applet Update Enable. Internal error obtaining value.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+ }
+ CMS.debug("TPSProcessor.checkForAppletUpdateEnabled: returning " + enabled);
+ return enabled;
+ }
+
+ protected String checkForAppletUpgrade(String operation) throws TPSException {
+ String requiredVersion = null;
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String appletRequiredConfig = operation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_APPLET_UPDATE_REQUIRED_VERSION;
+ CMS.debug("TPSProcessor.checkForAppletUpgrade: getting config: " + appletRequiredConfig);
+ try {
+ requiredVersion = configStore.getString(appletRequiredConfig, null);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "TPSProcessor.checkForAppletUpgrade: Can't find applet required Version. Internal error obtaining version.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ if (requiredVersion == null) {
+ throw new TPSException("TPSProcessor.checkForAppletUpgrade: Can't find applet required Version.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ CMS.debug("TPSProcessor.checkForAppletUpgrade: returning: " + requiredVersion);
+
+ return requiredVersion;
+ }
+
+ protected void checkAllowUnknownToken(String operation) throws TPSException {
+ boolean allow = true;
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String unknownConfig = "op." + operation + "." + TPSEngine.CFG_ALLOW_UNKNOWN_TOKEN;
+
+ try {
+ allow = configStore.getBoolean(unknownConfig, true);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.checkAllowUnknownToken: Internal error getting config value.");
+ }
+
+ if (allow == false) {
+ throw new TPSException(
+ "TPSProcessor.checkAllowUnknownToken: Unknown tokens not allowed for this operation!",
+ TPSStatus.STATUS_ERROR_TOKEN_DISABLED);
+ }
+
+ }
+
+ protected String getTKSConnectorID() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ String id = null;
+
+ String config = "op." + currentTokenOperation + "." + selectedTokenType + ".tks.conn";
+
+ try {
+ id = configStore.getString(config, "tks1");
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getTKSConnectorID: Internal error finding config value.");
+
+ }
+
+ CMS.debug("TPSProcessor.getTKSConectorID: returning: " + id);
+
+ return id;
+ }
+
+ protected TPSBuffer getNetkeyAID() throws TPSException {
+
+ String NetKeyAID = null;
+ IConfigStore configStore = CMS.getConfigStore();
+ try {
+
+ NetKeyAID = configStore.getString(TPSEngine.CFG_APPLET_NETKEY_INSTANCE_AID,
+ TPSEngine.CFG_DEF_NETKEY_INSTANCE_AID);
+
+ } catch (EBaseException e1) {
+ CMS.debug("TPS_Processor.getNetkeyAID: Internal Error obtaining mandatory config values. Error: " + e1);
+ throw new TPSException("TPS error getting config values from config store.");
+ }
+
+ TPSBuffer ret = new TPSBuffer(NetKeyAID);
+
+ return ret;
+ }
+
+ protected TPSBuffer getNetkeyPAID() throws TPSException {
+
+ String NetKeyPAID = null;
+ IConfigStore configStore = CMS.getConfigStore();
+ try {
+
+ NetKeyPAID = configStore.getString(
+ TPSEngine.CFG_APPLET_NETKEY_FILE_AID, TPSEngine.CFG_DEF_NETKEY_FILE_AID);
+
+ } catch (EBaseException e1) {
+ CMS.debug("TPS_Processor.getNetkeyAID: Internal Error obtaining mandatory config values. Error: " + e1);
+ throw new TPSException("TPS error getting config values from config store.");
+ }
+
+ TPSBuffer ret = new TPSBuffer(NetKeyPAID);
+
+ return ret;
+ }
+
+ protected TPSBuffer getCardManagerAID() throws TPSException {
+
+ String cardMgrAID = null;
+ IConfigStore configStore = CMS.getConfigStore();
+ try {
+
+ cardMgrAID = configStore.getString(TPSEngine.CFG_DEF_CARDMGR_INSTANCE_AID,
+ TPSEngine.CFG_DEF_CARDMGR_INSTANCE_AID);
+
+ } catch (EBaseException e1) {
+ CMS.debug("TPS_Processor.getNetkeyAID: Internal Error obtaining mandatory config values. Error: " + e1);
+ throw new TPSException("TPS error getting config values from config store.");
+ }
+
+ TPSBuffer ret = new TPSBuffer(cardMgrAID);
+
+ return ret;
+ }
+
+ protected String getAppletExtension() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ String extension = null;
+ String extensionConfig = TPSEngine.CFG_APPLET_EXTENSION;
+
+ try {
+ extension = configStore.getString(extensionConfig, "ijc");
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getAppletExtension: Internal error finding config value.");
+
+ }
+
+ CMS.debug("TPSProcessor.getAppletExtension: returning: " + extension);
+
+ return extension;
+ }
+
+ protected String getAppletDirectory(String operation) throws TPSException {
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String directory = null;
+
+ String directoryConfig = operation + "." + selectedTokenType + "." + TPSEngine.CFG_APPLET_DIRECTORY;
+
+ //We need a directory
+ try {
+ directory = configStore.getString(directoryConfig);
+ } catch (EPropertyNotFound e) {
+ throw new TPSException("TPSProcessor.getAppletDirectory: Required config param missing.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getAppletDirectory: Internal error finding config value.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+
+ CMS.debug("getAppletDirectory: returning: " + directory);
+ return directory;
+ }
+
+ protected int getChannelBlockSize() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ int blockSize = 0;
+ try {
+ blockSize = configStore.getInteger(TPSEngine.CFG_CHANNEL_BLOCK_SIZE, TPSEngine.CFG_CHANNEL_DEF_BLOCK_SIZE);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getChannelBlockSize: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+ }
+
+ CMS.debug("TPSProcess.getChannelBlockSize: returning: " + blockSize);
+ return blockSize;
+
+ }
+
+ protected int getChannelInstanceSize() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ int instanceSize = 0;
+ try {
+ instanceSize = configStore.getInteger(TPSEngine.CFG_CHANNEL_INSTANCE_SIZE,
+ TPSEngine.CFG_CHANNEL_DEF_INSTANCE_SIZE);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getChannelInstanceSize: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+ }
+
+ CMS.debug("TPSProcess.getChannelInstanceSize: returning: " + instanceSize);
+
+ return instanceSize;
+
+ }
+
+ protected int getAppletMemorySize() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ int memSize = 0;
+ try {
+ memSize = configStore.getInteger(TPSEngine.CFG_CHANNEL_APPLET_MEMORY_SIZE,
+ TPSEngine.CFG_CHANNEL_DEF_APPLET_MEMORY_SIZE);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getAppletMemorySize: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+ }
+ CMS.debug("TPSProcess.getAppletMemorySize: returning: " + memSize);
+
+ return memSize;
+ }
+
+ protected int getChannelDefKeyVersion() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ int ver = 0;
+ try {
+ ver = configStore.getInteger(TPSEngine.CFG_CHANNEL_DEFKEY_VERSION, 0x0);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getChannelDefKeyVersion: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+ }
+
+ CMS.debug("TPSProcessor.getChannelDefKeyVersion: " + ver);
+
+ return ver;
+
+ }
+
+ protected int getChannelDefKeyIndex() throws TPSException {
+ IConfigStore configStore = CMS.getConfigStore();
+ int index = 0;
+ try {
+ index = configStore.getInteger(TPSEngine.CFG_CHANNEL_DEFKEY_INDEX, 0x0);
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getChannelDefKeyVersion: Internal error finding config value: " + e,
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+
+ }
+
+ CMS.debug("TPSProcessor.getChannelDefKeyIndex: " + index);
+
+ return index;
+
+ }
+
+ protected PK11SymKey getSharedSecretTransportKey(String connId) throws TPSException, NotInitializedException {
+
+ IConfigStore configStore = CMS.getConfigStore();
+ String sharedSecretName = null;
+ try {
+ String configName = "conn." + connId + ".tksSharedSymKeyName";
+ sharedSecretName = configStore.getString(configName, "sharedSecret");
+
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getSharedSecretTransportKey: Internal error finding config value: "
+ + e,
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+
+ }
+
+ CMS.debug("TPSProcessor.getSharedSecretTransportKey: calculated key name: " + sharedSecretName);
+
+ String symmKeys = null;
+ boolean keyPresent = false;
+ try {
+ symmKeys = SessionKey.ListSymmetricKeys("internal");
+ CMS.debug("TPSProcessor.getSharedSecretTransportKey: symmKeys List: " + symmKeys);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ CMS.debug(e);
+ }
+
+ for (String keyName : symmKeys.split(",")) {
+ if (sharedSecretName.equals(keyName)) {
+ CMS.debug("TPSProcessor.getSharedSecret: shared secret key found!");
+ keyPresent = true;
+ break;
+ }
+
+ }
+
+ if (!keyPresent) {
+ throw new TPSException("TPSProcessor.getSharedSecret: Can't find shared secret!",
+ TPSStatus.STATUS_ERROR_SECURE_CHANNEL);
+ }
+
+ // We know for now that shared secret is on this token
+ String tokenName = "Internal Key Storage Token";
+ PK11SymKey sharedSecret = SessionKey.GetSymKeyByName(tokenName, sharedSecretName);
+
+ CMS.debug("TPSProcessor.getSharedSecret: SymKey returns: " + sharedSecret);
+
+ return sharedSecret;
+
+ }
+
+ public boolean getIsExternalReg() {
+ return isExternalReg;
+ }
+
+ public void process(BeginOpMsg beginMsg) throws TPSException, IOException {
+
+ if (beginMsg == null) {
+ throw new TPSException("TPSProcessor.process: invalid input data, not beginMsg provided.",
+ TPSStatus.STATUS_ERROR_UPGRADE_APPLET);
+ }
+ setBeginMessage(beginMsg);
+ setCurrentTokenOperation("format");
+ checkIsExternalReg();
+
+ format(false);
+ }
+
+ public void statusUpdate(int status, String info) throws IOException {
+
+ if (!requiresStatusUpdate())
+ return;
+
+ CMS.debug("In TPSProcessor.statusUpdate status: " + status + " info: " + info);
+
+ StatusUpdateRequestMsg statusUpdate = new StatusUpdateRequestMsg(status, info);
+ session.write(statusUpdate);
+
+ //We don't really care about the response, just that we get it.
+
+ session.read();
+
+ }
+
+ public TPSEngine getTPSEngine() {
+ TPSSubsystem subsystem =
+ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+
+ return subsystem.getEngine();
+
+ }
+
+ // Do the incoming extensions support status update?
+ public boolean requiresStatusUpdate() {
+
+ boolean result = false;
+
+ // We can't get here without a begin message established.
+ String update = getBeginMessage().getExtension(BeginOpMsg.STATUS_UPDATE_EXTENSION_NAME);
+
+ if (update != null && update.equals("true")) {
+ result = true;
+ }
+
+ return result;
+
+ }
+
+ protected AppletInfo getAppletInfo() throws TPSException, IOException {
+ AppletInfo result = null;
+
+ CMS.debug("TPSProcessor.getAppletInfo, entering ...");
+
+ selectCardManager();
+
+ TPSBuffer cplc_data = getCplcData();
+ CMS.debug("cplc_data: " + cplc_data.toString());
+
+ TPSBuffer token_cuid = extractTokenCUID(cplc_data);
+ TPSBuffer token_msn = extractTokenMSN(cplc_data);
+
+ /**
+ * Checks if the netkey has the required applet version.
+ */
+
+ selectCoolKeyApplet();
+
+ TPSBuffer token_status = getStatus();
+
+ byte major_version = 0x0;
+ byte minor_version = 0x0;
+ byte app_major_version = 0x0;
+ byte app_minor_version = 0x0;
+
+ CMS.debug("TPS_Processor.getAppletInfo: status: " + token_status.toHexString());
+ if (token_status.size() >= 4) {
+ major_version = token_status.at(0);
+ minor_version = token_status.at(1);
+ app_major_version = token_status.at(2);
+ app_minor_version = token_status.at(3);
+ }
+
+ int free_mem = 0;
+ int total_mem = 0;
+
+ if (token_status.size() >= 12) {
+ byte tot_high = token_status.at(6);
+ byte tot_low = token_status.at(7);
+
+ byte free_high = token_status.at(10);
+ byte free_low = token_status.at(11);
+
+ total_mem = (tot_high << 8) + tot_low;
+ free_mem = (free_high << 8) + free_low;
+
+ }
+
+ result = new AppletInfo(major_version, minor_version, app_major_version, app_minor_version);
+ result.setCUID(token_cuid);
+ result.setMSN(token_msn);
+ result.setTotalMem(total_mem);
+ result.setFreeMem(free_mem);
+
+ CMS.debug("TPSProcessor.getAppletInfo: cuid: " + result.getCUIDhexString() + " msn: " + result.getMSNString()
+ + " major version: " + result.getMinorVersion() + " minor version: " + result.getMinorVersion()
+ + " App major version: " + result.getAppMajorVersion() + " App minor version: "
+ + result.getAppMinorVersion());
+
+ return result;
+ }
+
+ protected void selectCardManager() throws TPSException, IOException {
+ CMS.debug("TPSProcessor.selectCardManager: entering..");
+ TPSBuffer aidBuf = getCardManagerAID();
+
+ APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, aidBuf);
+
+ if (!select.checkResult()) {
+ throw new TPSException("TPSProcessor.selectCardManager: Can't selelect the card manager applet!");
+ }
+ }
+
+ protected boolean checkSymmetricKeysEnabled() throws TPSException {
+ boolean result = true;
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String symmConfig = "op" + "." + currentTokenOperation + "." + selectedTokenType + "."
+ + TPSEngine.CFG_SYMM_KEY_UPGRADE_ENABLED;
+
+ try {
+ result = configStore.getBoolean(symmConfig, true);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.checkSymmetricKeysEnabled: Internal error getting config value.");
+ }
+
+ return result;
+ }
+
+ protected int getSymmetricKeysRequiredVersion() throws TPSException {
+ int version = 0;
+ ;
+
+ IConfigStore configStore = CMS.getConfigStore();
+
+ String requiredVersionConfig = "op" + "." + currentTokenOperation + "." + selectedTokenType + "."
+ + "update.symmetricKeys.requiredVersion";
+
+ CMS.debug("TPSProcessor.getSymmetricKeysRequiredVersion: configValue: " + requiredVersionConfig);
+ try {
+ version = configStore.getInteger(requiredVersionConfig, 0x0);
+ } catch (EBaseException e) {
+ throw new TPSException("TPSProcessor.getSymmetricKeysRequired: Internal error getting config value.");
+ }
+
+ CMS.debug("TPSProcessor.getSymmetricKeysRequiredVersion: returning version: " + version);
+
+ return version;
+ }
+
+ protected SecureChannel checkAndUpgradeSymKeys() throws TPSException, IOException {
+
+ /* If the key of the required version is
+ not found, create them.
+
+ This sends a InitializeUpdate request to the token.
+ We tell the token to use whatever it thinks is the
+ default key version (0). It will return the version
+ of the key it actually used later. (This is accessed
+ with GetKeyInfoData below)
+ [ Note: This is not explained very well in the manual
+ The token can have multiple sets of symmetric keys
+ Each set is given a version number, which I think is
+ better thought of as a SLOT. One key slot is populated
+ with a set of keys when the token is manufactured.
+ This is then designated as the default key set version.
+ Later, we will write a new key set with PutKey, and
+ set it to be the new default]
+ */
+
+ SecureChannel channel = null;
+
+ int defKeyVersion = 0;
+ int defKeyIndex = getChannelDefKeyIndex();
+
+ if (checkSymmetricKeysEnabled()) {
+
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: Symm key upgrade enabled.");
+ int requiredVersion = getSymmetricKeysRequiredVersion();
+
+ // try to make a secure channel with the 'requiredVersion' keys
+ // If this fails, we know we will have to attempt an upgrade
+ // of the keys
+
+ boolean failed = false;
+ try {
+
+ channel = setupSecureChannel((byte) requiredVersion, (byte) defKeyIndex,
+ SecurityLevel.SECURE_MSG_MAC_ENC,
+ getTKSConnectorID());
+
+ } catch (TPSException e) {
+
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: failed to create secure channel with required version, we need to upgrade the keys.");
+ failed = true;
+ }
+
+ //If we failed we need to upgrade the keys
+ if (failed == true) {
+
+ selectCardManager();
+
+ channel = setupSecureChannel();
+
+ /* Assemble the Buffer with the version information
+ The second byte is the key offset, which is always 1
+ */
+
+ byte[] nv = { (byte) requiredVersion, 0x01 };
+ TPSBuffer newVersion = new TPSBuffer(nv);
+
+ // GetKeyInfoData will return a buffer which is bytes 11,12 of
+ // the data structure on page 89 of Cyberflex Access Programmer's
+ // Guide
+ // Byte 0 is the key set version.
+ // Byte 1 is the index into that key set
+
+ String connId = getTKSConnectorID();
+ TPSBuffer curKeyInfo = channel.getKeyInfoData();
+ TPSEngine engine = getTPSEngine();
+
+ TPSBuffer keySetData = engine.createKeySetData(newVersion, curKeyInfo,
+ channel.getKeyDiversificationData(), connId);
+
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: new keySetData from TKS: " + keySetData.toHexString());
+
+ byte curVersion = curKeyInfo.at(0);
+ byte curIndex = curKeyInfo.at(1);
+
+ channel.putKeys(curVersion, curIndex, keySetData);
+
+ String curVersionStr = curKeyInfo.toHexString();
+ String newVersionStr = newVersion.toHexString();
+ TPSSession session = getSession();
+ TokenRecord tokenRecord = session.getTokenRecord();
+ tokenRecord.setKeyInfo(newVersion.toHexStringPlain());
+
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: curVersionStr: " + curVersionStr + " newVersionStr: "
+ + newVersionStr);
+
+ selectCoolKeyApplet();
+
+ channel = setupSecureChannel((byte) requiredVersion, (byte) defKeyIndex,
+ SecurityLevel.SECURE_MSG_MAC_ENC,
+ getTKSConnectorID());
+
+ } else {
+ CMS.debug("TPSProcessor.checkAndUpgradeSymeKeys: We are already at the desired key set, returning secure channel.");
+ }
+
+ } else {
+ //Create a standard secure channel with current key set.
+ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: Key changeover disabled in the configuration.");
+
+ defKeyVersion = getChannelDefKeyVersion();
+
+ channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, SecurityLevel.SECURE_MSG_MAC_ENC,
+ getTKSConnectorID());
+
+ }
+
+ CMS.debug("TPSProcessor.checkAndUpdradeSymKeys: Leaving successfully....");
+ return channel;
+ }
+
+ //List objects that may be on a given token
+ //Return null if object void of objects
+
+ protected TPSBuffer listObjects(byte seq) throws TPSException, IOException {
+ TPSBuffer objects = null;
+
+ ListObjectsAPDU listObjects = new ListObjectsAPDU(seq);
+
+ APDUResponse respApdu = handleAPDURequest(listObjects);
+
+ if (!respApdu.checkResult()) {
+ CMS.debug("TPSProcessor.listObjects: Bad response from ListObjects! Token possibly has no objects");
+ return null;
+ }
+
+ objects = respApdu.getData();
+
+ return objects;
+
+ }
+
+ // Request new pin from client
+ protected String requestNewPin(int minLen, int maxLen) throws IOException, TPSException {
+
+ CMS.debug("TPSProcessor.requestNewPin: entering...");
+
+ String newPin = null;
+
+ NewPinRequestMsg new_pin_req = new NewPinRequestMsg(minLen, maxLen);
+
+ session.write(new_pin_req);
+
+ NewPinResponseMsg new_pin_resp = (NewPinResponseMsg) session.read();
+
+ newPin = new_pin_resp.get(NewPinResponseMsg.NEW_PIN_NAME);
+
+ if (newPin.length() < minLen || newPin.length() > maxLen) {
+ throw new TPSException("TPSProcessor.requestNewPin: new pin length outside of length contraints: min: "
+ + minLen + " max: " + maxLen);
+ }
+
+ return newPin;
+ }
+
+ protected String mapPattern(LinkedHashMap<String, String> map, String pattern) throws TPSException {
+
+ //Right now only support one pattern to match within pattern: for instance:
+ // "encryption key for $userid$ , not only the one "$userid$" pattern.
+
+ String result = null;
+
+ if (pattern == null || map == null) {
+ throw new TPSException("TPSProcessor.mapPattern: Illegal input paramters!",
+ TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+ }
+
+ final char delim = '$';
+ int firstPos = 0;
+ int nextPos = 0;
+ String patternToMap = null;
+ String patternMapped = null;
+
+ firstPos = pattern.indexOf(delim);
+ nextPos = pattern.indexOf(delim, firstPos + 1);
+
+ if ((nextPos - firstPos) <= 1) {
+ return pattern;
+ }
+
+ patternToMap = pattern.substring(firstPos + 1, nextPos);
+
+ CMS.debug("TPSProcessor.mapPattern: patternTo map: " + patternToMap);
+
+ String piece1 = "";
+ if (firstPos >= 1)
+ piece1 = pattern.substring(0, firstPos);
+
+ String piece2 = "";
+ if (nextPos < (pattern.length() - 1))
+ piece2 = pattern.substring(nextPos + 1);
+
+ for (Map.Entry<String, String> entry : map.entrySet()) {
+ String key = entry.getKey();
+
+ String value = entry.getValue();
+ CMS.debug("TPSProcessor.mapPattern: Exposed: key: " + key + " Param: " + value);
+
+ if (key.equals(patternToMap)) {
+ CMS.debug("TPSProcessor.mapPattern: found match: key: " + key + " mapped to: " + value);
+ patternMapped = value;
+ break;
+ }
+
+ }
+
+ result = piece1 + patternMapped + piece2;
+
+ CMS.debug("TPSProcessor.mapPattern: returning: " + result);
+ return result;
+
+ }
+
+ protected String formatCurrentAppletVersion(AppletInfo aInfo) throws TPSException, IOException {
+
+ if (aInfo == null) {
+ throw new TPSException("TPSProcessor.formatCurrentAppletVersion: ", TPSStatus.STATUS_ERROR_CONTACT_ADMIN);
+ }
+
+ TPSBuffer build_id = getAppletVersion();
+ String build_idStr = build_id.toHexStringPlain();
+
+ String finalVersion = aInfo.getAppMajorVersion() + "." + aInfo.getAppMinorVersion() + "." + build_idStr;
+
+ finalVersion = finalVersion.toLowerCase();
+ CMS.debug("TPSProcessor.formatCurrentAppletVersion: returing: " + finalVersion);
+
+ return finalVersion;
+
+ }
+
+ public static void main(String[] args) {
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/profile/BaseTokenProfileResolver.java b/base/tps/src/org/dogtagpki/server/tps/profile/BaseTokenProfileResolver.java
new file mode 100644
index 000000000..c62d1ed2b
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/profile/BaseTokenProfileResolver.java
@@ -0,0 +1,38 @@
+package org.dogtagpki.server.tps.profile;
+
+import org.dogtagpki.tps.main.TPSException;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.IConfigStore;
+
+/**
+ * This class implements the base TPS Profile Resolver instance
+ *
+ * @author cfu
+ */
+public abstract class BaseTokenProfileResolver {
+ protected IConfigStore configStore = null;
+ protected String instanceName = "";
+ protected String prefix = "";
+
+ public BaseTokenProfileResolver() {
+ }
+
+ public void init(String instName) {
+ instanceName = instName;
+ prefix = TokenProfileResolverManager.TOKEN_PROFILE_RESOLVER_CFG +
+ "." + instanceName;
+ configStore = CMS.getConfigStore();
+ }
+
+ public String getName() {
+ return instanceName;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public abstract String getTokenType(TokenProfileParams pPram)
+ throws TPSException;
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/profile/MappingTokenProfileResolver.java b/base/tps/src/org/dogtagpki/server/tps/profile/MappingTokenProfileResolver.java
new file mode 100644
index 000000000..264fba882
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/profile/MappingTokenProfileResolver.java
@@ -0,0 +1,294 @@
+package org.dogtagpki.server.tps.profile;
+
+import org.dogtagpki.server.tps.engine.TPSEngine;
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+
+/**
+ * MappingTokenProfileResolver is a profile resolver plugin that calculates
+ * token type by sorting through a list of filters in mapping
+ */
+public class MappingTokenProfileResolver extends BaseTokenProfileResolver {
+
+ public MappingTokenProfileResolver() {
+ }
+
+ public String getTokenType(TokenProfileParams pParam)
+ throws TPSException {
+
+ String tokenType = null;
+ String mappingOrder = null;
+ int major_version = 0;
+ int minor_version = 0;
+ String cuid = null;
+ // String msn = null;
+ String eTokenType = null;
+ String eTokenATR = null;
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: starts");
+
+ major_version = pParam.getInt(TokenProfileParams.PROFILE_PARAM_MAJOR_VERSION);
+ CMS.debug("MappingTokenProfileResolver: param major_version =" + major_version);
+
+ minor_version = pParam.getInt(TokenProfileParams.PROFILE_PARAM_MINOR_VERSION);
+ CMS.debug("MappingTokenProfileResolver: param minor_version =" + minor_version);
+
+ cuid = pParam.getString(TokenProfileParams.PROFILE_PARAM_CUID);
+ // msn = (String) pParam.get(TokenProfileParams.PROFILE_PARAM_MSN);
+ // they don't necessarily have extension
+ try {
+ eTokenType = pParam.getString(TokenProfileParams.PROFILE_PARAM_EXT_TOKEN_TYPE);
+ eTokenATR = pParam.getString(TokenProfileParams.PROFILE_PARAM_EXT_TOKEN_ATR);
+ } catch (TPSException e) {
+ CMS.debug("MappingTokenProfileResolver: OK to not have extension. Continue.");
+ }
+
+ CMS.debug("MappingTokenProfileResolver: params retrieved.");
+
+ String configName = prefix + "." + TPSEngine.CFG_PROFILE_MAPPING_ORDER;
+
+ try {
+ CMS.debug("MappingTokenProfileResolver: getting mapping order:" +
+ configName);
+ mappingOrder = configStore.getString(configName);
+ } catch (EPropertyNotFound e) {
+ CMS.debug("MappingTokenProfileResolver: exception:" + e);
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Token Type configuration incorrect! Mising mapping order!",
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+
+ } catch (EBaseException e1) {
+ //The whole feature won't work if this is wrong.
+ CMS.debug("MappingTokenProfileResolver: exception:" + e1);
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value.!",
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+
+ String targetTokenType = null;
+
+ for (String mappingId : mappingOrder.split(",")) {
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: mapping: " + mappingId);
+
+ String mappingConfigName = prefix + ".mapping." + mappingId + ".target.tokenType";
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: mappingConfigName: " + mappingConfigName);
+
+ //We need this to exist.
+ try {
+ targetTokenType = configStore.getString(mappingConfigName);
+ } catch (EPropertyNotFound e) {
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Token Type configuration incorrect! No target token type config value found! Config: "
+ + mappingConfigName,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+ + mappingConfigName,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+
+ mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenType";
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: mappingConfigName: " + mappingConfigName);
+
+ //For this and remaining cases, it is not automatically an error if we don't get anything back
+ // from the config.
+ try {
+ tokenType = configStore.getString(mappingConfigName, null);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+ + mappingConfigName,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+
+ }
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: targetTokenType: " + targetTokenType);
+
+ if (tokenType != null && tokenType.length() > 0) {
+
+ if (eTokenType == null) {
+ continue;
+ }
+
+ //String eTokenType = extensions.get("tokenType");
+ //if (eTokenType == null) {
+ // continue;
+ //}
+
+ if (!eTokenType.equals(tokenType)) {
+ continue;
+ }
+ }
+
+ mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenATR";
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: mappingConfigName: " + mappingConfigName);
+
+ String tokenATR = null;
+
+ try {
+ tokenATR = configStore.getString(mappingConfigName, null);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+ + mappingConfigName,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: tokenATR: " + tokenATR);
+
+ if (tokenATR != null && tokenATR.length() > 0) {
+ if (eTokenATR == null) {
+ continue;
+ }
+
+ //String eTokenATR = extensions.get("tokenATR");
+
+ //if (eTokenATR == null) {
+ // continue;
+ //}
+
+ if (!eTokenATR.equals(tokenATR)) {
+ continue;
+ }
+
+ }
+
+ mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenCUID.start";
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: mappingConfigName: " + mappingConfigName);
+
+ String tokenCUIDStart = null;
+
+ try {
+ tokenCUIDStart = configStore.getString(mappingConfigName, null);
+
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+ + mappingConfigName,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: tokenCUIDStart: " + tokenCUIDStart);
+
+ if (tokenCUIDStart != null && tokenCUIDStart.length() > 0) {
+ if (cuid == null) {
+ continue;
+ }
+
+ if (tokenCUIDStart.length() != 20) {
+ continue;
+ }
+
+ if (cuid.compareTo(tokenCUIDStart) < 0) {
+ continue;
+ }
+
+ }
+
+ mappingConfigName = prefix + ".mapping." + mappingId + ".filter.tokenCUID.end";
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: mappingConfigName: " + mappingConfigName);
+
+ String tokenCUIDEnd = null;
+ try {
+ tokenCUIDEnd = configStore.getString(mappingConfigName, null);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+ + mappingConfigName,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: tokenCUIDEnd: " + tokenCUIDEnd);
+
+ if (tokenCUIDEnd != null && tokenCUIDEnd.length() > 0) {
+ if (cuid == null) {
+ continue;
+ }
+
+ if (tokenCUIDEnd.length() != 20) {
+ continue;
+ }
+
+ if (cuid.compareTo(tokenCUIDEnd) > 0) {
+ continue;
+ }
+
+ }
+
+ mappingConfigName = prefix + ".mapping." + mappingId + ".filter.appletMajorVersion";
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: mappingConfigName: " + mappingConfigName);
+
+ String majorVersion = null;
+ String minorVersion = null;
+
+ try {
+ majorVersion = configStore.getString(mappingConfigName, null);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+ + mappingConfigName,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: majorVersion: " + majorVersion);
+ if (majorVersion != null && majorVersion.length() > 0) {
+
+ int major = Integer.parseInt(majorVersion);
+
+ if (major != major_version) {
+ continue;
+ }
+ }
+
+ mappingConfigName = prefix + ".mapping." + mappingId + ".filter.appletMinorVersion";
+
+ CMS.debug("MappingTokenProfileResolver.getTokenType: mappingConfigName: " + mappingConfigName);
+
+ try {
+ minorVersion = configStore.getString(mappingConfigName, null);
+ } catch (EBaseException e) {
+ throw new TPSException(
+ "MappingTokenProfileResolver.getTokenType: Internal error obtaining config value. Config: "
+ + mappingConfigName,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+ CMS.debug("MappingTokenProfileResolver.getTokenType: minorVersion " + minorVersion);
+
+ if (minorVersion != null && minorVersion.length() > 0) {
+
+ int minor = Integer.parseInt(minorVersion);
+
+ if (minor != minor_version) {
+ continue;
+ }
+ }
+
+ //if we make it this far, we have a token type
+ CMS.debug("MappingTokenProfileResolver.getTokenType: Selected Token type: " + targetTokenType);
+ break;
+ }
+
+ if (targetTokenType == null) {
+ CMS.debug("MappingTokenProfileResolver.getTokenType: end found: " + targetTokenType);
+ throw new TPSException("MappingTokenProfileResolver.getTokenType: Can't find token type!",
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_NOT_FOUND);
+ }
+
+ return targetTokenType;
+
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/profile/TokenProfileParams.java b/base/tps/src/org/dogtagpki/server/tps/profile/TokenProfileParams.java
new file mode 100644
index 000000000..d04bc9fb8
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/profile/TokenProfileParams.java
@@ -0,0 +1,145 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.profile;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.dogtagpki.tps.main.TPSException;
+import org.dogtagpki.tps.msg.EndOpMsg.TPSStatus;
+
+import com.netscape.certsrv.apps.CMS;
+
+/**
+ * A class represents profile params information.
+ * <P>
+ *
+ * @version $Revision$, $Date$
+ */
+public class TokenProfileParams {
+
+ public static final String PROFILE_PARAM_MAJOR_VERSION = "pp_major_version";
+ public static final String PROFILE_PARAM_MINOR_VERSION = "pp_minor_version";
+ public static final String PROFILE_PARAM_CUID = "pp_cuid";
+ public static final String PROFILE_PARAM_MSN = "pp_msn";
+ public static final String PROFILE_PARAM_EXT_TOKEN_TYPE = "pp_ext_tokenType";
+ public static final String PROFILE_PARAM_EXT_TOKEN_ATR = "pp_ext_tokenATR";
+
+ private HashMap<String, String> content = new HashMap<String, String>();
+
+ /**
+ * Constructs a meta information.
+ * <P>
+ */
+ public TokenProfileParams() {
+ }
+
+ /**
+ * Returns a short string describing this certificate attribute.
+ * <P>
+ *
+ * @return information about this certificate attribute.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer("[\n" + " Meta information:\n");
+
+ for (Map.Entry<String, String> entry : content.entrySet()) {
+ String key = entry.getKey();
+
+ sb.append(" " + key + " : " + entry.getValue() + "\n");
+ }
+ sb.append("]\n");
+ return sb.toString();
+ }
+
+ /**
+ * Gets a String attribute value.
+ * <P>
+ *
+ * @param name the name of the attribute to return.
+ */
+ public String getString(String name)
+ throws TPSException {
+ String val = content.get(name);
+ if (val == null) {
+ CMS.debug("TokenProfileParams.getString: param null:"+ name);
+ throw new TPSException (
+ "TokenProfileParams.getString: param null:"+ name,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_PARAMS_NOT_FOUND);
+ }
+ return val;
+ }
+
+ /**
+ * Gets an int attribute value.
+ * <P>
+ *
+ * @param name the name of the attribute to return.
+ */
+ public int getInt(String name)
+ throws TPSException {
+ String val = content.get(name);
+ if (val == null) {
+ CMS.debug("TokenProfileParams.getInt: param null:"+ name);
+ throw new TPSException (
+ "TokenProfileParams.getInt: param null:"+ name,
+ TPSStatus.STATUS_ERROR_DEFAULT_TOKENTYPE_PARAMS_NOT_FOUND);
+ }
+ try {
+ int intVal = Integer.parseInt(val);
+ return intVal;
+ } catch (NumberFormatException e) {
+ CMS.debug("TokenProfileParams.getInt: param "+ name + "=" + val + e);
+ throw new TPSException (
+ "TokenProfileParams.getInt: param major_version:"+ e,
+ TPSStatus.STATUS_ERROR_MISCONFIGURATION);
+ }
+ }
+
+ /**
+ * Sets an attribute value.
+ *
+ * @param name the name of the attribute
+ * @param val the attribute value.
+ */
+ public void set(String name, String val) {
+ content.put(name, val);
+ }
+
+ /**
+ * Deletes an attribute value from this AttrSet.
+ * <P>
+ *
+ * @param name the name of the attribute to delete.
+ */
+ public void delete(String name) {
+ content.remove(name);
+ }
+
+ /**
+ * Returns an enumeration of the names of the attributes existing within
+ * this attribute.
+ * <P>
+ *
+ * @return an enumeration of the attribute names.
+ */
+ public Set<String> getElements() {
+ return content.keySet();
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/profile/TokenProfileResolverManager.java b/base/tps/src/org/dogtagpki/server/tps/profile/TokenProfileResolverManager.java
new file mode 100644
index 000000000..b6325fcca
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/profile/TokenProfileResolverManager.java
@@ -0,0 +1,114 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.profile;
+
+import java.util.HashMap;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.registry.IPluginInfo;
+import com.netscape.certsrv.registry.IPluginRegistry;
+
+/**
+ * TokenProfileResolverManager is a class for profile resolver plugin
+ * management
+ *
+ * @author cfu
+ */
+public class TokenProfileResolverManager
+{
+ private static final String TOKEN_PROFILE_RESOLVER_TYPE = "tpsTokenProfileResolver";
+ public static final String PROP_RESOLVER_LIST = "list";
+ public static final String PROP_RESOLVER_CLASS_ID = "class_id";
+
+ protected static final String TOKEN_PROFILE_RESOLVER_CFG = "tokenProfileResolver";
+ protected IPluginRegistry registry = null;
+ protected HashMap<String, BaseTokenProfileResolver> tokenProfileResolvers = null;
+
+ public TokenProfileResolverManager() {
+ tokenProfileResolvers = new HashMap<String, BaseTokenProfileResolver>();
+ }
+
+ /**
+ * initializes all profile resolver plugin instances specified in
+ * <instance-name>/conf/registry.cfg
+ *
+ * configuration e.g.
+ *
+ * registry.cfg:
+ * types=tpsTokenProfileResolver
+ * tpsProfileResolver.ids=mappingTokenProfileResolverImpl
+ * tpsProfileResolver.mappingTokenProfileResolverImpl.class=org.dogtagpki.server.tps.profile.MappingTokenProfileResolver
+ * tpsProfileResolver.mappingTokenProfileResolverImpl.desc=Mapping-based Token profile resolver
+ * tpsProfileResolver.mappingTokenProfileResolverImpl.name=Mapping-based Token profile resolver
+ *
+ * CS.cfg :
+ * registry.file=/var/lib/pki/pki-tomcat/conf/tps/registry.cfg
+ * tokenProfileResolver.list=formatMappingResolver,enrollMappingResolver,pinResetMappingResolver
+ * tokenProfileResolver.formatMappingResolver.class_id=mappingProfileResolverImpl
+ * tokenProfileResolver.formatMappingResolver.[plugin-specific configuration]
+ *
+ * op.format.tokenProfileResolver=formatMappingResolver
+ * ...
+ * op.enroll.tokenProfileResolver=enrollMappingResolver
+ *
+ * Note: "none" indicates no resolver plugin applied
+ * op.format.tokenProfileResolver=none
+ */
+ public void initProfileResolverInstances()
+ throws EBaseException {
+
+ CMS.debug("TokenProfileResolverManager: initProfileResolverInstances(): begins");
+ IConfigStore conf = CMS.getConfigStore();
+ registry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY);
+ if (registry == null) {
+ CMS.debug("TokenProfileResolverManager: initProfileResolverInstances(): registry null");
+ return;
+ }
+
+ IConfigStore prConf = conf.getSubStore(TOKEN_PROFILE_RESOLVER_CFG);
+ String profileList = prConf.getString(PROP_RESOLVER_LIST, "");
+
+ for (String prInst : profileList.split(",")) {
+ String classID = prConf.getString(prInst + "." + PROP_RESOLVER_CLASS_ID);
+ CMS.debug("TokenProfileResolverManager: initProfileResolverInstances(): initializing classID=" + classID);
+ IPluginInfo resolverInfo =
+ registry.getPluginInfo(TOKEN_PROFILE_RESOLVER_TYPE, classID);
+ String resolverClass = resolverInfo.getClassName();
+ BaseTokenProfileResolver resolver = null;
+ try {
+ resolver = (BaseTokenProfileResolver)
+ Class.forName(resolverClass).newInstance();
+ } catch (Exception e) {
+ // throw Exception
+ CMS.debug("TokenProfileResolverManager: resolver plugin Class.forName " +
+ resolverClass + " " + e.toString());
+ throw new EBaseException(e.toString());
+ }
+ resolver.init(prInst);
+ tokenProfileResolvers.put(prInst, resolver);
+ CMS.debug("TokenProfileResolverManager: initProfileResolverInstances(): resolver instance added: " + prInst);
+ }
+ }
+
+ public BaseTokenProfileResolver getResolverInstance(String name) {
+ return tokenProfileResolvers.get(name);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/ActivityService.java b/base/tps/src/org/dogtagpki/server/tps/rest/ActivityService.java
new file mode 100644
index 000000000..6002e7a94
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/ActivityService.java
@@ -0,0 +1,177 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
+import org.dogtagpki.server.tps.dbs.ActivityRecord;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.logging.ActivityCollection;
+import com.netscape.certsrv.logging.ActivityData;
+import com.netscape.certsrv.logging.ActivityResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ActivityService extends PKIService implements ActivityResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public ActivityService() {
+ CMS.debug("ActivityService.<init>()");
+ }
+
+ public ActivityData createActivityData(ActivityRecord activityRecord) {
+
+ ActivityData activityData = new ActivityData();
+ activityData.setID(activityRecord.getId());
+ activityData.setTokenID(activityRecord.getTokenID());
+ activityData.setUserID(activityRecord.getUserID());
+ activityData.setIP(activityRecord.getIP());
+ activityData.setOperation(activityRecord.getOperation());
+ activityData.setResult(activityRecord.getResult());
+ activityData.setMessage(activityRecord.getMessage());
+ activityData.setDate(activityRecord.getDate());
+
+ String activityID = activityRecord.getId();
+ try {
+ activityID = URLEncoder.encode(activityID, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+
+ URI uri = uriInfo.getBaseUriBuilder().path(ActivityResource.class).path("{activityID}").build(activityID);
+ activityData.setLink(new Link("self", uri));
+
+ return activityData;
+ }
+
+ public ActivityRecord createActivityRecord(ActivityData activityData) {
+
+ ActivityRecord activityRecord = new ActivityRecord();
+ activityRecord.setId(activityData.getID());
+ activityRecord.setTokenID(activityData.getTokenID());
+ activityRecord.setUserID(activityData.getUserID());
+ activityRecord.setIP(activityData.getIP());
+ activityRecord.setOperation(activityData.getOperation());
+ activityRecord.setResult(activityData.getResult());
+ activityRecord.setMessage(activityData.getMessage());
+ activityRecord.setDate(activityData.getDate());
+
+ return activityRecord;
+ }
+
+ @Override
+ public Response findActivities(String filter, Integer start, Integer size) {
+
+ CMS.debug("ActivityService.findActivities()");
+
+ if (filter != null && filter.length() < MIN_FILTER_LENGTH) {
+ throw new BadRequestException("Filter is too short.");
+ }
+
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ActivityDatabase database = subsystem.getActivityDatabase();
+
+ Iterator<ActivityRecord> activities = database.findRecords(filter).iterator();
+
+ ActivityCollection response = new ActivityCollection();
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && activities.hasNext(); i++) activities.next();
+
+ // return entries up to the page size
+ for ( ; i<start+size && activities.hasNext(); i++) {
+ response.addEntry(createActivityData(activities.next()));
+ }
+
+ // count the total entries
+ for ( ; activities.hasNext(); i++) activities.next();
+ response.setTotal(i);
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+ response.addLink(new Link("prev", uri));
+ }
+
+ if (start+size < i) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+ response.addLink(new Link("next", uri));
+ }
+
+ return createOKResponse(response);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response getActivity(String activityID) {
+
+ if (activityID == null) throw new BadRequestException("Activity ID is null.");
+
+ CMS.debug("ActivityService.getActivity(\"" + activityID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ActivityDatabase database = subsystem.getActivityDatabase();
+
+ return createOKResponse(createActivityData(database.getRecord(activityID)));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/AuthenticatorService.java b/base/tps/src/org/dogtagpki/server/tps/rest/AuthenticatorService.java
new file mode 100644
index 000000000..d862e261d
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/AuthenticatorService.java
@@ -0,0 +1,350 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.config.AuthenticatorDatabase;
+import org.dogtagpki.server.tps.config.AuthenticatorRecord;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.tps.authenticator.AuthenticatorCollection;
+import com.netscape.certsrv.tps.authenticator.AuthenticatorData;
+import com.netscape.certsrv.tps.authenticator.AuthenticatorResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class AuthenticatorService extends PKIService implements AuthenticatorResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public AuthenticatorService() {
+ CMS.debug("AuthenticatorService.<init>()");
+ }
+
+ public AuthenticatorData createAuthenticatorData(AuthenticatorRecord authenticatorRecord) throws UnsupportedEncodingException {
+
+ String authenticatorID = authenticatorRecord.getID();
+
+ AuthenticatorData authenticatorData = new AuthenticatorData();
+ authenticatorData.setID(authenticatorID);
+ authenticatorData.setStatus(authenticatorRecord.getStatus());
+ authenticatorData.setProperties(authenticatorRecord.getProperties());
+
+ authenticatorID = URLEncoder.encode(authenticatorID, "UTF-8");
+ URI uri = uriInfo.getBaseUriBuilder().path(AuthenticatorResource.class).path("{authenticatorID}").build(authenticatorID);
+ authenticatorData.setLink(new Link("self", uri));
+
+ return authenticatorData;
+ }
+
+ public AuthenticatorRecord createAuthenticatorRecord(AuthenticatorData authenticatorData) {
+
+ AuthenticatorRecord authenticatorRecord = new AuthenticatorRecord();
+ authenticatorRecord.setID(authenticatorData.getID());
+ authenticatorRecord.setStatus(authenticatorData.getStatus());
+ authenticatorRecord.setProperties(authenticatorData.getProperties());
+
+ return authenticatorRecord;
+ }
+
+ @Override
+ public Response findAuthenticators(String filter, Integer start, Integer size) {
+
+ CMS.debug("AuthenticatorService.findAuthenticators()");
+
+ if (filter != null && filter.length() < MIN_FILTER_LENGTH) {
+ throw new BadRequestException("Filter is too short.");
+ }
+
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
+
+ Iterator<AuthenticatorRecord> authenticators = database.findRecords(filter).iterator();
+
+ AuthenticatorCollection response = new AuthenticatorCollection();
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && authenticators.hasNext(); i++) authenticators.next();
+
+ // return entries up to the page size
+ for ( ; i<start+size && authenticators.hasNext(); i++) {
+ response.addEntry(createAuthenticatorData(authenticators.next()));
+ }
+
+ // count the total entries
+ for ( ; authenticators.hasNext(); i++) authenticators.next();
+ response.setTotal(i);
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+ response.addLink(new Link("prev", uri));
+ }
+
+ if (start+size < i) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+ response.addLink(new Link("next", uri));
+ }
+
+ return createOKResponse(response);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response getAuthenticator(String authenticatorID) {
+
+ if (authenticatorID == null) throw new BadRequestException("Authenticator ID is null.");
+
+ CMS.debug("AuthenticatorService.getAuthenticator(\"" + authenticatorID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
+
+ return createOKResponse(createAuthenticatorData(database.getRecord(authenticatorID)));
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response addAuthenticator(AuthenticatorData authenticatorData) {
+
+ if (authenticatorData == null) throw new BadRequestException("Authenticator data is null.");
+
+ CMS.debug("AuthenticatorService.addAuthenticator(\"" + authenticatorData.getID() + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
+
+ String status = authenticatorData.getStatus();
+ Principal principal = servletRequest.getUserPrincipal();
+
+ if (status == null || database.requiresApproval() && !database.canApprove(principal)) {
+ // if status is unspecified or user doesn't have rights to approve, the entry is disabled
+ authenticatorData.setStatus("Disabled");
+ }
+
+ database.addRecord(authenticatorData.getID(), createAuthenticatorRecord(authenticatorData));
+ authenticatorData = createAuthenticatorData(database.getRecord(authenticatorData.getID()));
+
+ return createCreatedResponse(authenticatorData, authenticatorData.getLink().getHref());
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response updateAuthenticator(String authenticatorID, AuthenticatorData authenticatorData) {
+
+ if (authenticatorID == null) throw new BadRequestException("Authenticator ID is null.");
+ if (authenticatorData == null) throw new BadRequestException("Authenticator data is null.");
+
+ CMS.debug("AuthenticatorService.updateAuthenticator(\"" + authenticatorID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
+
+ AuthenticatorRecord record = database.getRecord(authenticatorID);
+
+ // only disabled authenticator can be updated
+ if (!"Disabled".equals(record.getStatus())) {
+ throw new ForbiddenException("Unable to update authenticator " + authenticatorID);
+ }
+
+ // update status if specified
+ String status = authenticatorData.getStatus();
+ if (status != null && !"Disabled".equals(status)) {
+ if (!"Enabled".equals(status)) {
+ throw new ForbiddenException("Invalid authenticator status: " + status);
+ }
+
+ // if user doesn't have rights, set to pending
+ Principal principal = servletRequest.getUserPrincipal();
+ if (database.requiresApproval() && !database.canApprove(principal)) {
+ status = "Pending_Approval";
+ }
+
+ // enable authenticator
+ record.setStatus(status);
+ }
+
+ // update properties if specified
+ Map<String, String> properties = authenticatorData.getProperties();
+ if (properties != null) {
+ record.setProperties(authenticatorData.getProperties());
+ }
+
+ database.updateRecord(authenticatorID, record);
+
+ authenticatorData = createAuthenticatorData(database.getRecord(authenticatorID));
+
+ return createOKResponse(authenticatorData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response changeAuthenticatorStatus(String authenticatorID, String action) {
+
+ if (authenticatorID == null) throw new BadRequestException("Authenticator ID is null.");
+ if (action == null) throw new BadRequestException("Action is null.");
+
+ CMS.debug("AuthenticatorService.changeAuthenticatorStatus(\"" + authenticatorID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
+
+ AuthenticatorRecord record = database.getRecord(authenticatorID);
+ String status = record.getStatus();
+
+ if ("Disabled".equals(status)) {
+ if ("enable".equals(action)) {
+ status = "Enabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else if ("Enabled".equals(status)) {
+ if ("disable".equals(action)) {
+ status = "Disabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else if ("Pending_Approval".equals(status)) {
+ if ("approve".equals(action)) {
+ status = "Enabled";
+ } else if ("reject".equals(action)) {
+ status = "Disabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else {
+ throw new PKIException("Invalid authenticator status: " + status);
+ }
+
+ record.setStatus(status);
+ database.updateRecord(authenticatorID, record);
+
+ AuthenticatorData authenticatorData = createAuthenticatorData(database.getRecord(authenticatorID));
+
+ return createOKResponse(authenticatorData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response removeAuthenticator(String authenticatorID) {
+
+ if (authenticatorID == null) throw new BadRequestException("Authenticator ID is null.");
+
+ CMS.debug("AuthenticatorService.removeAuthenticator(\"" + authenticatorID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ AuthenticatorDatabase database = subsystem.getAuthenticatorDatabase();
+
+ AuthenticatorRecord record = database.getRecord(authenticatorID);
+ String status = record.getStatus();
+
+ if (!"Disabled".equals(status)) {
+ throw new ForbiddenException("Unable to delete authenticator " + authenticatorID);
+ }
+
+ database.removeRecord(authenticatorID);
+
+ return createNoContentResponse();
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/ConnectorService.java b/base/tps/src/org/dogtagpki/server/tps/rest/ConnectorService.java
new file mode 100644
index 000000000..c281265ef
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/ConnectorService.java
@@ -0,0 +1,350 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.config.ConnectorDatabase;
+import org.dogtagpki.server.tps.config.ConnectorRecord;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.tps.connector.ConnectorCollection;
+import com.netscape.certsrv.tps.connector.ConnectorData;
+import com.netscape.certsrv.tps.connector.ConnectorResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ConnectorService extends PKIService implements ConnectorResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public ConnectorService() {
+ CMS.debug("ConnectorService.<init>()");
+ }
+
+ public ConnectorData createConnectorData(ConnectorRecord connectionRecord) throws UnsupportedEncodingException {
+
+ String connectorID = connectionRecord.getID();
+
+ ConnectorData connectorData = new ConnectorData();
+ connectorData.setID(connectorID);
+ connectorData.setStatus(connectionRecord.getStatus());
+ connectorData.setProperties(connectionRecord.getProperties());
+
+ connectorID = URLEncoder.encode(connectorID, "UTF-8");
+ URI uri = uriInfo.getBaseUriBuilder().path(ConnectorResource.class).path("{connectorID}").build(connectorID);
+ connectorData.setLink(new Link("self", uri));
+
+ return connectorData;
+ }
+
+ public ConnectorRecord createConnectorRecord(ConnectorData connectorData) {
+
+ ConnectorRecord connectorRecord = new ConnectorRecord();
+ connectorRecord.setID(connectorData.getID());
+ connectorRecord.setStatus(connectorData.getStatus());
+ connectorRecord.setProperties(connectorData.getProperties());
+
+ return connectorRecord;
+ }
+
+ @Override
+ public Response findConnectors(String filter, Integer start, Integer size) {
+
+ CMS.debug("ConnectorService.findConnectors()");
+
+ if (filter != null && filter.length() < MIN_FILTER_LENGTH) {
+ throw new BadRequestException("Filter is too short.");
+ }
+
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+
+ Iterator<ConnectorRecord> connections = database.findRecords(filter).iterator();
+
+ ConnectorCollection response = new ConnectorCollection();
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && connections.hasNext(); i++) connections.next();
+
+ // return entries up to the page size
+ for ( ; i<start+size && connections.hasNext(); i++) {
+ response.addEntry(createConnectorData(connections.next()));
+ }
+
+ // count the total entries
+ for ( ; connections.hasNext(); i++) connections.next();
+ response.setTotal(i);
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+ response.addLink(new Link("prev", uri));
+ }
+
+ if (start+size < i) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+ response.addLink(new Link("next", uri));
+ }
+
+ return createOKResponse(response);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response getConnector(String connectorID) {
+
+ if (connectorID == null) throw new BadRequestException("Connector ID is null.");
+
+ CMS.debug("ConnectorService.getConnector(\"" + connectorID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+
+ return createOKResponse(createConnectorData(database.getRecord(connectorID)));
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response addConnector(ConnectorData connectorData) {
+
+ if (connectorData == null) throw new BadRequestException("Connector data is null.");
+
+ CMS.debug("ConnectorService.addConnector(\"" + connectorData.getID() + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+
+ String status = connectorData.getStatus();
+ Principal principal = servletRequest.getUserPrincipal();
+
+ if (status == null || database.requiresApproval() && !database.canApprove(principal)) {
+ // if status is unspecified or user doesn't have rights to approve, the entry is disabled
+ connectorData.setStatus("Disabled");
+ }
+
+ database.addRecord(connectorData.getID(), createConnectorRecord(connectorData));
+ connectorData = createConnectorData(database.getRecord(connectorData.getID()));
+
+ return createCreatedResponse(connectorData, connectorData.getLink().getHref());
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response updateConnector(String connectorID, ConnectorData connectorData) {
+
+ if (connectorID == null) throw new BadRequestException("Connector ID is null.");
+ if (connectorData == null) throw new BadRequestException("Connector data is null.");
+
+ CMS.debug("ConnectorService.updateConnector(\"" + connectorID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+
+ ConnectorRecord record = database.getRecord(connectorID);
+
+ // only disabled connector can be updated
+ if (!"Disabled".equals(record.getStatus())) {
+ throw new ForbiddenException("Unable to update connector " + connectorID);
+ }
+
+ // update status if specified
+ String status = connectorData.getStatus();
+ if (status != null && !"Disabled".equals(status)) {
+ if (!"Enabled".equals(status)) {
+ throw new ForbiddenException("Invalid connector status: " + status);
+ }
+
+ // if user doesn't have rights, set to pending
+ Principal principal = servletRequest.getUserPrincipal();
+ if (database.requiresApproval() && !database.canApprove(principal)) {
+ status = "Pending_Approval";
+ }
+
+ // enable connector
+ record.setStatus(status);
+ }
+
+ // update properties if specified
+ Map<String, String> properties = connectorData.getProperties();
+ if (properties != null) {
+ record.setProperties(properties);
+ }
+
+ database.updateRecord(connectorID, record);
+
+ connectorData = createConnectorData(database.getRecord(connectorID));
+
+ return createOKResponse(connectorData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response changeConnectorStatus(String connectorID, String action) {
+
+ if (connectorID == null) throw new BadRequestException("Connector ID is null.");
+ if (action == null) throw new BadRequestException("Action is null.");
+
+ CMS.debug("ConnectorService.changeConnectorStatus(\"" + connectorID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+
+ ConnectorRecord record = database.getRecord(connectorID);
+ String status = record.getStatus();
+
+ if ("Disabled".equals(status)) {
+ if ("enable".equals(action)) {
+ status = "Enabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else if ("Enabled".equals(status)) {
+ if ("disable".equals(action)) {
+ status = "Disabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else if ("Pending_Approval".equals(status)) {
+ if ("approve".equals(action)) {
+ status = "Enabled";
+ } else if ("reject".equals(action)) {
+ status = "Disabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else {
+ throw new PKIException("Invalid connector status: " + status);
+ }
+
+ record.setStatus(status);
+ database.updateRecord(connectorID, record);
+
+ ConnectorData connectorData = createConnectorData(database.getRecord(connectorID));
+
+ return createOKResponse(connectorData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response removeConnector(String connectorID) {
+
+ if (connectorID == null) throw new BadRequestException("Connector ID is null.");
+
+ CMS.debug("ConnectorService.removeConnector(\"" + connectorID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ConnectorDatabase database = subsystem.getConnectorDatabase();
+
+ ConnectorRecord record = database.getRecord(connectorID);
+ String status = record.getStatus();
+
+ if (!"Disabled".equals(status)) {
+ throw new ForbiddenException("Unable to delete connector " + connectorID);
+ }
+
+ database.removeRecord(connectorID);
+
+ return createNoContentResponse();
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/ProfileMappingService.java b/base/tps/src/org/dogtagpki/server/tps/rest/ProfileMappingService.java
new file mode 100644
index 000000000..f3a6f2e38
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/ProfileMappingService.java
@@ -0,0 +1,341 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.config.ProfileMappingDatabase;
+import org.dogtagpki.server.tps.config.ProfileMappingRecord;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.tps.profile.ProfileMappingCollection;
+import com.netscape.certsrv.tps.profile.ProfileMappingData;
+import com.netscape.certsrv.tps.profile.ProfileMappingResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ProfileMappingService extends PKIService implements ProfileMappingResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public ProfileMappingService() {
+ CMS.debug("ProfileMappingService.<init>()");
+ }
+
+ public ProfileMappingData createProfileMappingData(ProfileMappingRecord profileMappingRecord) throws UnsupportedEncodingException {
+
+ String profileMappingID = profileMappingRecord.getID();
+
+ ProfileMappingData profileMappingData = new ProfileMappingData();
+ profileMappingData.setID(profileMappingID);
+ profileMappingData.setStatus(profileMappingRecord.getStatus());
+ profileMappingData.setProperties(profileMappingRecord.getProperties());
+
+ profileMappingID = URLEncoder.encode(profileMappingID, "UTF-8");
+ URI uri = uriInfo.getBaseUriBuilder().path(ProfileMappingResource.class).path("{profileMappingID}").build(profileMappingID);
+ profileMappingData.setLink(new Link("self", uri));
+
+ return profileMappingData;
+ }
+
+ public ProfileMappingRecord createProfileMappingRecord(ProfileMappingData profileMappingData) {
+
+ ProfileMappingRecord profileMappingRecord = new ProfileMappingRecord();
+ profileMappingRecord.setID(profileMappingData.getID());
+ profileMappingRecord.setStatus(profileMappingData.getStatus());
+ profileMappingRecord.setProperties(profileMappingData.getProperties());
+
+ return profileMappingRecord;
+ }
+
+ @Override
+ public Response findProfileMappings(String filter, Integer start, Integer size) {
+
+ CMS.debug("ProfileMappingService.findProfileMappings()");
+
+ if (filter != null && filter.length() < MIN_FILTER_LENGTH) {
+ throw new BadRequestException("Filter is too short.");
+ }
+
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
+
+ Iterator<ProfileMappingRecord> profileMappings = database.findRecords(filter).iterator();
+
+ ProfileMappingCollection response = new ProfileMappingCollection();
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && profileMappings.hasNext(); i++) profileMappings.next();
+
+ // return entries up to the page size
+ for ( ; i<start+size && profileMappings.hasNext(); i++) {
+ response.addEntry(createProfileMappingData(profileMappings.next()));
+ }
+
+ // count the total entries
+ for ( ; profileMappings.hasNext(); i++) profileMappings.next();
+ response.setTotal(i);
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+ response.addLink(new Link("prev", uri));
+ }
+
+ if (start+size < i) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+ response.addLink(new Link("next", uri));
+ }
+
+ return createOKResponse(response);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response getProfileMapping(String profileMappingID) {
+
+ CMS.debug("ProfileMappingService.getProfileMapping(\"" + profileMappingID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
+
+ return createOKResponse(createProfileMappingData(database.getRecord(profileMappingID)));
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response addProfileMapping(ProfileMappingData profileMappingData) {
+
+ CMS.debug("ProfileMappingService.addProfileMapping(\"" + profileMappingData.getID() + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
+
+ String status = profileMappingData.getStatus();
+ Principal principal = servletRequest.getUserPrincipal();
+
+ if (status == null || database.requiresApproval() && !database.canApprove(principal)) {
+ // if status is unspecified or user doesn't have rights to approve, the entry is disabled
+ profileMappingData.setStatus("Disabled");
+ }
+
+ database.addRecord(profileMappingData.getID(), createProfileMappingRecord(profileMappingData));
+ profileMappingData = createProfileMappingData(database.getRecord(profileMappingData.getID()));
+
+ return createCreatedResponse(profileMappingData, profileMappingData.getLink().getHref());
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response updateProfileMapping(String profileMappingID, ProfileMappingData profileMappingData) {
+
+ CMS.debug("ProfileMappingService.updateProfileMapping(\"" + profileMappingID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
+
+ ProfileMappingRecord record = database.getRecord(profileMappingID);
+
+ // only disabled profile mapping can be updated
+ if (!"Disabled".equals(record.getStatus())) {
+ throw new ForbiddenException("Unable to update profile mapping " + profileMappingID);
+ }
+
+ // update status if specified
+ String status = profileMappingData.getStatus();
+ if (status != null && !"Disabled".equals(status)) {
+ if (!"Enabled".equals(status)) {
+ throw new ForbiddenException("Invalid profile mapping status: " + status);
+ }
+
+ // if user doesn't have rights, set to pending
+ Principal principal = servletRequest.getUserPrincipal();
+ if (database.requiresApproval() && !database.canApprove(principal)) {
+ status = "Pending_Approval";
+ }
+
+ // enable profile mapping
+ record.setStatus(status);
+ }
+
+ // update properties if specified
+ Map<String, String> properties = profileMappingData.getProperties();
+ if (properties != null) {
+ record.setProperties(properties);
+ }
+
+ database.updateRecord(profileMappingID, record);
+
+ profileMappingData = createProfileMappingData(database.getRecord(profileMappingID));
+
+ return createOKResponse(profileMappingData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response changeProfileMappingStatus(String profileMappingID, String action) {
+
+ if (profileMappingID == null) throw new BadRequestException("Profile mapping ID is null.");
+ if (action == null) throw new BadRequestException("Action is null.");
+
+ CMS.debug("ProfileMappingService.changeProfileMappingStatus(\"" + profileMappingID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
+
+ ProfileMappingRecord record = database.getRecord(profileMappingID);
+ String status = record.getStatus();
+
+ if ("Disabled".equals(status)) {
+ if ("enable".equals(action)) {
+ status = "Enabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else if ("Enabled".equals(status)) {
+ if ("disable".equals(action)) {
+ status = "Disabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else if ("Pending_Approval".equals(status)) {
+ if ("approve".equals(action)) {
+ status = "Enabled";
+ } else if ("reject".equals(action)) {
+ status = "Disabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else {
+ throw new PKIException("Invalid profile mapping status: " + status);
+ }
+
+ record.setStatus(status);
+ database.updateRecord(profileMappingID, record);
+
+ ProfileMappingData profileMappingData = createProfileMappingData(database.getRecord(profileMappingID));
+
+ return createOKResponse(profileMappingData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response removeProfileMapping(String profileMappingID) {
+
+ CMS.debug("ProfileMappingService.removeProfileMapping(\"" + profileMappingID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileMappingDatabase database = subsystem.getProfileMappingDatabase();
+
+ ProfileMappingRecord record = database.getRecord(profileMappingID);
+ String status = record.getStatus();
+
+ if (!"Disabled".equals(status)) {
+ throw new ForbiddenException("Unable to delete profile mapping " + profileMappingID);
+ }
+
+ database.removeRecord(profileMappingID);
+
+ return createNoContentResponse();
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/ProfileService.java b/base/tps/src/org/dogtagpki/server/tps/rest/ProfileService.java
new file mode 100644
index 000000000..e5bfd4663
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/ProfileService.java
@@ -0,0 +1,351 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.config.ProfileDatabase;
+import org.dogtagpki.server.tps.config.ProfileRecord;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.tps.profile.ProfileCollection;
+import com.netscape.certsrv.tps.profile.ProfileData;
+import com.netscape.certsrv.tps.profile.ProfileResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class ProfileService extends PKIService implements ProfileResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public ProfileService() {
+ CMS.debug("ProfileService.<init>()");
+ }
+
+ public ProfileData createProfileData(ProfileRecord profileRecord) throws UnsupportedEncodingException {
+
+ String profileID = profileRecord.getID();
+
+ ProfileData profileData = new ProfileData();
+ profileData.setID(profileID);
+ profileData.setStatus(profileRecord.getStatus());
+ profileData.setProperties(profileRecord.getProperties());
+
+ profileID = URLEncoder.encode(profileID, "UTF-8");
+ URI uri = uriInfo.getBaseUriBuilder().path(ProfileResource.class).path("{profileID}").build(profileID);
+ profileData.setLink(new Link("self", uri));
+
+ return profileData;
+ }
+
+ public ProfileRecord createProfileRecord(ProfileData profileData) {
+
+ ProfileRecord profileRecord = new ProfileRecord();
+ profileRecord.setID(profileData.getID());
+ profileRecord.setStatus(profileData.getStatus());
+ profileRecord.setProperties(profileData.getProperties());
+
+ return profileRecord;
+ }
+
+ @Override
+ public Response findProfiles(String filter, Integer start, Integer size) {
+
+ CMS.debug("ProfileService.findProfiles()");
+
+ if (filter != null && filter.length() < MIN_FILTER_LENGTH) {
+ throw new BadRequestException("Filter is too short.");
+ }
+
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileDatabase database = subsystem.getProfileDatabase();
+
+ Iterator<ProfileRecord> profiles = database.findRecords(filter).iterator();
+
+ ProfileCollection response = new ProfileCollection();
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && profiles.hasNext(); i++) profiles.next();
+
+ // return entries up to the page size
+ for ( ; i<start+size && profiles.hasNext(); i++) {
+ response.addEntry(createProfileData(profiles.next()));
+ }
+
+ // count the total entries
+ for ( ; profiles.hasNext(); i++) profiles.next();
+ response.setTotal(i);
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+ response.addLink(new Link("prev", uri));
+ }
+
+ if (start+size < i) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+ response.addLink(new Link("next", uri));
+ }
+
+ return createOKResponse(response);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response getProfile(String profileID) {
+
+ if (profileID == null) throw new BadRequestException("Profile ID is null.");
+
+ CMS.debug("ProfileService.getProfile(\"" + profileID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileDatabase database = subsystem.getProfileDatabase();
+
+ return createOKResponse(createProfileData(database.getRecord(profileID)));
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response addProfile(ProfileData profileData) {
+
+ if (profileData == null) throw new BadRequestException("Profile data is null.");
+
+ CMS.debug("ProfileService.addProfile(\"" + profileData.getID() + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileDatabase database = subsystem.getProfileDatabase();
+
+ String status = profileData.getStatus();
+ Principal principal = servletRequest.getUserPrincipal();
+
+ if (status == null || database.requiresApproval() && !database.canApprove(principal)) {
+ // if status is unspecified or user doesn't have rights to approve, the entry is disabled
+ profileData.setStatus("Disabled");
+ }
+
+ database.addRecord(profileData.getID(), createProfileRecord(profileData));
+
+ profileData = createProfileData(database.getRecord(profileData.getID()));
+
+ return createCreatedResponse(profileData, profileData.getLink().getHref());
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response updateProfile(String profileID, ProfileData profileData) {
+
+ if (profileID == null) throw new BadRequestException("Profile ID is null.");
+ if (profileData == null) throw new BadRequestException("Profile data is null.");
+
+ CMS.debug("ProfileService.updateProfile(\"" + profileID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileDatabase database = subsystem.getProfileDatabase();
+
+ ProfileRecord record = database.getRecord(profileID);
+
+ // only disabled profile can be updated
+ if (!"Disabled".equals(record.getStatus())) {
+ throw new ForbiddenException("Unable to update profile " + profileID);
+ }
+
+ // update status if specified
+ String status = profileData.getStatus();
+ if (status != null && !"Disabled".equals(status)) {
+ if (!"Enabled".equals(status)) {
+ throw new ForbiddenException("Invalid profile status: " + status);
+ }
+
+ // if user doesn't have rights, set to pending
+ Principal principal = servletRequest.getUserPrincipal();
+ if (database.requiresApproval() && !database.canApprove(principal)) {
+ status = "Pending_Approval";
+ }
+
+ // enable profile
+ record.setStatus(status);
+ }
+
+ // update properties if specified
+ Map<String, String> properties = profileData.getProperties();
+ if (properties != null) {
+ record.setProperties(properties);
+ }
+
+ database.updateRecord(profileID, record);
+
+ profileData = createProfileData(database.getRecord(profileID));
+
+ return createOKResponse(profileData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response changeProfileStatus(String profileID, String action) {
+
+ if (profileID == null) throw new BadRequestException("Profile ID is null.");
+ if (action == null) throw new BadRequestException("Action is null.");
+
+ CMS.debug("ProfileService.changeProfileStatus(\"" + profileID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileDatabase database = subsystem.getProfileDatabase();
+
+ ProfileRecord record = database.getRecord(profileID);
+ String status = record.getStatus();
+
+ if ("Disabled".equals(status)) {
+ if ("enable".equals(action)) {
+ status = "Enabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else if ("Enabled".equals(status)) {
+ if ("disable".equals(action)) {
+ status = "Disabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else if ("Pending_Approval".equals(status)) {
+ if ("approve".equals(action)) {
+ status = "Enabled";
+ } else if ("reject".equals(action)) {
+ status = "Disabled";
+ } else {
+ throw new BadRequestException("Invalid action: " + action);
+ }
+
+ } else {
+ throw new PKIException("Invalid profile status: " + status);
+ }
+
+ record.setStatus(status);
+ database.updateRecord(profileID, record);
+
+ ProfileData profileData = createProfileData(database.getRecord(profileID));
+
+ return createOKResponse(profileData);
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response removeProfile(String profileID) {
+
+ if (profileID == null) throw new BadRequestException("Profile ID is null.");
+
+ CMS.debug("ProfileService.removeProfile(\"" + profileID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ ProfileDatabase database = subsystem.getProfileDatabase();
+
+ ProfileRecord record = database.getRecord(profileID);
+ String status = record.getStatus();
+
+ if (!"Disabled".equals(status)) {
+ throw new ForbiddenException("Unable to delete profile " + profileID);
+ }
+
+ database.removeRecord(profileID);
+
+ return createNoContentResponse();
+
+ } catch (PKIException e) {
+ throw e;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TPSApplication.java b/base/tps/src/org/dogtagpki/server/tps/rest/TPSApplication.java
new file mode 100644
index 000000000..70c8afd02
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TPSApplication.java
@@ -0,0 +1,105 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.rest;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+import org.dogtagpki.server.rest.ACLInterceptor;
+import org.dogtagpki.server.rest.AccountService;
+import org.dogtagpki.server.rest.AuditService;
+import org.dogtagpki.server.rest.AuthMethodInterceptor;
+import org.dogtagpki.server.rest.GroupService;
+import org.dogtagpki.server.rest.PKIExceptionMapper;
+import org.dogtagpki.server.rest.MessageFormatInterceptor;
+import org.dogtagpki.server.rest.SelfTestService;
+import org.dogtagpki.server.rest.SystemCertService;
+import org.dogtagpki.server.rest.UserService;
+import org.dogtagpki.server.tps.config.ConfigService;
+
+/**
+ * @author Endi S. Dewata <edewata@redhat.com>
+ */
+public class TPSApplication extends Application {
+
+ private Set<Object> singletons = new LinkedHashSet<Object>();
+ private Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
+
+ public TPSApplication() {
+
+ // account
+ classes.add(AccountService.class);
+
+ // audit
+ classes.add(AuditService.class);
+
+ // installer
+ classes.add(TPSInstallerService.class);
+
+ // user and group management
+ classes.add(GroupService.class);
+ classes.add(UserService.class);
+
+ // system certs
+ classes.add(SystemCertService.class);
+
+ // activities
+ classes.add(ActivityService.class);
+
+ // authenticators
+ classes.add(AuthenticatorService.class);
+
+ // certificates
+ classes.add(TPSCertService.class);
+
+ // config
+ classes.add(ConfigService.class);
+
+ // connections
+ classes.add(ConnectorService.class);
+
+ // profiles
+ classes.add(ProfileService.class);
+ classes.add(ProfileMappingService.class);
+
+ // selftests
+ classes.add(SelfTestService.class);
+
+ // tokens
+ classes.add(TokenService.class);
+
+ // exception mapper
+ classes.add(PKIExceptionMapper.class);
+
+ // interceptors
+ singletons.add(new AuthMethodInterceptor());
+ singletons.add(new ACLInterceptor());
+ singletons.add(new MessageFormatInterceptor());
+ }
+
+ public Set<Class<?>> getClasses() {
+ return classes;
+ }
+
+ public Set<Object> getSingletons() {
+ return singletons;
+ }
+
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TPSCertService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TPSCertService.java
new file mode 100644
index 000000000..75314cd5d
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TPSCertService.java
@@ -0,0 +1,179 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.dbs.TPSCertDatabase;
+import org.dogtagpki.server.tps.dbs.TPSCertRecord;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.tps.cert.TPSCertCollection;
+import com.netscape.certsrv.tps.cert.TPSCertData;
+import com.netscape.certsrv.tps.cert.TPSCertResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class TPSCertService extends PKIService implements TPSCertResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public TPSCertService() {
+ System.out.println("TPSCertService.<init>()");
+ }
+
+ public TPSCertData createCertData(TPSCertRecord certRecord) {
+
+ TPSCertData certData = new TPSCertData();
+ certData.setID(certRecord.getId());
+ certData.setSerialNumber(certRecord.getSerialNumber());
+ certData.setSubject(certRecord.getSubject());
+ certData.setTokenID(certRecord.getTokenID());
+ certData.setKeyType(certRecord.getKeyType());
+ certData.setStatus(certRecord.getStatus());
+ certData.setUserID(certRecord.getUserID());
+ certData.setCreateTime(certRecord.getCreateTime());
+ certData.setModifyTime(certRecord.getModifyTime());
+
+ String certID = certRecord.getId();
+ try {
+ certID = URLEncoder.encode(certID, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+
+ URI uri = uriInfo.getBaseUriBuilder().path(TPSCertResource.class).path("{certID}").build(certID);
+ certData.setLink(new Link("self", uri));
+
+ return certData;
+ }
+
+ public TPSCertRecord createCertRecord(TPSCertData certData) {
+
+ TPSCertRecord certRecord = new TPSCertRecord();
+ certRecord.setId(certData.getID());
+ certRecord.setSerialNumber(certData.getSerialNumber());
+ certRecord.setSubject(certData.getSubject());
+ certRecord.setTokenID(certData.getTokenID());
+ certRecord.setKeyType(certData.getKeyType());
+ certRecord.setStatus(certData.getStatus());
+ certRecord.setUserID(certData.getUserID());
+ certRecord.setCreateTime(certData.getCreateTime());
+ certRecord.setModifyTime(certData.getModifyTime());
+
+ return certRecord;
+ }
+
+ @Override
+ public Response findCerts(String filter, Integer start, Integer size) {
+
+ System.out.println("TPSCertService.findCerts()");
+
+ if (filter != null && filter.length() < MIN_FILTER_LENGTH) {
+ throw new BadRequestException("Filter is too short.");
+ }
+
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TPSCertDatabase database = subsystem.getCertDatabase();
+
+ Iterator<TPSCertRecord> activities = database.findRecords(filter).iterator();
+
+ TPSCertCollection response = new TPSCertCollection();
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && activities.hasNext(); i++) activities.next();
+
+ // return entries up to the page size
+ for ( ; i<start+size && activities.hasNext(); i++) {
+ response.addEntry(createCertData(activities.next()));
+ }
+
+ // count the total entries
+ for ( ; activities.hasNext(); i++) activities.next();
+ response.setTotal(i);
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+ response.addLink(new Link("prev", uri));
+ }
+
+ if (start+size < i) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+ response.addLink(new Link("next", uri));
+ }
+
+ return createOKResponse(response);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response getCert(String certID) {
+
+ if (certID == null) throw new BadRequestException("Certificate ID is null.");
+
+ System.out.println("TPSCertService.getCert(\"" + certID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TPSCertDatabase database = subsystem.getCertDatabase();
+
+ return createOKResponse(createCertData(database.getRecord(certID)));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java
new file mode 100644
index 000000000..9c4943b9f
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TPSInstallerService.java
@@ -0,0 +1,153 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2014 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package org.dogtagpki.server.tps.rest;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+
+import org.dogtagpki.server.rest.SystemConfigService;
+import org.dogtagpki.server.tps.installer.TPSInstaller;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.system.ConfigurationRequest;
+import com.netscape.certsrv.system.SystemCertData;
+import com.netscape.cms.servlet.csadmin.ConfigurationUtils;
+
+/**
+ * @author alee
+ *
+ */
+public class TPSInstallerService extends SystemConfigService {
+
+
+ public TPSInstallerService() throws EBaseException {
+ }
+
+ @Override
+ public void configureSubsystem(ConfigurationRequest request,
+ Collection<String> certList, String token, String domainXML) {
+
+ super.configureSubsystem(request, certList, token, domainXML);
+
+ // get subsystem certificate nickname
+ String nickname = null;
+ for (SystemCertData cert : request.getSystemCerts()) {
+ if (cert.getTag().equals("subsystem")) {
+ nickname = cert.getNickname();
+ break;
+ }
+ }
+
+ if (nickname == null || nickname.isEmpty()) {
+ throw new BadRequestException("No nickname provided for subsystem certificate");
+ }
+
+ // CA Info Panel
+ configureCAConnector(request, nickname);
+
+ // TKS Info Panel
+ configureTKSConnector(request, nickname);
+
+ //DRM Info Panel
+ configureKRAConnector(request, nickname);
+
+ //AuthDBPanel
+ ConfigurationUtils.updateAuthdbInfo(request.getAuthdbBaseDN(),
+ request.getAuthdbHost(), request.getAuthdbPort(),
+ request.getAuthdbSecureConn());
+ }
+
+ public void configureCAConnector(ConfigurationRequest request, String nickname) {
+
+ // TODO: get installer from session
+ TPSInstaller installer = new TPSInstaller();
+ installer.configureCAConnector(request.getCaUri(), nickname);
+ }
+
+ public void configureTKSConnector(ConfigurationRequest request, String nickname) {
+
+ // TODO: get installer from session
+ TPSInstaller installer = new TPSInstaller();
+ installer.configureTKSConnector(request.getTksUri(), nickname);
+ }
+
+ public void configureKRAConnector(ConfigurationRequest request, String nickname) {
+
+ boolean keygen = request.getEnableServerSideKeyGen().equalsIgnoreCase("true");
+
+ // TODO: get installer from session
+ TPSInstaller installer = new TPSInstaller();
+ installer.configureKRAConnector(keygen, request.getKraUri(), nickname);
+ }
+
+ @Override
+ public void configureDatabase(ConfigurationRequest request) {
+
+ super.configureDatabase(request);
+
+ cs.putString("tokendb.activityBaseDN", "ou=Activities," + request.getBaseDN());
+ cs.putString("tokendb.baseDN", "ou=Tokens," + request.getBaseDN());
+ cs.putString("tokendb.certBaseDN", "ou=Certificates," + request.getBaseDN());
+ cs.putString("tokendb.userBaseDN", request.getBaseDN());
+ cs.putString("tokendb.hostport", request.getDsHost() + ":" + request.getDsPort());
+ }
+
+ @Override
+ public void finalizeConfiguration(ConfigurationRequest request) {
+
+ super.finalizeConfiguration(request);
+
+ try {
+ ConfigurationUtils.addProfilesToTPSUser(request.getAdminUID());
+
+ URI secdomainURI = new URI(request.getSecurityDomainUri());
+
+ // register TPS with CA
+ URI caURI = request.getCaUri();
+ ConfigurationUtils.registerUser(secdomainURI, caURI, "ca");
+
+ // register TPS with TKS
+ URI tksURI = request.getTksUri();
+ ConfigurationUtils.registerUser(secdomainURI, tksURI, "tks");
+
+ if (request.getEnableServerSideKeyGen().equalsIgnoreCase("true")) {
+ URI kraURI = request.getKraUri();
+ ConfigurationUtils.registerUser(secdomainURI, kraURI, "kra");
+ String transportCert = ConfigurationUtils.getTransportCert(secdomainURI, kraURI);
+ ConfigurationUtils.exportTransportCert(secdomainURI, tksURI, transportCert);
+ }
+
+ // generate shared secret from the tks
+ ConfigurationUtils.getSharedSecret(
+ tksURI.getHost(),
+ tksURI.getPort(),
+ Boolean.getBoolean(request.getImportSharedSecret()));
+
+ } catch (URISyntaxException e) {
+ throw new BadRequestException("Invalid URI for CA, TKS or KRA");
+
+ } catch (Exception e) {
+ CMS.debug(e);
+ throw new PKIException("Errors in registering TPS to CA, TKS or KRA: " + e);
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
new file mode 100644
index 000000000..a58447089
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/rest/TokenService.java
@@ -0,0 +1,562 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+import org.dogtagpki.server.tps.dbs.ActivityDatabase;
+import org.dogtagpki.server.tps.dbs.TokenDatabase;
+import org.dogtagpki.server.tps.dbs.TokenRecord;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.tps.token.TokenCollection;
+import com.netscape.certsrv.tps.token.TokenData;
+import com.netscape.certsrv.tps.token.TokenResource;
+import com.netscape.certsrv.tps.token.TokenStatus;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class TokenService extends PKIService implements TokenResource {
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ public Map<TokenStatus, Collection<TokenStatus>> transitions = new HashMap<TokenStatus, Collection<TokenStatus>>();
+
+ public TokenService() throws Exception {
+ CMS.debug("TokenService.<init>()");
+ IConfigStore configStore = CMS.getConfigStore();
+
+ // load allowed token state transitions
+ CMS.debug("TokenService: allowed transitions:");
+
+ for (String transition : configStore.getString("tokendb.allowedTransitions").split(",")) {
+ String states[] = transition.split(":");
+ TokenStatus fromState = TokenStatus.fromInt(Integer.valueOf(states[0]));
+ TokenStatus toState = TokenStatus.fromInt(Integer.valueOf(states[1]));
+ CMS.debug("TokenService: - " + fromState + " to " + toState);
+
+ Collection<TokenStatus> nextStates = transitions.get(fromState);
+ if (nextStates == null) {
+ nextStates = new HashSet<TokenStatus>();
+ transitions.put(fromState, nextStates);
+ }
+ nextStates.add(toState);
+ }
+
+ }
+
+ public TokenStatus getTokenStatus(TokenRecord tokenRecord) {
+ String status = tokenRecord.getStatus();
+
+ if ("uninitialized".equals(status)) {
+ return TokenStatus.UNINITIALIZED;
+
+ } else if ("active".equals(status)) {
+ return TokenStatus.ACTIVE;
+
+ } else if ("lost".equals(status)) {
+ String reason = tokenRecord.getReason();
+
+ if ("keyCompromise".equals(reason)) {
+ return TokenStatus.PERM_LOST;
+
+ } else if ("destroyed".equals(reason)) {
+ return TokenStatus.DAMAGED;
+
+ } else if ("onHold".equals(reason)) {
+ return TokenStatus.TEMP_LOST;
+ }
+
+ } else if ("terminated".equals(status)) {
+ return TokenStatus.TERMINATED;
+ }
+
+ return TokenStatus.PERM_LOST;
+ }
+
+ public void setTokenStatus(TokenRecord tokenRecord, TokenStatus tokenState) throws Exception {
+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID);
+
+ switch (tokenState) {
+ case UNINITIALIZED:
+ tokenRecord.setStatus("uninitialized");
+ tokenRecord.setReason(null);
+ break;
+ case ACTIVE:
+ String origStatus = tokenRecord.getStatus();
+ String origReason = tokenRecord.getReason();
+ if (origStatus.equalsIgnoreCase("lost") &&
+ origReason.equalsIgnoreCase("onHold")) {
+ //unrevoke certs
+ tps.tdb.unRevokeCertsByCUID(tokenRecord.getId());
+ }
+
+ tokenRecord.setStatus("active");
+ tokenRecord.setReason(null);
+ break;
+ case PERM_LOST:
+ case TEMP_LOST_PERM_LOST:
+ tokenRecord.setStatus("lost");
+ tokenRecord.setReason("keyCompromise");
+
+ //revoke certs
+ tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "keyCompromise");
+ break;
+ case DAMAGED:
+ tokenRecord.setStatus("lost");
+ tokenRecord.setReason("destroyed");
+
+ //revoke certs
+ tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "destroyed");
+
+ break;
+ case TEMP_LOST:
+ tokenRecord.setStatus("lost");
+ tokenRecord.setReason("onHold");
+
+ // put certs onHold
+ tps.tdb.revokeCertsByCUID(tokenRecord.getId(), "onHold");
+ break;
+ case TERMINATED:
+ String reason = "keyCompromise";
+ String origStatus2 = tokenRecord.getStatus();
+ String origReason2 = tokenRecord.getReason();
+ // temp token looks at "onHold"
+ if (origStatus2.equalsIgnoreCase("lost") &&
+ origReason2.equalsIgnoreCase("onHold")) {
+ reason = "onHold";
+ }
+ tokenRecord.setStatus("terminated");
+ tokenRecord.setReason(reason);
+
+ //revoke certs
+ tps.tdb.revokeCertsByCUID(tokenRecord.getId(), reason) ;
+ break;
+ default:
+ throw new PKIException("Unsupported token state: " + tokenState);
+ }
+
+ }
+
+ public TokenData createTokenData(TokenRecord tokenRecord) {
+
+ TokenData tokenData = new TokenData();
+ tokenData.setID(tokenRecord.getId());
+ tokenData.setTokenID(tokenRecord.getId());
+ tokenData.setUserID(tokenRecord.getUserID());
+ tokenData.setType(tokenRecord.getType());
+ tokenData.setStatus(getTokenStatus(tokenRecord));
+ tokenData.setAppletID(tokenRecord.getAppletID());
+ tokenData.setKeyInfo(tokenRecord.getKeyInfo());
+ tokenData.setPolicy(tokenRecord.getPolicy());
+ tokenData.setCreateTimestamp(tokenRecord.getCreateTimestamp());
+ tokenData.setModifyTimestamp(tokenRecord.getModifyTimestamp());
+
+ String tokenID = tokenRecord.getId();
+ try {
+ tokenID = URLEncoder.encode(tokenID, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+
+ URI uri = uriInfo.getBaseUriBuilder().path(TokenResource.class).path("{tokenID}").build(tokenID);
+ tokenData.setLink(new Link("self", uri));
+
+ return tokenData;
+ }
+
+ public TokenRecord createTokenRecord(TokenData tokenData) throws Exception {
+
+ TokenRecord tokenRecord = new TokenRecord();
+ tokenRecord.setId(tokenData.getID());
+ tokenRecord.setUserID(tokenData.getUserID());
+ tokenRecord.setType(tokenData.getType());
+ setTokenStatus(tokenRecord, tokenData.getStatus());
+ tokenRecord.setAppletID(tokenData.getAppletID());
+ tokenRecord.setKeyInfo(tokenData.getKeyInfo());
+ tokenRecord.setPolicy(tokenData.getPolicy());
+ tokenRecord.setCreateTimestamp(tokenData.getCreateTimestamp());
+ tokenRecord.setModifyTimestamp(tokenData.getModifyTimestamp());
+
+ return tokenRecord;
+ }
+
+ @Override
+ public Response findTokens(String filter, Integer start, Integer size) {
+
+ CMS.debug("TokenService.findTokens()");
+
+ if (filter != null && filter.length() < MIN_FILTER_LENGTH) {
+ throw new BadRequestException("Filter is too short.");
+ }
+
+ start = start == null ? 0 : start;
+ size = size == null ? DEFAULT_SIZE : size;
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TokenDatabase database = subsystem.getTokenDatabase();
+
+ Iterator<TokenRecord> tokens = database.findRecords(filter).iterator();
+
+ TokenCollection response = new TokenCollection();
+ int i = 0;
+
+ // skip to the start of the page
+ for ( ; i<start && tokens.hasNext(); i++) tokens.next();
+
+ // return entries up to the page size
+ for ( ; i<start+size && tokens.hasNext(); i++) {
+ response.addEntry(createTokenData(tokens.next()));
+ }
+
+ // count the total entries
+ for ( ; tokens.hasNext(); i++) tokens.next();
+ response.setTotal(i);
+
+ if (start > 0) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", Math.max(start-size, 0)).build();
+ response.addLink(new Link("prev", uri));
+ }
+
+ if (start+size < i) {
+ URI uri = uriInfo.getRequestUriBuilder().replaceQueryParam("start", start+size).build();
+ response.addLink(new Link("next", uri));
+ }
+
+ return createOKResponse(response);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response getToken(String tokenID) {
+
+ if (tokenID == null) throw new BadRequestException("Token ID is null.");
+
+ CMS.debug("TokenService.getToken(\"" + tokenID + "\")");
+
+ try {
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TokenDatabase database = subsystem.getTokenDatabase();
+
+ return createOKResponse(createTokenData(database.getRecord(tokenID)));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new PKIException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Response addToken(TokenData tokenData) {
+
+ if (tokenData == null) throw new BadRequestException("Token data is null.");
+
+ String tokenID = tokenData.getTokenID();
+ CMS.debug("TokenService.addToken(\"" + tokenID + "\")");
+
+ String remoteUser = servletRequest.getRemoteUser();
+ String ipAddress = servletRequest.getRemoteAddr();
+
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TokenRecord tokenRecord = null;
+ String msg = "add token";
+
+ try {
+ TokenDatabase database = subsystem.getTokenDatabase();
+
+ // new tokens are uninitialized when created
+ tokenData.setStatus(TokenStatus.UNINITIALIZED);
+
+ tokenRecord = createTokenRecord(tokenData);
+ tokenRecord.setId(tokenID);
+ database.addRecord(tokenID, tokenRecord);
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_ADD, tokenRecord,
+ ipAddress, msg, "success", remoteUser);
+ tokenData = createTokenData(database.getRecord(tokenID));
+
+ return createCreatedResponse(tokenData, tokenData.getLink().getHref());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_ADD, tokenRecord,
+ ipAddress, msg, "failure", remoteUser);
+ msg = msg + ":" + e;
+
+ throw new PKIException(msg);
+ }
+ }
+
+ @Override
+ public Response replaceToken(String tokenID, TokenData tokenData) {
+
+ if (tokenID == null) throw new BadRequestException("Token ID is null.");
+ if (tokenData == null) throw new BadRequestException("Token data is null.");
+
+ CMS.debug("TokenService.replaceToken(\"" + tokenID + "\")");
+
+ String remoteUser = servletRequest.getRemoteUser();
+ String ipAddress = servletRequest.getRemoteAddr();
+
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TokenRecord tokenRecord = null;
+ String msg = "replace token";
+ try {
+ TokenDatabase database = subsystem.getTokenDatabase();
+
+ tokenRecord = database.getRecord(tokenID);
+ tokenRecord.setUserID(remoteUser);
+ tokenRecord.setType(tokenData.getType());
+ tokenRecord.setAppletID(tokenData.getAppletID());
+ tokenRecord.setKeyInfo(tokenData.getKeyInfo());
+ tokenRecord.setPolicy(tokenData.getPolicy());
+ database.updateRecord(tokenID, tokenRecord);
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
+ ipAddress, msg, "success", remoteUser);
+
+ tokenData = createTokenData(database.getRecord(tokenID));
+
+ return createOKResponse(tokenData);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
+ ipAddress, msg, "failure",
+ remoteUser);
+ msg = msg + ":" + e;
+
+ throw new PKIException(msg);
+ }
+ }
+
+ @Override
+ public Response modifyToken(String tokenID, TokenData tokenData) {
+
+ if (tokenID == null) throw new BadRequestException("Token ID is null.");
+ if (tokenData == null) throw new BadRequestException("Token data is null.");
+
+ CMS.debug("TokenService.modifyToken(\"" + tokenID + "\")");
+
+ String remoteUser = servletRequest.getRemoteUser();
+ String ipAddress = servletRequest.getRemoteAddr();
+
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TokenRecord tokenRecord = null;
+ String msg = "modify token";
+ try {
+ TokenDatabase database = subsystem.getTokenDatabase();
+
+ // get existing record
+ tokenRecord = database.getRecord(tokenID);
+
+ // update user ID if specified
+ String userID = tokenData.getUserID();
+ if (userID != null) {
+ if (userID.equals("")) { // remove value if empty
+ tokenRecord.setUserID(null);
+ } else { // otherwise replace value
+ tokenRecord.setUserID(userID);
+ }
+ }
+
+ // update type if specified
+ String type = tokenData.getType();
+ if (type != null) {
+ if (type.equals("")) { // remove value if empty
+ tokenRecord.setType(null);
+ } else { // otherwise replace value
+ tokenRecord.setType(type);
+ }
+ }
+
+ // update applet ID if specified
+ String appletID = tokenData.getAppletID();
+ if (appletID != null) {
+ if (appletID.equals("")) { // remove value if empty
+ tokenRecord.setAppletID(null);
+ } else { // otherwise replace value
+ tokenRecord.setAppletID(appletID);
+ }
+ }
+
+ // update key info if specified
+ String keyInfo = tokenData.getKeyInfo();
+ if (keyInfo != null) {
+ if (keyInfo.equals("")) { // remove value if empty
+ tokenRecord.setKeyInfo(null);
+ } else { // otherwise replace value
+ tokenRecord.setKeyInfo(keyInfo);
+ }
+ }
+
+ // update policy if specified
+ String policy = tokenData.getPolicy();
+ if (policy != null) {
+ if (policy.equals("")) { // remove value if empty
+ tokenRecord.setPolicy(null);
+ } else { //otherwise replace value
+ tokenRecord.setPolicy(policy);
+ }
+ }
+
+ database.updateRecord(tokenID, tokenRecord);
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
+ ipAddress, msg, "success", remoteUser);
+
+ tokenData = createTokenData(database.getRecord(tokenID));
+
+ return createOKResponse(tokenData);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
+ ipAddress, msg, "failure",
+ remoteUser);
+ msg = msg + ":" + e;
+
+ throw new PKIException(msg);
+ }
+ }
+
+ @Override
+ public Response changeTokenStatus(String tokenID, TokenStatus tokenStatus) {
+
+ if (tokenID == null) throw new BadRequestException("Token ID is null.");
+ if (tokenStatus == null) throw new BadRequestException("Token state is null.");
+
+ CMS.debug("TokenService.changeTokenStatus(\"" + tokenID + "\", \"" + tokenStatus + "\")");
+
+ String remoteUser = servletRequest.getRemoteUser();
+ String ipAddress = servletRequest.getRemoteAddr();
+
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TokenRecord tokenRecord = null;
+ String msg = "";
+ try {
+ TokenDatabase database = subsystem.getTokenDatabase();
+
+ tokenRecord = database.getRecord(tokenID);
+ TokenStatus currentTokenStatus = getTokenStatus(tokenRecord);
+ CMS.debug("TokenService.changeTokenStatus(): current status: " + currentTokenStatus);
+ msg = "change token status from " + currentTokenStatus + " to " + tokenStatus;
+
+ // make sure transition is allowed
+ Collection<TokenStatus> nextStatuses = transitions.get(currentTokenStatus);
+ CMS.debug("TokenService.changeTokenStatus(): allowed next statuses: " + nextStatuses);
+ if (nextStatuses == null || !nextStatuses.contains(tokenStatus)) {
+ CMS.debug("TokenService.changeTokenStatus(): next status not allowed: " + tokenStatus);
+ msg = msg + ": Invalid token status transition";
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
+ ipAddress, msg,
+ "failure",
+ remoteUser);
+ throw new BadRequestException(msg);
+ }
+
+ CMS.debug("TokenService.changeTokenStatus(): next status allowed: " + tokenStatus);
+ setTokenStatus(tokenRecord, tokenStatus);
+ database.updateRecord(tokenID, tokenRecord);
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
+ ipAddress, msg, "success",
+ remoteUser);
+
+ TokenData tokenData = createTokenData(database.getRecord(tokenID));
+
+ return createOKResponse(tokenData);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ msg = msg + e;
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DO_TOKEN, tokenRecord,
+ ipAddress, msg, "failure",
+ remoteUser);
+
+ throw new PKIException(msg);
+ }
+ }
+
+ @Override
+ public Response removeToken(String tokenID) {
+
+ if (tokenID == null) throw new BadRequestException("Token ID is null.");
+
+ CMS.debug("TokenService.removeToken(\"" + tokenID + "\")");
+
+ String remoteUser = servletRequest.getRemoteUser();
+ String ipAddress = servletRequest.getRemoteAddr();
+
+ TPSSubsystem subsystem = (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
+ TokenRecord tokenRecord = null;
+ String msg = "remove token";
+ try {
+ TokenDatabase database = subsystem.getTokenDatabase();
+ tokenRecord = database.getRecord(tokenID);
+ database.removeRecord(tokenID);
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DELETE, tokenRecord,
+ ipAddress, msg, "success", remoteUser);
+
+ return createNoContentResponse();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ subsystem.tdb.tdbActivity(ActivityDatabase.OP_DELETE, tokenRecord,
+ ipAddress, msg, "failure",
+ remoteUser);
+ msg = msg + ":" + e;
+
+ throw new PKIException(msg);
+ }
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/selftests/TPSPresence.java b/base/tps/src/org/dogtagpki/server/tps/selftests/TPSPresence.java
new file mode 100644
index 000000000..65ac197e7
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/selftests/TPSPresence.java
@@ -0,0 +1,187 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.selftests;
+
+import java.security.PublicKey;
+import java.util.Locale;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.selftests.EDuplicateSelfTestException;
+import com.netscape.certsrv.selftests.EInvalidSelfTestException;
+import com.netscape.certsrv.selftests.EMissingSelfTestException;
+import com.netscape.certsrv.selftests.ESelfTestException;
+import com.netscape.certsrv.selftests.ISelfTestSubsystem;
+import com.netscape.cms.selftests.ASelfTest;
+
+/**
+ * This class implements a self test to check for TPS presence.
+ * <P>
+ *
+ * @author alee
+ * @version $Revision$, $Date$
+ */
+public class TPSPresence extends ASelfTest {
+
+ public static final String PROP_TPS_SUB_ID = "TpsSubId";
+ private String tpsSubId = null;
+
+ /**
+ * Initializes this subsystem with the configuration store
+ * associated with this instance name.
+ * <P>
+ *
+ * @param subsystem the associated subsystem
+ * @param instanceName the name of this self test instance
+ * @param parameters configuration store (self test parameters)
+ * @exception EDuplicateSelfTestException subsystem has duplicate name/value
+ * @exception EInvalidSelfTestException subsystem has invalid name/value
+ * @exception EMissingSelfTestException subsystem has missing name/value
+ */
+ public void initSelfTest(ISelfTestSubsystem subsystem, String instanceName,
+ IConfigStore parameters) throws EDuplicateSelfTestException, EInvalidSelfTestException,
+ EMissingSelfTestException {
+ super.initSelfTest(subsystem, instanceName, parameters);
+
+ try {
+ tpsSubId = mConfig.getString(PROP_TPS_SUB_ID);
+ if (tpsSubId != null) {
+ tpsSubId = tpsSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_VALUES", getSelfTestName(),
+ mPrefix + "." + PROP_TPS_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_TPS_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_NAME", getSelfTestName(),
+ mPrefix + "." + PROP_TPS_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix, PROP_TPS_SUB_ID, null);
+ }
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest() throws ESelfTestException {
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ }
+
+ /**
+ * Returns the name associated with this self test. This method may
+ * return null if the self test has not been initialized.
+ * <P>
+ *
+ * @return instanceName of this self test
+ */
+ public String getSelfTestName() {
+ return super.getSelfTestName();
+ }
+
+ /**
+ * Returns the root configuration storage (self test parameters)
+ * associated with this subsystem.
+ * <P>
+ *
+ * @return configuration store (self test parameters) of this subsystem
+ */
+ public IConfigStore getSelfTestConfigStore() {
+ return super.getSelfTestConfigStore();
+ }
+
+ /**
+ * Retrieves description associated with an individual self test.
+ * This method may return null.
+ * <P>
+ *
+ * @param locale locale of the client that requests the description
+ * @return description of self test
+ */
+ public String getSelfTestDescription(Locale locale) {
+ return CMS.getUserMessage(locale,
+ "CMS_SELFTESTS_TPS_PRESENCE_DESCRIPTION");
+ }
+
+ /**
+ * Execute an individual self test.
+ * <P>
+ *
+ * @param logger specifies logging subsystem
+ * @exception ESelfTestException self test exception
+ */
+ public void runSelfTest(ILogEventListener logger)
+ throws ESelfTestException {
+ String logMessage = null;
+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(tpsSubId);
+ if (tps == null) {
+ // log that the TPS is not installed
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_PRESENT", getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the TPS certificate
+ org.mozilla.jss.crypto.X509Certificate tpsCert = null;
+ try {
+ tpsCert = tps.getSubsystemCert();
+ } catch (Exception e) {
+ e.printStackTrace();
+ // cert does not exist or is not yet configured
+ // tpsCert will remain null
+ }
+
+ if (tpsCert == null) {
+ // log that the TPS is not yet initialized
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_INITIALIZED",
+ getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the TPS certificate public key
+ PublicKey tpsPubKey = tpsCert.getPublicKey();
+ if (tpsPubKey == null) {
+ // log that something is seriously wrong with the TPS
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_CORRUPT", getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ }
+
+ // log that the TPS is present
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_PRESENT", getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ }
+}
diff --git a/base/tps/src/org/dogtagpki/server/tps/selftests/TPSValidity.java b/base/tps/src/org/dogtagpki/server/tps/selftests/TPSValidity.java
new file mode 100644
index 000000000..f140d6e7c
--- /dev/null
+++ b/base/tps/src/org/dogtagpki/server/tps/selftests/TPSValidity.java
@@ -0,0 +1,197 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2013 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.tps.selftests;
+
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.util.Locale;
+
+import netscape.security.x509.X509CertImpl;
+
+import org.dogtagpki.server.tps.TPSSubsystem;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.logging.ILogEventListener;
+import com.netscape.certsrv.selftests.EDuplicateSelfTestException;
+import com.netscape.certsrv.selftests.EInvalidSelfTestException;
+import com.netscape.certsrv.selftests.EMissingSelfTestException;
+import com.netscape.certsrv.selftests.ESelfTestException;
+import com.netscape.certsrv.selftests.ISelfTestSubsystem;
+import com.netscape.cms.selftests.ASelfTest;
+
+/**
+ * This class implements a self test to check the validity of the TPS.
+ * <P>
+ *
+ * @author alee
+ * @version $Revision$, $Date$
+ */
+public class TPSValidity extends ASelfTest {
+
+ // parameter information
+ public static final String PROP_TPS_SUB_ID = "TpsSubId";
+ private String tpsSubId = null;
+
+ /**
+ * Initializes this subsystem with the configuration store
+ * associated with this instance name.
+ * <P>
+ *
+ * @param subsystem the associated subsystem
+ * @param instanceName the name of this self test instance
+ * @param parameters configuration store (self test parameters)
+ * @exception EDuplicateSelfTestException subsystem has duplicate name/value
+ * @exception EInvalidSelfTestException subsystem has invalid name/value
+ * @exception EMissingSelfTestException subsystem has missing name/value
+ */
+ public void initSelfTest(ISelfTestSubsystem subsystem, String instanceName,
+ IConfigStore parameters) throws EDuplicateSelfTestException,
+ EInvalidSelfTestException, EMissingSelfTestException {
+ super.initSelfTest(subsystem, instanceName, parameters);
+
+ try {
+ tpsSubId = mConfig.getString(PROP_TPS_SUB_ID);
+ if (tpsSubId != null) {
+ tpsSubId = tpsSubId.trim();
+ } else {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_VALUES", getSelfTestName(),
+ mPrefix + "." + PROP_TPS_SUB_ID));
+
+ throw new EMissingSelfTestException(PROP_TPS_SUB_ID);
+ }
+ } catch (EBaseException e) {
+ mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(),
+ CMS.getLogMessage("SELFTESTS_MISSING_NAME", getSelfTestName(),
+ mPrefix + "." + PROP_TPS_SUB_ID));
+
+ throw new EMissingSelfTestException(mPrefix, PROP_TPS_SUB_ID, null);
+ }
+ }
+
+ /**
+ * Notifies this subsystem if it is in execution mode.
+ * <P>
+ *
+ * @exception ESelfTestException failed to start
+ */
+ public void startupSelfTest() throws ESelfTestException {
+ }
+
+ /**
+ * Stops this subsystem. The subsystem may call shutdownSelfTest
+ * anytime after initialization.
+ * <P>
+ */
+ public void shutdownSelfTest() {
+ }
+
+ /**
+ * Returns the name associated with this self test. This method may
+ * return null if the self test has not been intialized.
+ * <P>
+ *
+ * @return instanceName of this self test
+ */
+ public String getSelfTestName() {
+ return super.getSelfTestName();
+ }
+
+ /**
+ * Returns the root configuration storage (self test parameters)
+ * associated with this subsystem.
+ * <P>
+ *
+ * @return configuration store (self test parameters) of this subsystem
+ */
+ public IConfigStore getSelfTestConfigStore() {
+ return super.getSelfTestConfigStore();
+ }
+
+ /**
+ * Retrieves description associated with an individual self test.
+ * This method may return null.
+ * <P>
+ *
+ * @param locale locale of the client that requests the description
+ * @return description of self test
+ */
+ public String getSelfTestDescription(Locale locale) {
+ return CMS.getUserMessage(locale,
+ "CMS_SELFTESTS_TPS_VALIDITY_DESCRIPTION");
+ }
+
+ /**
+ * Execute an individual self test.
+ * <P>
+ *
+ * @param logger specifies logging subsystem
+ * @exception ESelfTestException self test exception
+ */
+ public void runSelfTest(ILogEventListener logger)
+ throws ESelfTestException {
+ String logMessage = null;
+ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(tpsSubId);
+
+ if (tps == null) {
+ // log that the TPS is not installed
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_PRESENT", getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Retrieve the TPS subsystem certificate
+ X509CertImpl tpsCert = null;
+ try {
+ tpsCert = new X509CertImpl(tps.getSubsystemCert().getEncoded());
+ } catch (Exception e) {
+ // certificate is not present or has not been configured
+ // tpsCert will remain null
+ }
+
+ if (tpsCert == null) {
+ // log that the TPS is not yet initialized
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_INITIALIZED",
+ getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ }
+
+ // Check the TPS validity period
+ try {
+ tpsCert.checkValidity();
+ } catch (CertificateNotYetValidException e) {
+ // log that the TPS is not yet valid
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_NOT_YET_VALID", getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ } catch (CertificateExpiredException e) {
+ // log that the TPS is expired
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_EXPIRED", getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ throw new ESelfTestException(logMessage);
+ }
+
+ // log that the TPS is valid
+ logMessage = CMS.getLogMessage("SELFTESTS_TPS_IS_VALID", getSelfTestName());
+ mSelfTestSubsystem.log(logger, logMessage);
+ }
+}
diff --git a/base/tps/src/pki-tps.mf b/base/tps/src/pki-tps.mf
new file mode 100644
index 000000000..d77fe8fa9
--- /dev/null
+++ b/base/tps/src/pki-tps.mf
@@ -0,0 +1,3 @@
+Name: pki-tps
+Specification-Version: ${APPLICATION_VERSION}
+Implementation-Version: ${VERSION}